Gokon handles a small but complete social event flow: create your profile, share an invite code to add friends, create events, add participants, and track RSVP states (Pending, Accepted, Declined). The iOS app keeps a local SwiftData graph so the UI stays fast while still syncing with server state.
Repositories: gokon-ios-client, gokon-server.
The app entry point sets a SwiftData model container for User, Event, and EventResponse. The main screen is a tab layout for Events, Friends, and My Profile. If no local/authenticated user exists yet, the profile tab shows the first-user creation form.
The networking layer is intentionally strict: APIClient is an actor, endpoint definitions are centralized in APIEndpoint, and typed DTOs in Networking/Models/APIModels.swift keep request/response boundaries explicit.
App auth state is stored in Keychain via AuthService and KeychainHelper (token, user UUID, invite code). That keeps credentials out of plain persisted app models.
The Flask server is set up with an app factory and split into blueprints: user, friend, event, and RSVP routes. Token auth is handled through the Authorization: Bearer ... header and looked up against the user auth token in storage.
Data modeling is relation-heavy by design: users have self-referential many-to-many friendships, events have many-to-many organizers and participants, and RSVP responses are separate rows connecting users and events with an enum status.
For local/dev deployment, I run PostgreSQL + Flask (gunicorn) + Nginx using Docker Compose, with migrations handled by Flask-Migrate/Alembic.
Instead of many client fetch calls, the app uses a single snapshot endpoint (/snapshot/<uuid>) to retrieve the full current user state: profile, friends, organized events, and participating events (including the caller’s RSVP view for those events).
SyncService orchestrates the flow, and UserRepository.syncSnapshotToSwiftData merges DTOs into existing SwiftData objects. This simplifies consistency rules in the UI and makes manual sync/pull-to-refresh straightforward.
The project currently uses server-issued bearer tokens and keychain-backed storage on device. Profile/event mutation endpoints enforce either ownership or organizer permissions server-side. Invite-code friend adds are simple by design for quick onboarding.
Photo upload is wired with multipart form-data and currently stores a placeholder URL path on the server side, with comments showing where object storage would be inserted for production.
Backend: Python 3.11, Flask, SQLAlchemy, gunicorn, PostgreSQL 16, Nginx, Docker Compose. Client: SwiftUI + SwiftData with native concurrency and typed API DTOs. The same API shape powers event creation, participant management, and RSVP updates across the app.