Saltar al contenido principal

Deployment

AI Supreme Council is deployed as static files on Cloudflare Pages with API logic running on Cloudflare Workers. A unified deploy script handles all targets.

Deployment Targets

TargetURLTypeCommand
Appaiscouncil.comCF Pages (static)scripts/deploy.sh pages
Stagingaiscouncil.netCF Pages (static)scripts/deploy.sh pages-staging
API Workerapi.aiscouncil.comCF Workerscripts/deploy.sh worker
Auth Workerauth.aiscouncil.comCF Workerscripts/deploy.sh worker-auth
App Storestore.aiscouncil.comCF Pages (static)scripts/deploy.sh store
AllEverything aboveAllscripts/deploy.sh all

Environment Variables

Export these in ~/.bashrc (never commit them):

export CF_ACCOUNT_ID_AISCOUNCIL="your-cloudflare-account-id"
export CF_PAGES_TOKEN_AISCOUNCIL="your-pages-api-token"
export CF_WORKER_TOKEN_AISCOUNCIL="your-worker-api-token"

Optional overrides:

export CF_PAGES_PROJECT_AISCOUNCIL="aiscouncil"              # default
export CF_PAGES_PROJECT_AISCOUNCIL_STAGING="aiscouncil-staging" # default
aviso

These tokens grant deploy access to your Cloudflare account. Never commit them to the repository. The deploy script will exit with an error if required variables are missing.

Pages Deployment (Production)

Step-by-Step

  1. Assemble the app from source:
./build.sh
  1. Deploy to production:
scripts/deploy.sh pages

This command:

  • Creates a clean _deploy/ directory
  • Copies static files via rsync, excluding development artifacts
  • Minifies index.html with html-minifier-terser (~40% size reduction)
  • Deploys to Cloudflare Pages with --branch=main
  • Cleans up _deploy/
info

Production deploys always use --branch=main. This is required for CF Pages to serve on the production domain (aiscouncil.com).

What Gets Deployed

The rsync step excludes everything that is not a browser-facing asset:

Excluded directories: src/, tools/, kernel/, serve/, worker/, worker-auth/, doc.aiscouncil.com/, node_modules/, .git/, .github/, .carl/, .claude/, modules/, scripts/, core-types/, bridge/, i18n/, dist/, build/

Excluded file types: *.py, *.zig, *.zon, *.md, *.sh, *.css, .env*

Excluded config files: package.json, package-lock.json, vitest.config.*, tsconfig.json, .cfignore, .gitignore

What remains are the production assets: index.html, sw.js, icons, manifest.webmanifest, registry/ JSON files, sdk/, ads.json, sitemap.xml, and any mini-program or app directories.

Minification

Production deploys pass index.html through html-minifier-terser with these options:

  • Collapse whitespace
  • Remove comments
  • Remove redundant attributes
  • Collapse boolean attributes
  • Minify inline CSS
  • Minify inline JavaScript

Typical size reduction is ~40% (e.g., 980 KB down to ~580 KB).

Staging Deployment

Deploy to the staging environment without minification:

scripts/deploy.sh pages-staging

Staging is served from aiscouncil.net. The app auto-detects its domain at runtime and adjusts API URLs, cookie domains, and cross-origin references accordingly.

Promoting Staging to Production

After validating on staging, promote the same build to production:

scripts/deploy.sh promote

This redeploys the current code to the production Pages project with minification enabled. The app code is identical -- only the domain changes.

Worker Deployment

API Worker

scripts/deploy.sh worker

This runs npx wrangler deploy inside the worker/ directory using the account ID and Worker token from your environment.

Auth Worker

scripts/deploy.sh worker-auth

Same process for the worker-auth/ directory.

Worker Secrets

Workers require secrets that are set separately from code deploys. Use wrangler secret put from the worker directory:

cd worker
npx wrangler secret put JWT_SECRET
npx wrangler secret put STRIPE_SECRET_KEY
npx wrangler secret put STRIPE_WEBHOOK_SECRET
npx wrangler secret put WEBHOOK_PATH_SECRET
cd worker-auth
npx wrangler secret put JWT_SECRET
npx wrangler secret put GOOGLE_CLIENT_SECRET
npx wrangler secret put APPLE_CLIENT_SECRET
npx wrangler secret put GITHUB_CLIENT_SECRET
tip

Secrets persist across deploys. You only need to set them once, or when rotating credentials.

Worker Configuration

Each worker has a wrangler.toml that defines:

  • Worker name and routes
  • KV namespace bindings
  • Environment variable references
  • Compatibility settings

Service Worker Cache

The client-side Service Worker (sw.js) uses a versioned cache:

const CACHE = 'ais-v1.0.0';

When to bump the cache version:

  • Breaking changes to the app shell (HTML structure, critical CSS)
  • Changes to precached assets (icons, manifest)
  • Major version releases

Bumping the version causes the Service Worker to:

  1. Create a new cache with the new name
  2. Precache all listed assets
  3. Delete all old caches on activation
aviso

Forgetting to bump the cache version after breaking changes will cause users to see stale content until they manually clear their browser cache or the old Service Worker expires.

Deploy Everything

Deploy the Pages app, API worker, and auth worker in sequence:

scripts/deploy.sh all

Post-Deploy Verification

After deploying, verify the app is serving correctly:

# Check production
curl -s https://aiscouncil.com/ | head -5

# Check API health
curl -s https://api.aiscouncil.com/health

# Check auth health
curl -s https://auth.aiscouncil.com/health
info

Cloudflare Pages auto-invalidates its CDN cache on deploy, but propagation may take 1-2 minutes globally. If you see stale content, wait briefly and try again.

Domain Architecture

The app uses domain detection at runtime to support both production and staging:

DomainConstantProductionStaging
AppAIS.DOMAINaiscouncil.comaiscouncil.net
MarketingAIS.WWWwww.aiscouncil.comwww.aiscouncil.net
APIAPI_BASEhttps://api.aiscouncil.com/v1https://api.aiscouncil.net/v1
AuthAUTH_BASEhttps://auth.aiscouncil.com/v1https://auth.aiscouncil.net/v1
DocsAIS.DOC_BASEhttps://doc.aiscouncil.comhttps://doc.aiscouncil.net
StoreAIS.STORE_URLhttps://store.aiscouncil.comhttps://store.aiscouncil.net

API base URLs can also be overridden via localStorage for local development:

localStorage.setItem('ais-api-base', 'http://localhost:8787/v1');
localStorage.setItem('ais-auth-base', 'http://localhost:8788/v1');

Local Development

For local development without deploying:

  1. Build the app: ./build.sh
  2. Serve index.html with any static file server (e.g., python3 -m http.server 8080)
  3. Run Workers locally with Wrangler:
cd worker && npx wrangler dev
cd worker-auth && npx wrangler dev --port 8788
  1. Override API base URLs in the browser console:
localStorage.setItem('ais-api-base', 'http://localhost:8787/v1');
localStorage.setItem('ais-auth-base', 'http://localhost:8788/v1');
location.reload();