---
title: "Deploy"
description: "Deploy your project to Cloudflare Workers"
source: /docs/deploy
---


Two Ways to Deploy [#two-ways-to-deploy]

The deploy wizard can run in two modes:

* **Interactive** — step through prompts; good for first deploys and exploration
* **Config file** — provide a `deploy.json` and run non-interactively; good for CI, re-deploys, and repeatable setups

Both modes use the same underlying steps.

Interactive Mode [#interactive-mode]

The wizard handles everything: database provisioning, secret configuration, Stripe product setup, worker deployment, and GitHub environment provisioning.

```bash
npx mastrakit deploy
```

You'll be prompted for:

* **Project slug** — used for worker names (e.g. `my-app` → `auth-my-app`)
* **Steps to run** — multi-select; toggle with space, confirm with enter
* **Secrets** — API keys for Anthropic/OpenAI, Stripe, Cloudflare, Resend, etc.

The wizard auto-generates `BETTER_AUTH_SECRET`, `SESSION_SECRET`, and metering service credentials so you don't need to supply them.

What It Does [#what-it-does]

1. **Checks prerequisites** — verifies Node.js, pnpm, Wrangler, Turso CLI, Stripe CLI, GitHub CLI
2. **Detects domain** — if your domain is a Cloudflare zone, uses custom domains; otherwise falls back to `*.workers.dev`
3. **Provisions databases** — creates 3-4 Turso databases (auth, api, mastra, metering)
4. **Collects secrets** — prompts for API keys (auto-generates `BETTER_AUTH_SECRET` and `SESSION_SECRET`)
5. **Creates Stripe products** — Pro plan, Enterprise plan (monthly + yearly), credit packages (100/500/1000)
6. **Deploys workers** — auth, api, metering, mastra, web (in dependency order)
7. **Pushes database schemas** — runs Drizzle migrations
8. **Sets up GitHub** — creates environments, pushes secrets and variables

Deploy Steps [#deploy-steps]

You can select which steps to run:

| Step              | Description                                 |
| ----------------- | ------------------------------------------- |
| `databases`       | Provision Turso databases                   |
| `secrets`         | Configure API keys and credentials          |
| `stripe`          | Create Stripe products and webhook          |
| `deploy-auth`     | Deploy auth worker                          |
| `deploy-api`      | Deploy API worker                           |
| `deploy-metering` | Deploy metering worker                      |
| `deploy-mastra`   | Deploy Mastra worker                        |
| `schema-push`     | Push database schemas                       |
| `deploy-web`      | Deploy web worker                           |
| `github-setup`    | Create GitHub environments and push secrets |

Config File Mode (deploy.json) [#config-file-mode-deployjson]

For automated or repeatable deployments, provide all inputs in a JSON file:

```bash
npx mastrakit deploy --config deploy.json
```

In this mode the wizard **does not prompt** — every value comes from the file. Missing required fields cause the wizard to exit with an error.

Full Example deploy.json [#full-example-deployjson]

```json
{
  "slug": "my-project",
  "domain": "mydomain.com",
  "currency": "eur",
  "llm": "anthropic",
  "secrets": {
    "ANTHROPIC_API_KEY": "sk-ant-...",
    "OPENAI_API_KEY": "sk-...",
    "STRIPE_SECRET_KEY": "sk_test_...",
    "STRIPE_PUBLISHABLE_KEY": "pk_test_...",
    "CF_ACCOUNT_ID": "abc123...",
    "CF_API_TOKEN": "cf_...",
    "GOOGLE_CLIENT_ID": "...apps.googleusercontent.com",
    "GOOGLE_CLIENT_SECRET": "GOCSPX-...",
    "GITHUB_CLIENT_ID": "Iv1...",
    "GITHUB_CLIENT_SECRET": "...",
    "RESEND_API_KEY": "re_...",
    "TWILIO_ACCOUNT_SID": "AC...",
    "TWILIO_AUTH_TOKEN": "...",
    "TWILIO_PHONE_NUMBER": "+1..."
  },
  "steps": [
    "databases",
    "secrets",
    "stripe",
    "oauth-proxy",
    "deploy-auth",
    "deploy-api",
    "deploy-metering",
    "deploy-mastra",
    "schema-push",
    "deploy-web",
    "deploy-docs",
    "github-setup"
  ]
}
```

The `oauth-proxy` step deploys a per-project OAuth proxy worker at `oauth-{slug}.{domain}`. It's the single redirect URI you register in the Google/GitHub consoles — every environment (prod, preview, dev, Conductor branches) routes OAuth through it, so you only register one callback per project.

Minimal deploy.json [#minimal-deployjson]

If you only need to redeploy workers (databases and secrets already configured):

```json
{
  "slug": "my-project",
  "domain": "mydomain.com",
  "steps": [
    "deploy-auth",
    "deploy-api",
    "deploy-mastra",
    "deploy-web"
  ]
}
```

Configure-Only (No Deploy) [#configure-only-no-deploy]

To provision databases and write `.dev.vars` without deploying workers — useful for bootstrapping local development:

```json
{
  "slug": "my-project",
  "currency": "eur",
  "llm": "anthropic",
  "secrets": { "ANTHROPIC_API_KEY": "sk-ant-..." },
  "steps": ["databases", "secrets"],
  "skipDeploy": true
}
```

Auto-Generated Secrets [#auto-generated-secrets]

These are always generated if missing — you don't need to include them:

* `BETTER_AUTH_SECRET`
* `SESSION_SECRET`
* `METERING_SERVICE_CLIENT_ID`
* `METERING_SERVICE_CLIENT_SECRET`
* `METERING_MASTER_API_KEY`

Config Fields [#config-fields]

| Field        | Type                        | Description                                                           |
| ------------ | --------------------------- | --------------------------------------------------------------------- |
| `slug`       | string                      | **Required.** Project slug (used for worker names and database names) |
| `domain`     | string                      | Custom domain (falls back to `*.workers.dev` if not a CF zone)        |
| `currency`   | `"eur"` or `"usd"`          | Currency for Stripe products (default: `eur`)                         |
| `llm`        | `"anthropic"` or `"openai"` | LLM provider (default: inherits from `.mastrakit/config.json`)        |
| `secrets`    | object                      | Pre-filled secrets — skips interactive prompts                        |
| `steps`      | `string[]`                  | Which deploy steps to run (see below)                                 |
| `skipDeploy` | boolean                     | If true, configure only (no worker deployments)                       |

secrets Keys [#secrets-keys]

Provide only the keys relevant to the components you scaffolded.

| Key                                           | Required for                                         |
| --------------------------------------------- | ---------------------------------------------------- |
| `ANTHROPIC_API_KEY`                           | `llm: "anthropic"`                                   |
| `OPENAI_API_KEY`                              | `llm: "openai"`                                      |
| `STRIPE_SECRET_KEY`, `STRIPE_PUBLISHABLE_KEY` | Stripe payments                                      |
| `CF_ACCOUNT_ID`, `CF_API_TOKEN`               | Cloudflare Workers deploy, Stripe webhook auto-setup |
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`    | Google OAuth sign-in (optional)                      |
| `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`    | GitHub OAuth sign-in (optional)                      |
| `RESEND_API_KEY`                              | Transactional email (optional)                       |
| `TWILIO_*`                                    | SMS notifications (optional)                         |

Custom Domain vs Workers.dev [#custom-domain-vs-workersdev]

The deploy wizard checks if your domain is a Cloudflare zone:

* **Custom domain detected:** Workers get routes like `auth-myproject.mydomain.com`
* **No custom domain:** Workers get routes like `auth-myproject.workers.dev`

To use custom domains, add your domain to Cloudflare first (DNS management).

Post-Deploy [#post-deploy]

Cloudflare AI Gateway [#cloudflare-ai-gateway]

Create an AI Gateway for LLM request routing and observability:

1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) > AI > AI Gateway
2. Create a gateway named `ai-platform-gateway` (or your custom `CF_GATEWAY_ID`)

Verify Deployment [#verify-deployment]

```bash
curl https://<auth-worker>/api/auth/ok
curl https://<api-worker>/health
curl https://<mastra-worker>/api/health
```

Redeploying [#redeploying]

To redeploy specific services:

```bash
npx mastrakit deploy --config deploy.json
# Select only the steps you need
```

Or deploy individual workers directly:

```bash
cd apps/auth && pnpm deploy
cd apps/api && pnpm deploy
cd apps/mastra && mastra build && pnpm deploy
cd apps/web && pnpm deploy
```
