Deploying

Deploying

This React/Node.js/Postgres app supports a one-command deploy to Fly.io or a manual deploy to any provider.

Fastest path: use the one-command deploy. Prefer another host or split front/back ends? See Deploying Manually below.


Deploying your app

Use the sequence below to deploy your app:


Prerequisites

AWS S3 CORS

If you use AWS S3, add your production domain to the bucket CORS AllowedOrigins. See File Uploading guide.


Env vars checklist

Before deploying, confirm all keys and variables.

Payment Processor vars

In Payments Integration you used test keys and test product IDs. For production, repeat the same steps with live mode and add the live keys to the deployed environment.

Other vars

Many will match development, but double-check. Full list:

General:

  • DATABASE_URL
  • JWT_SECRET
  • WASP_WEB_CLIENT_URL
  • WASP_SERVER_URL

OpenAI:

  • OPENAI_API_KEY

SendGrid:

  • SENDGRID_API_KEY

Social auth:

  • GOOGLE_CLIENT_ID
  • GOOGLE_CLIENT_SECRET
  • GITHUB_CLIENT_ID
  • GITHUB_CLIENT_SECRET

Analytics:

  • REACT_APP_PLAUSIBLE_ANALYTICS_ID
  • PLAUSIBLE_API_KEY
  • PLAUSIBLE_SITE_ID
  • PLAUSIBLE_BASE_URL
  • REACT_APP_GOOGLE_ANALYTICS_ID
  • GOOGLE_ANALYTICS_CLIENT_EMAIL
  • GOOGLE_ANALYTICS_PROPERTY_ID
  • GOOGLE_ANALYTICS_PRIVATE_KEY Note: convert the JSON private key to base64 first with echo -n "PRIVATE_KEY" | base64

See Analytics docs [link] for details

AWS S3:

  • AWS_S3_IAM_ACCESS_KEY
  • AWS_S3_IAM_SECRET_KEY
  • AWS_S3_FILES_BUCKET
  • AWS_S3_REGION

Deploying to Fly.io

Fly.io is a global app platform — great for SaaS because you can spin up for free, run frontend + backend together, scale easily, and deploy with a single command.

Use wasp deploy to ship the whole stack—DB, server, and client—in a single command. For the step-by-step, follow the official Deploy to Fly with the Wasp CLI guide; work through it carefully to get live.

⚠️

Setting Environment Variables

We're using some client-side env vars, so pass them to your wasp deploy commands to include them in the build.
REACT_APP_CLIENT_ENV_VAR_1=<...> REACT_APP_CLIENT_ENV_VAR_2=<...> wasp deploy
The deploy command handles the following server-side envs automatically: DATABASE_URL · PORT · JWT_SECRET · WASP_WEB_CLIENT_URL · WASP_SERVER_URL

Deploying manually or to other providers

If you’d rather deploy the frontend and backend separately — or use your own host — see the Manual Deployment guide.

Client-side environment variables on manual builds

Append client-side vars to your build command, for example:

bash
REACT_APP_CLIENT_ENV_VAR_1=<...> npm run build

Adding server redirect URLs to social auth

After deploying your server, add correct redirect URIs in each provider’s app settings. Use the Wasp docs for:


Setting up your production Stripe webhook

Follow these steps when preparing for production.

Stripe API versions

Your Stripe account is tied to the current API version at the time you create it — and that dictates webhook response formats and request expectations. Since this template assumes a particular version, your account’s version could differ. Test any change before deploying.

Reference in code:

stripeClient.ts
export const stripe = new Stripe(process.env.STRIPE_API_KEY!, {
  apiVersion: 'YYYY-MM-DD', // e.g. 2023-08-16
});
i
Stripe will send events not initiated by your server requests using your account's default API version. That is why the client apiVersion and the account default version should match.

Steps to align versions:

  1. Find your default API version in Stripe dashboard under Developers
  2. Confirm it matches your src/payment/stripe/stripeClient.ts:
stripeClient.ts
export const stripe = new Stripe(process.env.STRIPE_KEY!, {
  apiVersion: 'YYYY-MM-DD', // e.g. 2023-08-16
});
  1. If they do not match, choose one of:
    • If your dashboard’s default equals the latest API, upgrade the Stripe NPM package to the latest
    • If your dashboard’s default is not the latest and you do not want to upgrade, install the Stripe NPM version that matches that date

How to find the NPM version that matches your default date:

  • Note the date of your default API version in the developer dashboard
  • Open the Stripe NPM package page and hover Published until you find the release matching your date preview

Install that exact package version:

bash
npm install [email protected] # e.g. npm install [email protected]

Test your app thoroughly after changing the client version.

Creating your production webhook

  1. Go to https://dashboard.stripe.com/webhooks
  2. Click + add endpoint
    1. preview 3.Enter your endpoint URL which is your deployed server URL plus /payments-webhook For example: https://open-saas-wasp-sh-server.fly.dev/payments-webhook
  3. Select the events to listen to. Use the same events your webhook consumes as listed in src/payment/stripe/webhookPayload.ts
  4. Reveal the signing secret on the webhook page
    1. preview
  5. Add this secret to your server environment as STRIPE_WEBHOOK_SECRET If deployed to Fly.io, run:
bash
wasp deploy fly cmd --context server secrets set STRIPE_WEBHOOK_SECRET=whsec_...

Setting up your production Lemon Squeezy webhook

Your endpoint is your deployed server URL plus /payments-webhook, for example: https://open-saas-wasp-sh-server.fly.dev/payments-webhook

In the Lemon Squeezy Webhooks Dashboard:

  • Click the + button
  • Add the Callback URL
  • Create a long random signing secret
  • Add it as LEMONSQUEEZY_WEBHOOK_SECRET in your server production environment
  • Select at least these events:
    • order_created
    • subscription_created
    • subscription_updated
    • subscription_cancelled
  • Save