Skip to main content
RefactKit uses Nitro v3 as its server engine, which means a single codebase can target Vercel, Cloudflare Workers, or a standalone Node.js server by changing one environment variable at build time. Vercel is the primary and recommended deployment target — the package.json build script defaults to NITRO_PRESET=vercel. This page covers the pre-deploy checklist, Vercel setup, and alternative deployment targets.

Pre-deploy checklist

Run these commands in order before every production deployment. They catch type errors, test regressions, and schema drift before your code reaches users:
pnpm check           # Biome lint + format check
pnpm test            # Unit and integration tests (Vitest)
pnpm test:e2e        # End-to-end tests (Playwright)
npx drizzle-kit push # Sync schema changes to production database
Run npx drizzle-kit push against your production database by ensuring DATABASE_URL in your environment points to the production Supabase project before running the command. Schema drift between your code and the live database will cause runtime errors.

Deployment targets

Vercel is the recommended deployment target. The package.json build command is pre-configured:
# build command (already set in package.json)
NITRO_PRESET=vercel vite build

Deploy steps

  1. Push your repository to GitHub (or GitLab / Bitbucket).
  2. Go to vercel.comAdd New Project → import your repository.
  3. Vercel auto-detects the build command from package.json. Confirm the framework preset is Other (not Next.js).
  4. Before clicking Deploy, open Environment Variables and add every variable from the table below.
  5. Click Deploy.

Required environment variables

Set these in Vercel Dashboard → Project → Settings → Environment Variables:
VariableExample valueNotes
DATABASE_URLpostgresql://postgres.[ref]:...@...pooler.supabase.com:6543/postgresMust use port 6543 (transaction pooler)
BETTER_AUTH_SECREToutput of openssl rand -base64 32Minimum 32 characters
BETTER_AUTH_URLhttps://your-domain.comYour Vercel deployment URL or custom domain
RESEND_API_KEYre_...From Resend dashboard
EMAIL_FROMRefactKit <noreply@yourdomain.com>Must match a verified Resend domain
VITE_SUPABASE_URLhttps://xxxx.supabase.coFrom Supabase → Project Settings → API
SUPABASE_SERVICE_ROLE_KEYeyJhbGci...From Supabase → Project Settings → API → service_role
VITE_APP_URLhttps://your-domain.comOptional — overrides the auth client base URL
Rotating BETTER_AUTH_SECRET invalidates all existing user sessions immediately. Every logged-in user will be signed out. Plan any secret rotation during low-traffic windows and communicate the impact in advance.
VITE_ prefixed variables are embedded into the client bundle at build time. Never set SUPABASE_SERVICE_ROLE_KEY or RESEND_API_KEY with a VITE_ prefix — doing so would expose them to every browser that loads your app.

Custom domain

After the initial deployment succeeds, go to Vercel Dashboard → Project → Settings → Domains and add your custom domain. Update BETTER_AUTH_URL and VITE_APP_URL to match the custom domain, then redeploy.

Environment variable reference

The table below summarizes every variable and where it is consumed:
VariableRequiredRuntimeDescription
DATABASE_URLServerSupabase PostgreSQL connection string — port 6543
BETTER_AUTH_SECRETServerSession signing secret — minimum 32 characters
BETTER_AUTH_URLServerPublic URL of your app — used in email links and OAuth callbacks
RESEND_API_KEYServerResend API key for transactional email
EMAIL_FROMServerSender address shown in outgoing emails
VITE_SUPABASE_URLBothSupabase project URL — embedded in client bundle
SUPABASE_SERVICE_ROLE_KEYServer onlySupabase service role key — bypasses RLS, never expose client-side
BETTER_AUTH_API_KEYOptionalServerEnables the Better Auth admin dashboard at /api/auth/dashboard
VITE_APP_URLOptionalBothOverrides the base URL for the auth client