Skip to main content

Architecture

Overview

Closegram follows a monorepo structure managed by Turborepo. The frontend communicates with the backend exclusively through a GraphQL API, using Apollo Client for data fetching, caching, and real-time subscriptions.

Applications

AppPortStackDescription
apps/frontend-nextjs3000Next.js 14, App RouterMain web client
apps/frontend-public3002CRA, ReactAlternative/public web client
apps/backend4000Apollo Server, ExpressGraphQL API
apps/docs3003Docusaurus 3This documentation site (English/Spanish)
apps/iosSwiftUI, Apollo iOSNative iOS app

Request flow

Web Browser / iOS App

Apollo Client ←→ WebSocket (subscriptions)

GraphQL API — apps/backend (Apollo Server + Express)

Database / External Services (Firebase, Stripe, Google Cloud)

Frontend structure

The main web app (apps/frontend-nextjs) uses the Next.js App Router:

src/
app/ # Routes (App Router)
home/ # Feed page
messages/ # Chat page
profile/ # User profile
settings/ # Settings (nested routes)
coins/ # Coins & transactions
payments/ # Stripe payments
login/ # Auth
components/ # Shared UI components
page-components/ # Full-page components
hooks/ # Custom React hooks
contexts/ # React contexts (auth, theme)
apollo/ # Apollo client setup
i18n/ # Translation files
lib/ # Utilities

Backend structure

graphql/
types/ # GraphQL type definitions (one file per domain)
resolvers/ # Resolvers (one file per domain)
context/ # Auth helpers and WebSocket context
typeDefs.js # Combines all types
resolvers.js # Combines all resolvers

data-access-services/ # DB queries (one file per model)
validators/ # Input validation
constants/ # App-wide constants
utils/ # Helpers (Google Cloud, Stripe, etc.)
workers/ # Background jobs (notification.worker.js)

State management

  • Server state: Apollo Client (normalized InMemoryCache)
  • UI state: React Context (auth, theme, toasts)
  • Form state: Local component state

Authentication flow

  1. User signs in via email/password, Apple, Google, or phone OTP
  2. Firebase validates credentials and returns an ID token
  3. The token is attached to every GraphQL request via Apollo's authLink (Authorization: Bearer <token>)
  4. The backend validates the token on each request using the Firebase Admin SDK
  5. The resolved user is placed in the GraphQL context and available to all resolvers

Real-time architecture

WebSocket subscriptions handle:

  • New messages and message updates
  • Typing indicators and read receipts
  • Incoming calls and call status changes
  • New conversations

The frontend uses Apollo's GraphQLWsLink for subscriptions and HttpLink for queries/mutations. A splitLink routes each operation to the correct transport.

iOS architecture

The iOS app (apps/ios) follows MVVM + Redux + Clean Architecture. Each feature module has its own Redux Store (State + Action + Reducer), a Repository abstraction, and SwiftUI views. See the iOS App technical doc for the full breakdown.

External services

ServicePurpose
Firebase AuthIdentity and token management
Firebase Admin SDKToken verification on the backend
Firebase Cloud MessagingPush notifications (Android + Web)
Apple VoIP PushIncoming call notifications on iOS
StripePayment processing
Google Cloud VisionAutomatic image NSFW detection
Google Cloud Video IntelligenceAutomatic video NSFW detection