pnpm deploy

One command, many hosts. Deploys the backend (Convex apps), builds the SPA, writes the provider's SPA fallback, ships the files, and syncs auth config — idempotently.

pnpm deploy <slug>                    # remembered provider, or cloudflare by default
pnpm deploy <slug> --to vercel        # cloudflare | vercel | netlify | surge | heroku | github-pages
pnpm deploy <slug> --dry-run          # plan + build, no network deploys
pnpm deploy <slug> --json             # final @geenius-mvp:result line
pnpm deploy --providers               # login status for all 6 providers

The 6 providers

  • cloudflare (default) — Cloudflare Pages; project created on first deploy; url https://<name>.pages.dev; SPA fallback via the template's public/_redirects
  • vercel — writes vercel.json with a rewrite of every route to /index.html
  • netlify — writes a _redirects file (/* /index.html 200)
  • surge — copies index.html to 200.html (Surge's SPA fallback); url https://<name>.surge.sh
  • heroku — static buildpack via the Build API; needs the Heroku CLI installed; SPA routing via static.json
  • github-pages — pushes a gh-pages branch (needs the gh CLI); copies index.html to 404.html and writes .nojekyll; url https://<owner>.github.io/<name>/

The remote project name is geenius-mvp-<slug> (override the prefix with the DEPLOY_PREFIX env var).

Login handling

Each provider is probed before deploying. If you are not logged in, its official login flow launches interactively, then the deploy proceeds. If a provider's CLI is missing (heroku, gh), the error says so and suggests --to another provider.

Convex backend first

  • Requires apps/<slug>/.env.local (run npx convex dev --once first) — this guard prevents minting a duplicate cloud project
  • Runs convex dev --once then convex deploy -y against the recorded project; never duplicates
  • Generates BETTER_AUTH_SECRET on prod if missing (preserved on redeploys)
  • Writes .env.production with VITE_CONVEX_URL + VITE_CONVEX_SITE_URL, then builds the SPA against prod
  • After the frontend lands, SITE_URL is set on the prod deployment to the real URL, so sign-in works on the deployed origin

Supabase apps need apps/<slug>/.env.production (copy .env.example and fill in the keys) before deploying. Static-stack apps deploy their files as-is — no build.

Deploy memory

The chosen provider and live URL are remembered in apps/<slug>/.deploy.json. Next time, plain pnpm deploy <slug> reuses them. With --json the final line is:

@geenius-mvp:result {"ok":true,"slug":"my-idea","provider":"cloudflare","url":"https://geenius-mvp-my-idea.pages.dev","backend":"https://brave-otter-123.convex.cloud"}