> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shipfastai.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Shipfastai to Railway and Vercel

> Deploy your FastAPI backend to Railway and your Next.js frontend to Vercel for a fully managed, zero-ops production environment.

Railway and Vercel together give you a production-grade deployment with managed infrastructure, automatic TLS, and preview environments — without configuring servers. Railway hosts your FastAPI backend and PostgreSQL database, and Vercel hosts your Next.js frontend. This guide walks you through both deployments and explains how to wire them together.

<Note>
  Railway's free Hobby plan is suitable for experimenting, but it imposes usage limits and may sleep inactive services. For a real production workload, upgrade to Railway's Pro plan (\$20/month) to get always-on services, more compute, and priority support.
</Note>

## Deploy the backend to Railway

<Steps>
  <Step title="Create a Railway project and add a PostgreSQL database">
    Log in to [railway.app](https://railway.app) and create a new project. Inside the project, click **New** → **Database** → **Add PostgreSQL**. Railway provisions a managed PostgreSQL instance and automatically injects a `DATABASE_URL` variable into services in the same project.
  </Step>

  <Step title="Connect your GitHub repo and select the backend directory">
    Click **New** → **GitHub Repo**, authorize Railway to access your repository, and select it. In the service settings, set the **Root Directory** to the backend path for your tier:

    * Basic: `products/basic/backend`
    * Pro: `products/pro/backend`
    * Enterprise: `products/enterprise/backend`

    Railway detects the `Dockerfile` in that directory and uses it for builds.
  </Step>

  <Step title="Set required environment variables">
    In the service's **Variables** tab, add the following. `DATABASE_URL` is already injected by the linked PostgreSQL service — do not override it.

    | Variable                  | Description                                               |
    | ------------------------- | --------------------------------------------------------- |
    | `JWT_SECRET`              | A long, random string used to sign JWT tokens             |
    | `STRIPE_SECRET_KEY`       | Your Stripe secret key (`sk_live_...`)                    |
    | `STRIPE_WEBHOOK_SECRET`   | Stripe webhook signing secret (`whsec_...`)               |
    | `STRIPE_PRICE_ID_MONTHLY` | Stripe price ID for the monthly plan                      |
    | `STRIPE_PRICE_ID_YEARLY`  | Stripe price ID for the yearly plan                       |
    | `RESEND_API_KEY`          | Resend API key for transactional email                    |
    | `FROM_EMAIL`              | Sender address for outgoing email                         |
    | `FRONTEND_URL`            | Your Vercel frontend URL (set after frontend is deployed) |
    | `CORS_ORIGINS`            | Same as `FRONTEND_URL`                                    |
    | `APP_ENV`                 | Set to `production`                                       |
    | `DEBUG`                   | Set to `false`                                            |
  </Step>

  <Step title="Configure the start command">
    In the service settings under **Deploy**, set the **Start Command** to:

    ```bash theme={null}
    uvicorn app.main:app --host 0.0.0.0 --port $PORT
    ```

    Railway injects the `$PORT` variable automatically. Do not hardcode a port number.
  </Step>

  <Step title="Deploy and note the backend URL">
    Click **Deploy**. Railway builds the Docker image and starts the service. Once the deployment is healthy, open the **Settings** tab and copy the public domain (e.g. `https://your-project-production.up.railway.app`). You will need this URL when setting up the frontend.
  </Step>
</Steps>

## Deploy the frontend to Vercel

<Steps>
  <Step title="Connect your GitHub repo to Vercel">
    Log in to [vercel.com](https://vercel.com), click **Add New Project**, and import your GitHub repository. Vercel detects the monorepo structure automatically.
  </Step>

  <Step title="Set the root directory">
    In the project configuration, expand **Root Directory** and set it to the frontend path for your tier:

    * Basic: `products/basic/frontend`
    * Pro: `products/pro/frontend`
    * Enterprise: `products/enterprise/frontend`

    Vercel uses this directory as the build context and automatically detects Next.js.
  </Step>

  <Step title="Set environment variables">
    Before deploying, add the following environment variables in the Vercel dashboard under **Settings** → **Environment Variables**:

    | Variable                              | Value                                              |
    | ------------------------------------- | -------------------------------------------------- |
    | `NEXT_PUBLIC_API_URL`                 | Your Railway backend URL from the previous section |
    | `NEXT_PUBLIC_STRIPE_PRICE_ID_MONTHLY` | Stripe monthly price ID                            |
    | `NEXT_PUBLIC_STRIPE_PRICE_ID_YEARLY`  | Stripe yearly price ID                             |

    Variables prefixed with `NEXT_PUBLIC_` are embedded into the browser bundle at build time, so you must redeploy after changing them.
  </Step>

  <Step title="Deploy">
    Click **Deploy**. Vercel builds the Next.js application and publishes it to its global edge network. Once deployment succeeds, Vercel assigns a `.vercel.app` domain you can use immediately or replace with a custom domain.
  </Step>
</Steps>

## Custom domain setup

You can add a custom domain in both services from their respective dashboards.

* **Railway**: Go to your service → **Settings** → **Networking** → **Custom Domain**. Add your domain and update your DNS records as instructed.
* **Vercel**: Go to your project → **Settings** → **Domains**. Add your domain and follow the DNS verification steps.

After pointing your custom domain to the backend, update the `FRONTEND_URL` and `CORS_ORIGINS` variables on Railway, and redeploy the backend. After pointing your custom domain to the frontend, update `NEXT_PUBLIC_API_URL` on Vercel and redeploy the frontend.

## Environment variable checklist

Use this table to confirm every variable is configured in the right service before going live.

| Variable                              | Set on Railway | Set on Vercel |
| ------------------------------------- | :------------: | :-----------: |
| `DATABASE_URL`                        |  Auto-injected |       —       |
| `JWT_SECRET`                          |       Yes      |       —       |
| `STRIPE_SECRET_KEY`                   |       Yes      |       —       |
| `STRIPE_WEBHOOK_SECRET`               |       Yes      |       —       |
| `STRIPE_PRICE_ID_MONTHLY`             |       Yes      |       —       |
| `STRIPE_PRICE_ID_YEARLY`              |       Yes      |       —       |
| `RESEND_API_KEY`                      |       Yes      |       —       |
| `FROM_EMAIL`                          |       Yes      |       —       |
| `FRONTEND_URL`                        |       Yes      |       —       |
| `CORS_ORIGINS`                        |       Yes      |       —       |
| `APP_ENV`                             |       Yes      |       —       |
| `NEXT_PUBLIC_API_URL`                 |        —       |      Yes      |
| `NEXT_PUBLIC_STRIPE_PRICE_ID_MONTHLY` |        —       |      Yes      |
| `NEXT_PUBLIC_STRIPE_PRICE_ID_YEARLY`  |        —       |      Yes      |
