Deployment

Production deployment on Cloudflare Workers.


The first deployment is completed manually in two steps. After that, you can enable automatic deployments triggered by pushes to your Git repository.

Prerequisites

  • Cloudflare account with a paid workers plan ($5/month)
  • Custom domain added to Cloudflare.
  • This repo cloned into your GitHub account.
  • A 'live' Stripe account i.e. one with a connected bank account.
  • An account with an email provider such as Mailgun, Brevo, Resend, etc.

Cloudflare deployment

1) Confirm the worker name

Update your worker name in workers/app/wrangler.jsonc.

2) Log in to Cloudflare

npx wrangler login

3) Create the remote D1 database

npx wrangler d1 create database -c workers/app/wrangler.jsonc

Set the database ID in the bindings section of wrangler.jsonc.

4) Run migrations

npm run db:migrate:remote

5) Create secrets

Better Auth (used for signing credentials):

npx wrangler secret put BETTER_AUTH_SECRET -c workers/app/wrangler.jsonc

Use a long, random value. For instance:

openssl rand -hex 32

Mailgun (if using Mailgun, otherwise your provider API keys)

npx wrangler secret put MAILGUN_API_KEY -c workers/app/wrangler.jsonc

6) Deploy once manually

npm run deploy --workspace workers/app

You should see the site live on a workers.dev domain. Not everything will work yet e.g. there are no pricing on the pricing page.

7) Add a custom domain

In Cloudflare:

  • Open your worker.
  • Go to Settings.
  • Add a Custom Domain under Domains and Routes.
  • Enter your top-level domain (no www).

If the domain is already in use, remove conflicting DNS records and try again.

8) Create environment variables

In Cloudflare:

  • Open your worker.
  • Go to Settings.
  • Click +Add under Variables and Secrets.
  • Set type to Text for each one.
  • Add:
    • BETTER_AUTH_URL <- Full URL of your site.
    • MAILGUN_DOMAIN (if using Mailgun)

Stripe

  • Add your products and prices to the 'Product Catalog'

1) Create a webhook with at least these events:

  • payment_intent.succeeded
  • customer.subscription.created
  • customer.subscription.deleted
  • customer.subscription.updated
  • Destination Type: Webhook Endpoint

Use this callback URL:

https://<YOUR DOMAIN>/api/stripe/webhooks

2) Environment variables and secrets

Create or edit a .env file in workers/app with the following information: NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...

And the following secrets:

npx wrangler secret put STRIPE_SECRET_KEY -c workers/app/wrangler.jsonc
npx wrangler secret put STRIPE_WEBHOOK_SECRET -c workers/app/wrangler.jsonc

Final deployment

Deploy again:

npx wrangler deploy -c workers/app/wrangler.jsonc

Your application should now be fully functional and ready to start selling.

Verification and Testing

  • Visit your custom domain.
  • Confirm GitHub sign-in works.
  • Check non-sensitive information via the route: https:///api/env. This route can later be deleted.

Post deployment checklist

  • Check Google Analytics to make sure setup is working.
  • Add site and sitemap to Google Search Console
  • Use ahrefs Site Audit to crawl the site for errors (free, optional)
  • List the application in GitHub Marketplace (free, optional)
  • Enable HTTP → HTTPS redirects under SSL/TLS → Edge Certificates in Cloudflare.
  • Disable Cloudflare managed Robots.txt policy (handled by robots.txt/route.ts)
  • Enable Cloudflare Turnstile on the contact form (optional).
  • Google Rich Results Test: https://search.google.com/test/rich-results

Cloudflare Turnstile

Create a widget in your Cloudflare dashboard and get the site key (public) and secret key (private).

Add the site key to environment variables in .env.production.local:

NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY=0x...

Add the secret key to secrets either in the dashboard or via:

npx wrangler secret put CLOUDFLARE_TURNSTILE_SECRET_KEY -c workers/app/wrangler.jsonc

Google Search Console

  • Use 'HTML Meta Tag' for validation.
  • Set the 'content' value via the environment variable: NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION

Do not use GA4 verification even if you've set it up.
Next.js adds the GA script to the body and loads it after hydration for performance reasons, but that method is incompatible with automated checker.

Theming

What most people think of as a theme is really a holdover from the old CMS days. Now a minimal theme consists of:

  • Font stack - Google fonts. Inter and Reddit Sans are popular choices.
  • Color palette - Can make due with a primary color.
  • Create a logo - Ask ChatGPT or other tools to generate an SVG.
  • Choose icons - Try any of these icon packs.