Deploys

Going live is single command. Goribu builds your app, sets up the Cloudflare resources it needs, and publishes it. You can also check what will change before anything does.

updated in 0.9.4
On this page

Log in to Cloudflare

Goribu deploys your app as a Cloudflare Worker (Cloudflare Workers), using Cloudflare's Wrangler tool, which comes installed with Goribu. You need a Cloudflare account, free or paid, to go live. Log in once from the app directory:

Terminal
pnpm exec goribu cloudflare-login
  • What it does: Opens your browser to authorize Goribu's Wrangler, then remembers the login for later deploys.
  • CI or a server: Set CLOUDFLARE_API_TOKEN instead. Create the token from the "Edit Cloudflare Workers" template. A custom domain also needs Zone Read for that domain.
  • Several accounts: If your login can reach more than one Cloudflare account, set CLOUDFLARE_ACCOUNT_ID in your shell to choose one.
  • Only for deploys: pnpm dev and pnpm build don't need a login.
  • Other Wrangler commands: Wrangler isn't on your PATH, so run it as pnpm exec goribu wrangler <args>. It uses the same account as deploy. goribu wrangler deploy is refused, because it would skip Goribu's build, resource setup, and migrations.

Check before you deploy

Run these before deploying a change:

Terminal
pnpm typecheck
pnpm build
pnpm check
Terminal
pnpm build
pnpm check
  • pnpm typecheck: TypeScript apps only.
  • pnpm build: Catches build errors and lists which pages are prerendered.
  • pnpm check: Shows what deploy would do, without changing anything: the Worker name, which resources will be created or reused, pending D1 migrations, domain changes, and whether production secrets will be uploaded. It never prints secret values, and doesn't inspect Postgres yet. Bindings from a wrangler block are listed separately, as not inspected or managed by Goribu.

A passing check doesn't prove your login can deploy; an app with no resources may not contact Cloudflare at all. Deploy checks your login itself before it builds.

Deploy

Terminal
pnpm run deploy

Use pnpm run deploy as a plain pnpm deploy is a different pnpm command. Deploy goes straight to production as there is no staging step. Run the same command for every release.

Each deploy runs these steps in order and stops at the first failure:

  1. Checks your config and Cloudflare login.
  2. Builds the app.
  3. Validates .env.production, if you have one (production secrets).
  4. Creates or reuses your declared D1 database, KV namespace and R2 buckets, or the Postgres connection.
  5. Applies pending database migrations.
  6. Uploads the Worker, static files, and secrets.
  7. Connects your custom domain, if you set one.
  • Your app's address: Wrangler prints it at the end: the workers.dev address, plus your domain if configured.
  • Data is kept: Deploying never deletes resources or their data and local development data is never copied to production.
  • After deploying: Open the live app and try the pages and forms you changed, especially anything that touches the database.

Schema changes

Migrations run before the new Worker is uploaded, while the old version is still serving visitors. So each migration must keep working with the old code.

Make breaking changes in steps: add new tables or nullable columns first, deploy code that uses them, then remove the old columns in a later release. Don't ship the addition and the removal in the same deploy.

  • A failed migration: Stops the deploy before the new Worker is uploaded. Migrations that already succeeded and resources already created stay in place.
  • Migrating ahead of time: Run pnpm exec goribu migrate --remote to apply a schema change before deploying. The next deploy finds nothing pending.

See migrations for D1 or Postgres for writing them.

Which requests run the Worker

In production, your Worker only runs for URLs that one of your routes can answer. Everything else, such as prerendered pages, images and bots probing /wp-login.php, is served by Cloudflare's static assets without running your code. This keeps requests fast and Worker usage low without anything to configure.

  • Unknown URLs: Get your app's 404 page straight from static assets.
  • Dynamic segments: A route such as /posts/[id] sends everything under /posts/ to the Worker, including /posts/42/wp-login.php, which still gets your 404 page.
  • Catch-all at the root: A route such as src/routes/[slug].tsxsrc/routes/[slug].jsx matches every URL, so every unknown URL runs the Worker. The build warns about this and it's recommended to put such routes under a prefix, such as /blog/[slug], when you can.
  • Rule limit: The build turns your Worker routes into Cloudflare routing rules for you, plus one exception for each static file under a dynamic route, such as public/posts/feed.xml under /posts/[id]. Cloudflare allows 100 rules, so if the build reports too many, group dynamic routes under shared prefixes or move those static files elsewhere.
  • Development: pnpm dev runs the Worker for every request so data and changes are always fresh.

Live logs

To see what's happening in production, such as errors after a deploy, stream live requests from your Worker:

Terminal
pnpm exec goribu tail
Example output
GET https://app.example.com/hello - 200 OK @ 2026-10-02T10:30:00.000Z
GET https://app.example.com/missing - 404 Not Found @ 2026-10-02T10:30:01.000Z
GET https://app.example.com/boom - 500 Internal Server Error @ 2026-10-02T10:30:02.000Z
  • What you see: Each request's status, followed by its console output and errors. Failures in background work after a response appear as separate lines, such as [Worker outcome: exception].
  • What you don't: Prerendered pages, static files, and unknown URLs never run the Worker, so they don't show up.
  • Live only: You see requests from now on, from all visitors, not past logs. Press Ctrl+C to stop.

If deployment fails

Read the first error; it names the step that failed and how to fix it. Then run pnpm run deploy again. A failed deploy always exits with an error and never reports success.

  • Login problems: Run pnpm exec goribu cloudflare-login again, or fix your API token, then retry. Deploy never starts a login on its own.
  • Domain problems: If connecting the domain fails, the new Worker is already live at its other addresses. Fix the reported conflict and deploy again.
  • Build output: Production files are written to .goribu/dist/. Like .wrangler/ and goribu.wrangler.jsonc, it's generated on every build, so don't edit or commit it.