Go Live
Ship your app to production. BetterStarter works with any hosting platform that supports Node.js.
Important Note:
[!TIP] I highly recommend deploying your project to a production server long before the application is "finished."
You don’t have to market it yet—just get it live. Why? Because you want to shrink the distance between zero and one as quickly as possible.
Deploying a feature-heavy app is exponentially more complex than deploying a skeleton. By going live today, you establish a working baseline. From that point on, every new feature is just an incremental update rather than a massive, high-stakes hurdle.
If you wait for perfection, you’ll likely never ship. And if you do, the technical debt of that "big bang" deployment will be 100x harder to manage.
Service Providers Needed
You need 2 hosting providers:
Environment Variables
BetterStarter uses T3 Env for environment variable management, which means the app will fail to start if required variables are missing. This forces you to be intentional about your configuration.
Setup Your Production Variables
- Copy
.env.localto.env.production(won't be committed, but used by your hosting provider) - Update all values to your production configuration
- Set
DATABASE_URLto your production PostgreSQL database - Update
APP_BASE_URLandBETTER_AUTH_URLto your production domain - Run database migrations:
pnpm db:migrate
Required Environment Variables
Set all of these in your production environment:
APP_BASE_URL=https://yourdomain.com
DATABASE_URL=postgres://...
BETTER_AUTH_URL=https://yourdomain.com
BETTER_AUTH_SECRET=<random-secret>
PLUNK_SECRET_API_KEY=...
TRANSACTIONAL_EMAIL=noreply@yourdomain.com
GOOGLE_CLIENT_SECRET=...
VITE_GOOGLE_CLIENT_ID=...
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
VITE_STRIPE_PRODUCT_CORE_ID=prod_...
VITE_STRIPE_PRICE_CORE_ONE_TIME_ID=price_...
VITE_STRIPE_PROMOTION_CODE_ID=promo_...If you're not using Stripe, Google Auth, or other services, use dummy values for now. You can remove unused variables later by updating src/env.ts.
Production Database Change Workflow
Use a migration-first workflow for production changes:
- Update your Drizzle schema in
src/db/schema/ - Generate a migration with
pnpm db:generate - Review the generated SQL in
drizzle/before applying it - Apply and verify the migration in a staging environment first
- Back up your production database
- Run
pnpm db:migrateagainst production - Verify app health and key user flows after deployment
Notes:
- Avoid using
db:pushin production except for very early projects or throwaway environments - Prefer additive, backward-compatible migrations first, then remove old columns/tables in a follow-up deploy
Vercel
The repo includes a vercel.json that configures the build automatically.
- Push your repo to GitHub
- Import the project in the Vercel dashboard
- Add all environment variables from
.env.productionin the Vercel project settings - Deploy. Vercel will run
pnpm buildautomatically
// vercel.json (already included)
{
"installCommand": "pnpm i",
"buildCommand": "pnpm build",
"devCommand": "pnpm dev",
"outputDirectory": ".output"
}Netlify
A netlify.toml is included in the repo.
- Push your repo to GitHub
- Import the project in the Netlify dashboard
- Add all environment variables in Site settings → Environment variables
- Deploy
# netlify.toml (already included)
[build]
command = "pnpm build"
publish = "dist"
functions = "dist/server"Cloudflare Pages
See guide on Tankstack Start for Cloudflare Deployment
Other Platforms
BetterStarter builds to a standard Node.js server. Any platform that can run Node.js will work.
Railway / Render / Fly.io