Typebase.

typebase-io-cli deploy

Deploy your Typebase server to the cloud with a single command.

Last updated on

The npx typebase-io-cli deploy command builds your server, pushes your database schema, and deploys everything to the cloud. Typebase supports three deployment providers:

Quick start

Deploy to your dev environment:

npx typebase-io-cli deploy dev

Deploy to production:

npx typebase-io-cli deploy prod

The first time you run this, the CLI will ask you to:

  1. Select a deployment provider (Vercel, Cloudflare, or Deno)
  2. Authenticate with the provider
  3. Select or create a project on the provider
  4. Select or create a database on Neon (if your project has a database schema)
  5. Select the account that holds your buckets (if your project has a storage.ts on Vercel or Cloudflare)

After the first deploy, the CLI remembers your choices in typebase.json, so future deploys are a single command.

What happens during deploy

When you run npx typebase-io-cli deploy, the CLI performs these steps automatically:

  1. Regenerates the types in _generated/: Runs the same logic as npx typebase-io-cli codegen, so you never have to run it by hand before deploying.
  2. Validates your TypeScript: Checks your typebase/ directory against those freshly generated types, so what gets checked is what gets built.
  3. Syncs your storage buckets: If your project has a storage.ts, runs bucket sync for the target: creates any declared bucket that doesn't exist yet, never deletes one, and makes sure the credentials cover them all. An existing bucket whose access differs from what you declared stops the deploy here.
  4. Generates server files: Builds the server code from your actions, schema, auth, env, publisher, and storage config.
  5. Transpiles to JavaScript: Converts TypeScript to JavaScript for deployment.
  6. Pushes your database schema: Syncs your Drizzle schema to your Neon database (if applicable). A change that would drop data stops here for confirmation; --skip-schema-changes-confirmation approves it in advance. In migrations mode it applies your pending migrations instead, and refuses to deploy when your schema files hold changes no migration records.
  7. Deploys the server: Uploads the built server to your chosen provider.
  8. Sets environment variables: Configures DATABASE_URL, BETTER_AUTH_SECRET, and your storage credentials on your provider. The key on the provider is always DATABASE_URL, regardless of target; each environment (dev, prod) holds its own value. Anything you declared in env.ts is your responsibility: set it with npx typebase-io-cli env <target> add <KEY> <value>, or the deployed server will refuse to boot.
  9. Saves the URL and environment variables: Writes the deployment URL to your project-root .env (TYPEBASE_APP_URL for prod, TYPEBASE_APP_URL_DEV for dev), along with the connection string (DATABASE_URL for prod, DATABASE_URL_DEV for dev) and the storage credentials (unsuffixed for prod, with a _DEV suffix for dev).

Schema changes are applied (step 6) before the new server code is live (step 7), whether they arrive by push or as migrations. This is normal for most deployment workflows, but it means the previous version of your server briefly runs against the new schema. For destructive changes in prod (dropped columns, renamed tables), design your rollout so the old code keeps working, typically by shipping additive changes first, then removing the old fields in a later deploy.

Options

ArgumentDescription
target (required)The environment to deploy to. Must be dev or prod.
FlagDescription
--provider <provider>Deployment provider: vercel, cloudflare, or deno
--logsStream the server logs once the deployment is live
--skip-schema-changes-confirmationApply destructive database schema changes without asking. They are still reported. No other prompt is affected

Streaming logs after deploying

Pass --logs to tail the server as soon as the deployment goes live, without running a second command:

npx typebase-io-cli deploy dev --logs

The stream starts once the deployment URL has been printed, and keeps running until you press x or Ctrl+C. It reuses the target and provider of the deploy, so it never asks you anything a second time. Everything else works exactly like typebase-io-cli logs, including the provider differences in delivery speed and completeness.

A failed deploy stops before the stream starts, so you never end up tailing a version that did not ship.

Dev vs Prod environments

Typebase supports two separate environments:

EnvironmentUse case
devDevelopment and testing. Uses a separate database branch.
prodProduction. Uses the main database.

Each environment gets its own:

  • Deployment URL
  • Database (or database branch)
  • Storage buckets
  • Environment variables

Deploy to dev:

npx typebase-io-cli deploy dev

Deploy to production:

npx typebase-io-cli deploy prod

Provider setup

When you log in to a provider, the CLI saves the API token it obtains (VERCEL_TOKEN, CLOUDFLARE_API_TOKEN, DENO_DEPLOY_TOKEN, NEON_API_KEY) to your project-root .env. Make sure .env is listed in your .gitignore so these tokens never end up in version control. The same goes for the storage credentials a deploy writes there.

Vercel

When you deploy to Vercel for the first time:

  1. The CLI asks you to paste a Vercel access token, created at vercel.com/account/tokens.
  2. You select an existing Vercel project or create a new one.
  3. Your server is deployed as a Vercel Serverless Function using Hono as the HTTP adapter.

A token scoped to your team is enough to deploy. If your project has a storage.ts on the vercel provider, create the token with the Full Account scope instead: bucket sync reads each Blob store's token, and Vercel only allows that from a Full Account token. See Vercel needs a Full Account token.

The deployment URL looks like: https://your-project.vercel.app

Cloudflare Workers

When you deploy to Cloudflare for the first time:

  1. The CLI asks you to log in to Cloudflare (opens a browser).
  2. You select or create a Cloudflare Worker.
  3. Your server is deployed as a Cloudflare Worker.

The deployment URL looks like: https://your-worker.your-subdomain.workers.dev

Cloudflare Workers use the Fetch API natively, so environment variables are handled through Cloudflare's secrets system rather than process.env. The generated src/env.ts reads them from the Worker bindings, so env on the action context works the same as on every other provider.

Deno Deploy

When you deploy to Deno Deploy for the first time:

  1. The CLI asks you to log in to Deno Deploy.
  2. You select or create a Deno Deploy project.
  3. Your server is deployed as a Deno Deploy application.

The deployment URL looks like: https://your-project.your-organization.deno.net

Database provisioning

If your project has a db/schema.ts, the CLI will set up a Neon PostgreSQL database for you:

  1. First deploy: The CLI asks you to authenticate with Neon, then creates (or selects) a project.
  2. Schema push: Your Drizzle schema is pushed to the database. In migrations mode your pending migrations are applied instead — see below.
  3. Environment variable: The connection string is set on your deployment provider under the key DATABASE_URL, and mirrored into your project-root .env as DATABASE_URL for prod or DATABASE_URL_DEV.

Dev and prod deployments use separate Neon branches, so your development data doesn't affect production.

Storage provisioning

If your project has a storage.ts, the CLI creates its buckets for you:

  1. First deploy: The CLI asks which Vercel team or Cloudflare account holds your buckets, and freezes the project part of their names in typebase.json. The storage provider doesn't have to match your server provider: a Worker can keep its files in Vercel Blob.
  2. Bucket sync: Every declared bucket missing for the target is created as <project>-<bucket>-<target>. Nothing is ever deleted; a bucket you stopped declaring is reported and left alone.
  3. Environment variables: The credentials for those buckets are set on your deployment provider and mirrored into your project-root .env. Your own Vercel or Cloudflare login token is never among them.

Dev and prod deployments use separate buckets, so a test upload never lands in production. storage sync does steps 1 and 2 on their own, without deploying.

Deploying with migrations

If your project has a db/migrations folder, step 2 changes: instead of pushing your schema, the CLI applies your pending migrations. Everything else is the same.

Two things behave differently from push mode:

  • Unrecorded schema changes stop the deploy. If you edited db/schema.ts without running db migrations generate, the deploy fails and names the affected tables. Without this, migrations would apply cleanly (there are none pending), and your server would ship with types describing a column the database doesn't have — a green build where every action touching that column fails at runtime.
  • A failed migration aborts the deploy. The server is never deployed against a database that didn't get the schema it expects.

Migrations are applied before the new server ships, so for a few seconds your old server runs against the new schema. Adding a table or a nullable column is safe. Dropping a column, renaming one, or adding a NOT NULL constraint will break the running server until the new one takes over. For those, deploy in two steps: ship a migration the old server can tolerate, then remove the old shape in a follow-up deploy.

Specifying the provider

You can skip the interactive prompt by passing the --provider flag:

npx typebase-io-cli deploy dev --provider vercel
npx typebase-io-cli deploy dev --provider cloudflare
npx typebase-io-cli deploy dev --provider deno

Or set the provider in typebase.json so it's always used:

typebase.json
{
  "serverProvider": "vercel"
}

After deploying

After a successful deploy, the CLI prints the deployment URL:

Deployment URL: https://your-project.vercel.app

This URL is also saved to your .env file. The key depends on the target (TYPEBASE_APP_URL for prod, TYPEBASE_APP_URL_DEV for dev), and a local run writes a third, so all three coexist:

TYPEBASE_APP_URL=https://your-project.vercel.app
TYPEBASE_APP_URL_DEV=https://your-project-dev.vercel.app
TYPEBASE_APP_URL_LOCAL=http://127.0.0.1:8080

Use these when setting up your client, with local at the front of the chain so a local run takes precedence whenever one is running.

Managing environment variables

Use the npx typebase-io-cli env command to manage environment variables on your deployment provider.

Add a variable:

npx typebase-io-cli env dev add MY_KEY my-value

Get a variable:

npx typebase-io-cli env dev get MY_KEY

See the env command for more details.

On this page