Deploying Spacerr is mostly about creating production provider resources, adding the production environment variables, preparing the production database, and checking the user flows that depend on third party services.
Recommended Host
The default setup is optimized for Vercel:
- Next.js App Router deployment.
- Vercel Blob for private and public file storage.
- Vercel Redis for realtime coordination and runtime state.
- Vercel AI Gateway for model access.
- Scheduled routes protected by
CRON_SECRET.
You can deploy elsewhere, but the provider setup and env var names are already tuned for Vercel.
Production Environment
Create a production env file before pushing values to your host.
cp .env.example .env.productionFill it with production values, not local test values.
NEXT_PUBLIC_DOMAIN="https://your-domain.com"
DATABASE_URL="postgresql://..."
DIRECT_URL="postgresql://..."
BETTER_AUTH_SECRET="replace-with-a-production-secret"
BETTER_AUTH_PASSKEY_RP_ID="your-domain.com"
CRON_SECRET="replace-with-a-production-secret"NEXT_PUBLIC_DOMAIN must match the deployed domain because auth callbacks, Stripe redirects, metadata, emails, and server generated links depend on it.
You have two ways to add production env vars to Vercel.
Option one: open the Vercel dashboard, go to your project settings, and add each value manually under Environment Variables for Production.
Option two (recommended): use the Vercel CLI. This is the option Spacerr uses because the helper can push .env.production for you. Install it, log in, and link this local folder to the correct Vercel project.
bun add -g vercel
vercel login
vercel linkThe project includes a helper that reads .env.production and pushes those values to the linked Vercel project's Production environment.
bun push:env:productionReview values in the Vercel dashboard after pushing so you can confirm the project, environment, and secrets are correct.
Database
Create a production Postgres database before the first production build. The default setup uses Neon, but you can use another Postgres provider if you prefer.
Use production values for DATABASE_URL and DIRECT_URL, and keep local, preview, and production databases separate. The Database section covers Neon setup, provider switching, and the database workflow.
Vercel Services
Create production versions of the Vercel services used by the app.
- One private Blob store for user files.
- One public Blob store for blog covers and public assets.
- One Redis database.
- One AI Gateway API key.
Add these values to production env vars:
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_private_..."
BLOB_PUBLIC_READ_WRITE_TOKEN="vercel_blob_rw_..."
REDIS_URL="redis://default:password@host:port"
AI_GATEWAY_API_KEY="your-ai-gateway-key"Auth And OAuth
Use production values for Better Auth.
BETTER_AUTH_SECRET="replace-with-a-production-secret"
BETTER_AUTH_PASSKEY_RP_ID="your-domain.com"
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"In Google Cloud Console, add production origins and callback URLs.
https://your-domain.com
https://your-domain.com/api/auth/callback/googleIf the domain changes later, update Google OAuth, NEXT_PUBLIC_DOMAIN, passkey relying party ID, and any provider dashboards that reference the old domain.
Stripe Live Mode
In Stripe live mode:
- Create live products and prices.
- Add monthly, yearly, and one time price IDs.
- Add the production webhook endpoint.
- Copy the live webhook signing secret.
- Use the live Stripe secret key in production env vars.
STRIPE_SECRET_KEY="sk_live_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
STRIPE_PRICE_ID_MONTHLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_YEARLY_SUBSCRIPTION="price_..."
STRIPE_PRICE_ID_ONE_TIME="price_..."Production webhook endpoint:
https://your-domain.com/api/auth/stripe/webhookVerify your sending domain in Resend before production launch.
RESEND_API_KEY="re_..."
RESEND_FROM_EMAIL="Your Product <hello@your-domain.com>"
SUPPORT_EMAIL="support@your-domain.com"Send at least one test email for sign up, magic link, password reset, and welcome email before launch.
Realtime And Analytics
Create production Pusher and PostHog projects or confirm the existing projects are safe for production data.
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_SECRET="your-pusher-secret"
NEXT_PUBLIC_PUSHER_KEY="your-pusher-key"
NEXT_PUBLIC_PUSHER_CLUSTER="your-pusher-cluster"
NEXT_PUBLIC_ANALYTICS_TRACKING="on"
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN="phc_..."
NEXT_PUBLIC_POSTHOG_HOST="https://us.i.posthog.com"Keep analytics off in production until your privacy copy and consent expectations are ready.
Build And Verify
Run local checks before deploying.
bun run lint
bun run buildAfter deployment, verify:
- Home, pricing, contact, blog, legal pages, and dashboard routes open.
- Sign up, sign in, magic link, passkeys, and password reset work.
- Stripe checkout redirects and returns correctly.
- Stripe webhook events arrive in the production endpoint.
- Blog cover uploads work.
- Chat streams work and can be stopped.
- Realtime sidebar updates work across two tabs.
- Emails are delivered from the verified domain.
- Sitemap, robots, RSS, and
llms.txtopen publicly. - Private dashboard and admin routes are not indexable.
First Admin
Create your first production user through the normal sign up flow, then promote that user in the production database.
Set the role field to admin in the User table.
Only do this for trusted operator accounts.