Architecture Overview

How identity, billing, and inference flow through the Xcity stack.

Xcity’s stack has three planes — identity, billing, and inference — that any product on the platform composes against.

                ┌────────────────────────────────────────────┐
   Browser  →   │  xcity-home (Astro, *.xcity.one)           │
                │   ├── /api/auth/*     identity BFF         │
                │   ├── /api/billing/*  Stripe BFF           │
                │   └── /api/me/*       plan / key resolver  │
                └──────┬───────────┬────────────────┬────────┘
                       │           │                │
                       ▼           ▼                ▼
                  GoTrue       Stripe          LiteLLM
                (auth.xcity)   (billing)     (tokenhub.xcity)


                                              Solar Compute (AR)

Identity plane

Authentication is centralized on auth.xcity.one (a self-hosted GoTrue instance with Supabase as a dev fallback). The xcity-home Astro app issues a host-only, SameSite=Lax session cookie scoped to *.xcity.one. Every browser sub-product on a .xcity.one subdomain inherits that session by hitting xcity-home BFF endpoints with credentials: 'include'.

See Sub-product Integration for the integration recipe.

Billing plane

Stripe is the source of truth for plans, subscriptions, and invoices. The xcity-home server holds the only set of Stripe credentials; sub-products never call Stripe directly. Plan and entitlement state is mirrored onto each user’s GoTrue app_metadata via Stripe webhooks landing at /api/billing/webhook.

See Billing model and the Stripe webhook reference.

Inference plane

tokenhub.xcity.one runs LiteLLM in front of one or more upstream model providers and our own self-hosted models. Every API key is bound to a Xcity account, a plan whitelist, and a budget cap. Requests are logged for the usage ledger that drives /dashboard/usage and overage billing.

Sub-products

Anything that lives on a *.xcity.one subdomain (xct-chat, xct-flow, xct-agent-marketplace, future ones) integrates via three BFF endpoints and never holds its own Stripe or auth credentials:

EndpointReturns
GET /api/auth/meCurrent user
GET /api/me/litellm-keyBearer + plan + allowed models
GET /api/billing/planPlan id, entitlements, renewal

CORS is enforced via a regex allowlist over *.xcity.one plus localhost for development; see src/lib/cors.ts.

Where data lives

DomainStoreRegion
User identityGoTrue PostgresSan Juan, AR (primary)
SubscriptionsStripeGlobal (US)
API usageLiteLLM PostgresSan Juan, AR
Audit logsObject storageSan Juan + DR

Enterprise contracts can pin a region or require an on-prem-style deployment — see Enterprise: Data Residency.

Last updated: