Skip to content

Deploy & ops ​

Run Gommo Developer as a single API service. Docs (VitePress) and the dev portal deploy separately.

Suggested layout ​

ServiceDomainHow
APIapi.yourdomain.comDocker / Railway / Fly
Docsdocs.yourdomain.comVitePress static — Vercel or GitHub Pages
Portal/portal/ on API (dev only)Off in prod unless GATEWAY_PORTAL=true

Never commit .env, GOMMO_ACCESS_TOKEN, or ADMIN_API_KEY — use platform secrets.

Local development ​

bash
cp .env.example .env
npm install
npm run dev            # API :3001
npm run docs:dev       # Docs :5173

Optional portal static serve: npm run portal:dev → :5180.

Verify:

bash
curl http://localhost:3001/health

Health check ​

http
GET /health

Example response:

json
{
  "success": true,
  "data": {
    "ok": true,
    "merchantConfigured": true,
    "adminConfigured": true
  }
}

Use /health for Railway, Fly, Kubernetes, and load balancer probes.

Configure platforms:

PlatformSetting
RailwayHealth check path /health
Fly.ioHTTP check in fly.toml → GET /health
Docker / k8sLiveness probe on /health

Docker ​

bash
docker build -t gommo-developer .
docker run --rm -p 3001:3001 --env-file .env gommo-developer

Image runs node dist/index.js after npm run build. Platform injects PORT — gateway reads process.env.PORT.

Self-host API modes (advanced) ​

Optional Mode B (/gateway/* JSON REST, wait: true) and Mode C (path proxy to Gommo) when you run this repo as api.yourdomain.com. Not required for standard Gommo integration — production apps call Gommo public API directly (Mode A).

DocPurpose
Integration modesMode A / B / C comparison
Endpoint mapCross-mode path reference
Choosing a modeDecision tree

These pages are collapsed under Deploy in the sidebar (not listed under Models & routing). To restore default nav, re-add links in docs/.vitepress/config.ts → modelsRoutingInDocs*.

Gateway error responses (Mode B) ​

Failed /gateway/* and /billing/* calls return JSON:

json
{ "success": false, "message": "Human-readable reason", "code": "UNAUTHORIZED" }

Check !res.ok or success === false. Common codes: VALIDATION_ERROR (400), UNAUTHORIZED (401), INSUFFICIENT_CREDITS (402/503 merchant buffer), NOT_CONFIGURED (503), UPSTREAM_ERROR. Optional data / raw on upstream failures.

The OpenAI shim (POST /v1/chat/completions) uses OpenAI-style { error: { message } } instead.

Repo reference: doc/GATEWAY-ERRORS.md. Smoke: npm run gateway:smoke with API running (npm run docs:stack).

Railway ​

  1. New project → Deploy from GitHub.
  2. Railway detects Dockerfile or Nixpacks (npm run build, npm start).
  3. Variables: copy from .env.example — at minimum GOMMO_API_DOMAIN, GOMMO_ACCESS_TOKEN, ADMIN_API_KEY.
  4. Custom domain: api.yourdomain.com → CNAME to Railway URL.
  5. Health check: /health.

Fly.io ​

bash
fly launch --no-deploy
fly secrets set GOMMO_ACCESS_TOKEN=... ADMIN_API_KEY=... GOMMO_API_DOMAIN=<registration-domain>
fly secrets set GATEWAY_CORS_ORIGIN=https://your-frontend.example.com
fly deploy
fly certs add api.yourdomain.com

fly.toml includes HTTP check on GET /health.

Production environment ​

VariablePurpose
PORTInjected by platform (3001 locally)
NODE_ENVproduction — disables portal by default
GOMMO_API_DOMAINRegistration domain (see .env.example)
GOMMO_ACCESS_TOKENMerchant — server only
ADMIN_API_KEYProtects /admin/*
GATEWAY_CORS_ORIGINComma-separated browser origins
GATEWAY_PORTALtrue to enable /portal in prod (use with care)
GATEWAY_RATE_LIMIT_MAXDefault 120/min/IP for /gateway
ADMIN_RATE_LIMIT_MAXDefault 30/min/IP for /admin
BILLING_RATE_LIMIT_MAXDefault 60/min/IP for /billing
BillingDefault Gommo top-up needs no extra env; optional PayOS legacy — see Billing
BYOK_ENCRYPTION_KEYRequired when BYOK_ENABLED and NODE_ENV=production — npm run byok:generate-key
BYOK_STORE_FILEPersistent volume — see BYOK production

Full template: .env.example in repo root.

CORS in production ​

Set when browser clients call from a different origin:

env
GATEWAY_CORS_ORIGIN=https://app.example.com,https://www.example.com

Leave unset for API-only (server-side) integrations.

Portal behavior ​

EnvironmentDefault
NODE_ENV !== productionPortal on at /portal/
ProductionPortal off
GATEWAY_PORTAL=trueForce on
GATEWAY_PORTAL=falseForce off

Error monitoring ​

REST routes return structured errors:

json
{ "success": false, "message": "…", "code": "UPSTREAM_ERROR" }

Log code + path for alerts. Upstream 502 from proxy indicates Gommo connectivity issues.

Docs deploy ​

Docs are static — not served by the API process in production.

In dev, VitePress proxies /gateway, /ai, and /billing to :3001. In production there is no proxy — the site must know your API URL at build time.

VITE_GATEWAY_URL (required for production docs) ​

Set this when running npm run docs:build. It is embedded into the static bundle (not a runtime secret).

FeaturePrimary APIUses VITE_GATEWAY_URL when set
Models catalog / comparePOST https://v2.api.gommo.net/ai/models or /models/ UIOptional proxy for dev
Sign in / sign up / accountPublic auth on api.gommo.net or /login/POST /gateway/auth/login, /register, /change-password, /credits/transfer (self-host JSON)
Dashboard /app/*POST https://api.gommo.net/ai/me/billing/* on self-host
Playground embedPublic URLs in Endpoints tab{API}/portal/playground.html?embed=1 (iframe)

Dev — leave unset; VitePress proxy handles API calls on :5173.

Production build:

bash
VITE_GATEWAY_URL=https://api.yourdomain.com npm run docs:build
npm run docs:preview   # optional — serve dist locally

If unset at build time, the bundle falls back to https://api.yourdomain.com — replace that placeholder before shipping.

GitHub Pages ​

Workflow .github/workflows/docs-pages.yml builds docs/.vitepress/dist and deploys with GitHub Actions.

One-time (required before the first successful deploy):

  1. Settings → Pages → Build and deployment → Source: select GitHub Actions (not “Deploy from a branch”).
  2. If deploy fails with 404 / Ensure GitHub Pages has been enabled, Pages was not enabled yet — complete step 1, then re-run Actions → Deploy docs → Run workflow. Operator checklist: docs-pages-setup on GitHub.

Optional API URL at build time:

  1. Settings → Secrets and variables → Actions → Variables
  2. Add VITE_GATEWAY_URL = https://api.yourdomain.com (no trailing slash)

Custom domain: CNAME docs.yourdomain.com in DNS (VitePress base: '/' in docs/.vitepress/config.ts).

Push to main (paths under docs/** or the workflow file) triggers build + deploy. CI also runs npm run docs:build on every push to catch VitePress errors early.

Vercel ​

  1. Import repo on Vercel.
  2. Build: npm run docs:build · Output: docs/.vitepress/dist (see vercel.json)
  3. Environment variables: VITE_GATEWAY_URL = https://api.yourdomain.com (Production)
  4. Custom domain: docs.yourdomain.com

API side when docs are on another origin ​

API variableWhy
GATEWAY_CORS_ORIGINInclude https://docs.yourdomain.com — browser calls from catalog, login, /app/
GATEWAY_PORTAL=trueEnable /portal/playground.html for the embedded playground on /app/playground/

Example:

env
GATEWAY_CORS_ORIGIN=https://docs.yourdomain.com
GATEWAY_PORTAL=true

Local preview (dev server with hot reload): npm run docs:dev → :5173.

Ops checklist ​

  • [ ] GET /health returns 200 with expected flags
  • [ ] Secrets set on platform (not in git)
  • [ ] VITE_GATEWAY_URL set on docs build (GitHub variable or Vercel env)
  • [ ] GATEWAY_CORS_ORIGIN includes docs origin (https://docs.…)
  • [ ] GATEWAY_PORTAL=true if using /app/playground/ embed in prod
  • [ ] PayOS webhook URL registered (HTTPS) — only if using legacy /billing/topup/*
  • [ ] Merchant buffer credits sufficient for topup fulfillment
  • [ ] Rate limits appropriate for traffic

Next ​

→ Best practices · Privacy · Report feedback