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:
- Vercel: serverless functions
- Cloudflare Workers: edge computing
- Deno Deploy: edge runtime
Quick start
Deploy to your dev environment:
npx typebase-io-cli deploy devDeploy to production:
npx typebase-io-cli deploy prodThe first time you run this, the CLI will ask you to:
- Select a deployment provider (Vercel, Cloudflare, or Deno)
- Authenticate with the provider
- Select or create a project on the provider
- Select or create a database on Neon (if your project has a database schema)
- Select the account that holds your buckets (if your project has a
storage.tson 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:
- Regenerates the types in
_generated/: Runs the same logic asnpx typebase-io-cli codegen, so you never have to run it by hand before deploying. - Validates your TypeScript: Checks your
typebase/directory against those freshly generated types, so what gets checked is what gets built. - 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. - Generates server files: Builds the server code from your actions, schema, auth, env, publisher, and storage config.
- Transpiles to JavaScript: Converts TypeScript to JavaScript for deployment.
- 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-confirmationapproves 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. - Deploys the server: Uploads the built server to your chosen provider.
- Sets environment variables: Configures
DATABASE_URL,BETTER_AUTH_SECRET, and your storage credentials on your provider. The key on the provider is alwaysDATABASE_URL, regardless of target; each environment (dev,prod) holds its own value. Anything you declared inenv.tsis your responsibility: set it withnpx typebase-io-cli env <target> add <KEY> <value>, or the deployed server will refuse to boot. - Saves the URL and environment variables: Writes the deployment URL to your project-root
.env(TYPEBASE_APP_URLforprod,TYPEBASE_APP_URL_DEVfordev), along with the connection string (DATABASE_URLforprod,DATABASE_URL_DEVfordev) and the storage credentials (unsuffixed forprod, with a_DEVsuffix fordev).
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
| Argument | Description |
|---|---|
target (required) | The environment to deploy to. Must be dev or prod. |
| Flag | Description |
|---|---|
--provider <provider> | Deployment provider: vercel, cloudflare, or deno |
--logs | Stream the server logs once the deployment is live |
--skip-schema-changes-confirmation | Apply 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 --logsThe 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.
Dev vs Prod environments
Typebase supports two separate environments:
| Environment | Use case |
|---|---|
dev | Development and testing. Uses a separate database branch. |
prod | Production. 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 devDeploy to production:
npx typebase-io-cli deploy prodProvider 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:
- The CLI asks you to paste a Vercel access token, created at vercel.com/account/tokens.
- You select an existing Vercel project or create a new one.
- 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:
- The CLI asks you to log in to Cloudflare (opens a browser).
- You select or create a Cloudflare Worker.
- 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:
- The CLI asks you to log in to Deno Deploy.
- You select or create a Deno Deploy project.
- 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:
- First deploy: The CLI asks you to authenticate with Neon, then creates (or selects) a project.
- Schema push: Your Drizzle schema is pushed to the database. In migrations mode your pending migrations are applied instead — see below.
- Environment variable: The connection string is set on your deployment provider under the key
DATABASE_URL, and mirrored into your project-root.envasDATABASE_URLfor prod orDATABASE_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:
- 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. - 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. - 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.tswithout runningdb 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 vercelnpx typebase-io-cli deploy dev --provider cloudflarenpx typebase-io-cli deploy dev --provider denoOr set the provider in typebase.json so it's always used:
{
"serverProvider": "vercel"
}After deploying
After a successful deploy, the CLI prints the deployment URL:
Deployment URL: https://your-project.vercel.appThis 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:8080Use 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-valueGet a variable:
npx typebase-io-cli env dev get MY_KEYSee the env command for more details.