Deployment
This guide covers deploying your CraftJS application to production.
Vercel (Recommended)
CraftJS is optimized for Vercel deployment.
Push to GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/yourusername/your-app.git
git push -u origin mainImport to Vercel
- Go to vercel.com/new
- Import your GitHub repository
- Vercel auto-detects Next.js settings
Configure Environment Variables
In Project Settings > Environment Variables, add all your secrets:
DATABASE_URL=postgresql://...
BETTER_AUTH_SECRET=...
BETTER_AUTH_URL=https://your-app.vercel.app
OPENAI_API_KEY=...
# ... all other variablesMake sure BETTER_AUTH_URL matches your production domain.
Deploy
Click “Deploy” and Vercel will:
- Install dependencies
- Build the application
- Deploy to the edge network
Configure Custom Domain (Optional)
- Go to Project Settings > Domains
- Add your custom domain
- Update DNS records as instructed
- Update
BETTER_AUTH_URLto your domain
Other Platforms
Railway
Install Railway CLI
npm install -g @railway/cli
railway loginDeploy
railway init
railway upConfigure
Add environment variables in the Railway dashboard.
Render
Create Web Service
- Go to render.com
- Create a new Web Service
- Connect your GitHub repo
Configure Build
- Build Command:
pnpm install && pnpm build - Start Command:
pnpm start
Environment Variables
Add all environment variables in the dashboard.
Docker
Create a Dockerfile:
# Dockerfile
FROM node:20-alpine AS base
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# Dependencies
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# Builder
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm build
# Runner
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
CMD ["node", "server.js"]Update next.config.ts:
const nextConfig = {
output: "standalone",
}Build and run:
docker build -t my-app .
docker run -p 3000:3000 --env-file .env my-appProduction Checklist
Environment Variables
Ensure all required variables are set:
# Required
DATABASE_URL=postgresql://...
BETTER_AUTH_SECRET=... # At least 32 characters
BETTER_AUTH_URL=https://your-domain.com
# At least one AI provider
OPENAI_API_KEY=sk-...
# For full functionality
RESEND_API_KEY=re_...
UPSTASH_REDIS_REST_URL=...
UPSTASH_REDIS_REST_TOKEN=...
DODO_API_KEY=...
DODO_WEBHOOK_SECRET=...Database
Run Migrations
pnpm db:migrateVerify Connection
Test your production database connection before deploying.
Set Up Backups
Enable automated backups in Neon or your database provider.
Security
Production security checklist:
- Use HTTPS - Vercel handles this automatically
- Strong secrets - Generate with
openssl rand -hex 32 - Secure cookies - Better Auth handles this
- Rate limiting - Configure for production load
- CORS settings - Restrict to your domains
- Content Security Policy - Configure in headers
Headers
Add security headers in next.config.ts:
const nextConfig = {
async headers() {
return [
{
source: "/:path*",
headers: [
{
key: "X-DNS-Prefetch-Control",
value: "on",
},
{
key: "Strict-Transport-Security",
value: "max-age=63072000; includeSubDomains; preload",
},
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "X-XSS-Protection",
value: "1; mode=block",
},
{
key: "Referrer-Policy",
value: "origin-when-cross-origin",
},
],
},
]
},
}Performance
- Enable caching - Use Redis for frequently accessed data
- Optimize images - Use Next.js Image component
- Code splitting - Next.js handles this automatically
- Edge functions - Deploy API routes to the edge
Monitoring
Error Tracking
Add Sentry for error tracking:
pnpm add @sentry/nextjs// sentry.client.config.ts
import * as Sentry from "@sentry/nextjs"
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 0.1,
})Webhooks
Update webhook URLs in provider dashboards:
| Provider | Webhook URL |
|---|---|
| Dodo Payments | https://your-domain.com/api/webhooks/dodo |
| Resend | https://your-domain.com/api/webhooks/resend |
| Trigger.dev | Automatic |
DNS & Email
For email deliverability:
- Verify domain in Resend
- Add SPF record - Provided by Resend
- Add DKIM record - Provided by Resend
- Add DMARC record - For email authentication
Rollback Strategy
Vercel
# List deployments
vercel ls
# Rollback to previous deployment
vercel rollbackDatabase
Always backup before migrations:
# Backup current state
pg_dump $DATABASE_URL > backup.sql
# Restore if needed
psql $DATABASE_URL < backup.sqlScaling
Vercel Pro/Enterprise
- Increased function duration
- More concurrent executions
- Team collaboration
Database Scaling
Neon scales automatically. For high load:
- Enable connection pooling
- Consider read replicas
Redis Scaling
Upstash scales automatically. Monitor usage in dashboard.
CI/CD
Example GitHub Actions workflow:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- run: pnpm install
- run: pnpm lint
- run: pnpm build
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: "--prod"Next Steps
- Configuration - Production config
- Caching - Production caching
- Analytics - Production monitoring