Skip to main content

Deployment

Four independently deployable pieces: API (Workers), Web (Pages), Docs (Pages), and Mobile (EAS Build). All triggered from the same GitHub repo.

What deploys where

API — Cloudflare Workers

  • Workflow: .github/workflows/cd.ymldeploy-api job.

  • Order per deploy: run migrations → build → wrangler deploy.

  • Config: apps/api/wrangler.toml (bindings, compat date, vars).

  • Secrets (Cloudflare secret store, set with wrangler secret put <NAME> — see secrets): SESSION_SECRET, PII_ENCRYPTION_KEY, INFINIA_API_USERNAME, INFINIA_API_PASSWORD, INFINIA_WEBHOOK_SECRET, NEON_DB_URL.

  • Public vars (in wrangler.toml [vars]): APPLE_BUNDLE_ID, GOOGLE_OAUTH_CLIENT_ID, INFINIA_COMPANY_ID, INFINIA_BASE_URL.

  • Bindings: HYPERDRIVE (id in wrangler.toml).

  • Neon region: pinned to an EU region — see privacy for the why.

  • Manual deploy from your machine:

    pnpm --filter @gringo-pay/api exec wrangler deploy

Web — Cloudflare Pages

  • Workflow: .github/workflows/cd.ymldeploy-web job.
  • Project name: gringo-pay-web (must match Cloudflare Pages project).
  • Build output: apps/web/dist.

Docs — Cloudflare Pages

  • Workflow: .github/workflows/docs.yml.
  • Project name: gringo-pay-docs (must match a Cloudflare Pages project).
  • URL: gringo-pay-docs.pages.dev (default; add a custom domain via the Cloudflare dashboard when ready).
  • One-time setup: create the Pages project in the Cloudflare dashboard (Pages → Create → Direct Upload → name it gringo-pay-docs). No repo settings to change.

Mobile — EAS

  • Workflow: .github/workflows/cd.ymlbuild-mobile job.
  • Currently only iOS preview builds. Android is not wired up yet.
  • Requires EXPO_TOKEN (Expo access token).
  • Distribution is via internal preview channel — no app store submission automated yet.

Mobile-specific config to set at build time:

  • EXPO_PUBLIC_API_BASE_URL — deployed API URL.
  • EXPO_PUBLIC_APPLE_BUNDLE_ID — must match the APPLE_BUNDLE_ID on the API side (used as aud when verifying Apple ID tokens).
  • EXPO_PUBLIC_GOOGLE_OAUTH_CLIENT_ID — same for Google.

Required GitHub secrets

SecretUsed byPurpose
CLOUDFLARE_API_TOKENCD (api + web)Deploy to Workers + Pages
CLOUDFLARE_ACCOUNT_IDCD (api + web)Cloudflare account
DATABASE_URLCD (api migrations)Neon Postgres for drizzle-kit migrate
EXPO_TOKENCD (mobile)EAS Build authentication
TURBO_TOKENCI + CD (optional)Turborepo remote cache
TURBO_TEAMCI + CD (optional)Turborepo team slug

First production deploy — pre-flight

Before the API can serve real users, all of these must be true (see also privacy pre-production checklist):

  • Infinia production credentials issued; INFINIA_BASE_URL set to Infinia's production hostname
  • Infinia HOSTED KYC widget branding option confirmed
  • Infinia UK / EU custodial licensing confirmed for our user population
  • DPAs signed with Infinia, Cloudflare, Neon
  • Apple + Google OAuth client IDs created; bundle id / client id set as env vars
  • SESSION_SECRET and PII_ENCRYPTION_KEY generated (32+ bytes each) and set via wrangler secret put
  • pgcrypto extension enabled on the production Neon database
  • Nightly reconciliation cron and retention cron scheduled
  • Privacy policy published on the marketing site
  • INFINIA_WEBHOOK_SECRET registered as the callback_url on every Infinia resource type we create
  • Observability tooling picked and wired up (architecture/observability) — edge SLIs emitting, page-worthy alerts firing to on-call, runbooks landed for each alert (ops/runbooks)
  • GET /health liveness probe monitored externally from ≥ 2 regions

Rollback

  • API: wrangler rollback — Cloudflare keeps recent versions.
  • Web: re-deploy a previous git SHA via workflow_dispatch.
  • Docs: re-deploy a previous git SHA via workflow_dispatch on docs.yml, or roll back via the Cloudflare Pages dashboard.
  • Mobile: re-run EAS Build on a prior SHA. Users need to install the new build.

Environments

Currently one environment: production. Infinia sandbox credentials + a dev Neon branch are used for local dev; there is no separately-deployed staging tier. Staging is a candidate for Phase 1.5 once we have real user volume to protect.