Deployment Guide
Deploy Kosuke Template to production in 60-90 minutes. This guide covers forking the repository, setting up all services, and configuring your production environment.
Prerequisitesβ
Required Accountsβ
Create accounts with these services (all have free tiers):
| Service | Purpose | Free Tier | Sign Up |
|---|---|---|---|
| GitHub | Source code hosting | Yes | github.com |
| Vercel | Application hosting | Yes (Hobby) | vercel.com |
| Neon | PostgreSQL database | Yes (3 GB) | Via Vercel integration |
| Fly.io | Microservice hosting | Yes (3 VMs) | fly.io |
| Stripe | Billing & subscriptions | Test mode | stripe.com |
| Clerk | Authentication | Yes (10k MAUs) | clerk.com |
| Resend | Email delivery | Yes (100/day) | resend.com |
| Sentry | Error monitoring | Yes (5k events) | sentry.io |
Step 1: Fork Repositoryβ
Fork to Your Accountβ
- Visit github.com/Kosuke-Org/kosuke-template
- Click Fork button (top-right)
- Configure fork:
- Owner: Your GitHub account
- Repository name:
your-project-name(kebab-case) - Copy main branch only: β Checked
- Click Create fork
Good Names: my-saas, startup-mvp, customer-portal
Avoid: My App, MyApp123, my_app
Step 2: Create Vercel Projectβ
Import Repositoryβ
- Go to vercel.com/new
- Sign in with GitHub
- Click Import Git Repository
- Select your forked repository
- Click Import
Configure Projectβ
- Project Name: Same as repository name
- Framework Preset: Next.js (auto-detected)
- Root Directory:
./(default) - Build Settings: Leave defaults
Deployβ
Click Deploy and wait for build.
First deployment will fail with:
Error: POSTGRES_URL environment variable is not set
This is expected! We'll fix this in the next steps.
Set Up Blob Storageβ
- In Vercel project, go to Storage tab
- Click Create Database
- Select Blob
- Name:
your-project-name-blob - Click Create
Vercel automatically adds BLOB_READ_WRITE_TOKEN environment variable.
Step 3: Set Up Neon Databaseβ
Create via Vercel Integrationβ
- In Vercel project, go to Storage tab
- Click Create Database
- Select Neon
- Choose:
- Create new Neon account (sign up with GitHub), OR
- Link existing account (if you have one)
- Create database:
- Region: Choose closest to users
- Name:
your-project-name-db - Environments: Production, Preview, Development
- Create Database Branch for Deployment: Preview
- Click Create
Automatic Configurationβ
Vercel adds these environment variables:
POSTGRES_URL(pooled connection - we use this)
Preview Branchesβ
Neon automatically creates database branches for pull requests:
- PR opened β Database branch created
- PR closed β Branch deleted
- Isolated testing per PR
Configure Automated Branch Cleanup (Optional)β
The template includes GitHub Actions automation to clean up preview branches when PRs are closed. This requires Neon API access:
- Go to Neon Dashboard β Settings
- Navigate to API Keys section
- Create new API key: Click Create API key
- Copy the key
- Add to GitHub Secrets (Settings β Secrets and variables β Actions):
- Name:
NEON_API_KEY - Secret: [paste your Neon API key]
- Name:
NEON_PROJECT_ID - Secret: [find in Neon Dashboard β Project Settings]
- Name:
The cleanup script (.github/scripts/cleanup-neon-branch.mjs) automatically runs when PRs close, deleting orphaned preview branches to save resources.
Step 4: Configure Stripe Billingβ
Choose Modeβ
Start in Stripe test mode (shown as Sandbox in the dashboard) and switch to live only when you are ready to charge real cards:
- Dashboard: dashboard.stripe.com/dashboard
- Click your organization name (top-left) β Switch to a sandbox
- No real chargesβperfect for end-to-end testing
Create Productsβ
Product 1: Pro Planβ
- Go to Products β Create Product
- Configure:
- Name:
Pro Plan - Description:
Professional subscription with advanced features - Recursion:
Recurring - Amount:
$20.00 USD per month - Billing Interval:
Monthly
- Name:
- Click Save product
- Under Pricing, open the recurring price Stripe created
- Copy the Price ID:
price_abc123...
Product 2: Business Planβ
- Click Create Product again
- Configure:
- Name:
Business Plan - Description:
Business subscription with premium features and priority support - Recursion:
Recurring - Price:
$200.00 USD per month - Billing Interval:
Monthly
- Name:
- Click Save product
- Under Pricing, open the recurring price
- Copy the Price ID:
price_xyz789...
Create API Tokenβ
- Go to Developers β API keys
- Copy the Publishable key (test mode):
pk_test_... - Click Reveal test key and copy the Secret key:
sk_test_...
Set Up Webhookβ
- Go to Webhooks β Add Endpoint
- Configure:
- Endpoint URL:
https://your-project-name.vercel.app/api/billing/webhook - Events:
- β
customer.subscription.created - β
customer.subscription.updated - β
customer.subscription.deleted - β
invoice.paid - β
invoice.payment_failed - β
subscription_schedule.completed - β
subscription_schedule.canceled
- β
- Endpoint URL:
- Copy Signing Secret
Update the environment variables in Vercel:
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PRO_PRICE_ID=price_...
STRIPE_BUSINESS_PRICE_ID=price_abc123...
STRIPE_WEBHOOK_SECRET=whsec_xyz789...
STRIPE_SUCCESS_URL=https://your-project-name.vercel.app/settings/billing
STRIPE_CANCEL_URL=https://your-project-name.vercel.app/settings/billing
Step 5: Configure Clerk Authenticationβ
Create Account & Applicationβ
- Go to dashboard.clerk.com
- Sign up with GitHub
- Click Add application
- Configure:
- Application name: Your project name
- Framework: Next.js
- Click Create application
Get API Keysβ
Copy these keys immediately:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
Enable Organizationsβ
- Go to Settings β Organizations
- Toggle Enable Organizations to ON
- Configure:
- Organization naming: β Allow custom names
- Default roles: admin, member (recommended)
- Allow Personal Accounts: ON
- Sessions Claims __session:
{
"publicMetadata": "{{user.public_metadata}}"
} - Enable Organization Slugs: ON
- Click Save
Set Up Webhookβ
- Go to Webhooks β Add Endpoint
- Configure:
- Endpoint URL:
https://your-project-name.vercel.app/api/clerk/webhook - Subscribe to events:
- β
User:
user.created,user.updated,user.deleted - β
Organization:
organization.created,organization.updated,organization.deleted - β
Membership:
organizationMembership.created,organizationMembership.updated,organizationMembership.deleted
- β
User:
- Endpoint URL:
- Copy Signing Secret (starts with
whsec_)
Update the environment variables in Vercel:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...
# URLs (use these exact values)
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/onboarding
Step 6: Configure Resend Emailβ
Create Account & API Keyβ
- Go to resend.com
- Sign up with email
- Verify email address
- Go to API Keys β Create API Key
- Configure:
- Name:
your-project-api - Permission: Full access
- Name:
- Copy API key (starts with
re_)
Email Configurationβ
For development, use Resend's test domain:
RESEND_API_KEY=re_...
RESEND_FROM_EMAIL=onboarding@resend.dev
RESEND_FROM_NAME=Your Project Name
# RESEND_REPLY_TO=support@yourdomain.com # Optional
For production, verify your custom domain:
- Go to Domains β Add Domain
- Enter
yourdomain.com - Add DNS records (SPF, DKIM, DMARC)
- Wait for verification
- Update:
RESEND_FROM_EMAIL=hello@yourdomain.com
Step 7: Configure Sentry Monitoringβ
Create Account & Projectβ
- Go to sentry.io
- Sign up with GitHub
- Click Create Project
- Configure:
- Platform: Next.js
- Project name: your-project-name
- Team: Default team
- Click Create Project
Get DSNβ
Copy your DSN:
NEXT_PUBLIC_SENTRY_DSN=https://hash@region.ingest.sentry.io/project-id
Find it in: Settings β Projects β [Your Project] β Client Keys (DSN)
Configurationβ
The template includes Sentry configuration with:
- Error tracking enabled
- Performance monitoring (10% sample rate)
- Session replay (10% normal, 100% on errors)
- Automatic source map upload
Adjust sample rates in sentry.*.config.ts if needed.
Step 8: Deploy Engine Microservice (Fly.io)β
The template includes a Python FastAPI microservice that runs on Fly.io. This service provides additional backend functionality and can be extended with custom business logic.
Install Fly CLIβ
macOS:
curl -L https://fly.io/install.sh | sh
Windows (PowerShell):
pwsh -Command "iwr https://fly.io/install.ps1 -useb | iex"
Linux:
curl -L https://fly.io/install.sh | sh
Verify installation:
fly version
Create Fly.io Accountβ
- Sign up at fly.io
- Log in via CLI:
fly auth login
Deploy Engine Serviceβ
- Navigate to engine directory:
cd engine
- Launch application:
fly launch
-
Configure deployment:
- App name:
your-project-engine(or use auto-generated) - Region: Choose closest to users (same as Neon database)
- PostgreSQL: No (we use Neon)
- Redis: No (unless needed)
- Deploy now: No (set secrets first)
- App name:
-
Copy your app URL:
https://your-project-engine.fly.dev
Set Environment Variablesβ
Set secrets for the engine service via CLI:
# Sentry monitoring (use same DSN as main app)
fly secrets set SENTRY_DSN=https://hash@region.ingest.sentry.io/project-id
# Frontend URL for CORS configuration
fly secrets set FRONTEND_URL=https://your-project-name.vercel.app
# API secret key for authentication (generate with: openssl rand -base64 32)
fly secrets set API_SECRET_KEY=<random-secure-token>
Generate secure API key:
openssl rand -base64 32
Alternative: Set via Fly.io Dashboard:
You can also manage secrets through the web UI:
- Go to fly.io/dashboard
- Select your app β Secrets
- Click Add Secret for each variable
- Enter Name and Value
- Click Set Secret
CLI secrets automatically trigger a deployment. Dashboard secrets require manual deployment via fly deploy or the UI.
Deployβ
fly deploy
Wait for deployment to complete (~2-3 minutes).
Verify Deploymentβ
Test health endpoint:
curl https://your-project-engine.fly.dev/health
Expected response:
{
"status": "healthy",
"service": "engine-service",
"timestamp": "2025-10-14T10:00:00.000000"
}
Visit API docs: https://your-project-engine.fly.dev/docs
Fly.io Configurationβ
The engine is configured to:
- Auto-scale: Scales to 0 when idle (free tier friendly)
- Auto-start: Starts on first request (2-3s cold start)
- Health checks: Monitors
/healthendpoint every 30s - HTTPS: Forced HTTPS with automatic certificates
- Region: Deploys to your selected region
Cost: Free tier includes 3 shared-cpu VMs with 256MB RAM each.
Step 9: Configure GitHub Actions Secretsβ
The template includes GitHub Actions for automated PR reviews and microservice deployment. Configure repository secrets to enable these features.
Navigate to GitHub Secretsβ
- Go to your forked repository on GitHub
- Click Settings β Secrets and variables β Actions
- Click New repository secret
Required Secretsβ
1. Anthropic API Key (Claude AI)β
Enables AI-powered PR reviews and issue assistance via Claude.
Get API Key:
- Go to console.anthropic.com
- Sign up or log in
- Navigate to API Keys
- Click Create Key
- Copy the key (starts with
sk-ant-)
Add to GitHub:
- Name:
ANTHROPIC_API_KEY - Secret:
sk-ant-api03-...
Usage:
- Mention
@claudein pull requests for code reviews - Mention
@claudein issues for assistance - Automated PR analysis and suggestions
2. Fly.io API Token (Microservice Deployment)β
Enables automatic deployment of the engine microservice on pull requests and pushes.
Get API Token:
fly auth token
Or via dashboard:
- Go to fly.io/user/personal_access_tokens
- Click Create token
- Name:
github-actions-deploy - Copy the token
Add to GitHub:
- Name:
FLY_API_TOKEN - Secret:
fo1_...
Usage:
- Automatic engine deployment on main branch pushes
- Preview deployments for pull requests
3. OpenAI API Key (Codex PR Reviews)β
Optional: Enables additional AI-powered code review features.
Get API Key:
- Go to platform.openai.com/api-keys
- Sign up or log in
- Click Create new secret key
- Name:
github-actions-pr-review - Copy the key (starts with
sk-)
Add to GitHub:
- Name:
OPENAI_API_KEY - Secret:
sk-...
Usage:
- Enhanced PR review with Codex analysis
- Code quality suggestions
- Security vulnerability detection
Verify Configurationβ
After adding secrets:
- Go to Actions tab in your repository
- Secrets should be available to workflows
- Test by creating a pull request
- Check Actions logs for successful API connections
Step 10: Add Environment Variablesβ
Navigate to Vercelβ
- Go to Vercel dashboard β Your project
- Click Settings β Environment Variables
Add All Variablesβ
For each variable, click Add New and:
- Enter Key and Value
- Select Production, Preview, and Development
- Click Save
Complete Variable Listβ
# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/onboarding
# Stripe Billing
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_PRO_PRICE_ID=price_...
STRIPE_BUSINESS_PRICE_ID=price_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_SUCCESS_URL=https://your-project-name.vercel.app/settings/billing
STRIPE_CANCEL_URL=https://your-project-name.vercel.app/settings/billing
# Sentry Monitoring
NEXT_PUBLIC_SENTRY_DSN=https://...@....ingest.sentry.io/...
# Resend Email
RESEND_API_KEY=re_...
RESEND_FROM_EMAIL=onboarding@resend.dev
RESEND_FROM_NAME=Your Project Name
# Engine Microservice
ENGINE_BASE_URL=https://your-project-engine.fly.dev
# Application
NEXT_PUBLIC_APP_URL=https://your-project-name.vercel.app
NODE_ENV=production
# Cron Security (generate with: openssl rand -base64 32)
CRON_SECRET=<random-secure-token>
# Database & Storage (already added by Vercel)
# POSTGRES_URL=postgresql://...@neon.tech/...
# BLOB_READ_WRITE_TOKEN=vercel_blob_rw_...
Redeployβ
Trigger new deployment:
git commit --allow-empty -m "Configure environment variables"
git push
Or in Vercel: Deployments β β― β Redeploy
Verify Deploymentβ
- β Deployment status: Ready
- Visit:
https://your-project-name.vercel.app - Test sign-in/sign-up
- Verify no errors in console
π Your application is now live!
Going to Productionβ
When ready to launch with real payments and custom domain:
Transition Stripe to Productionβ
- Go to dashboard.stripe.com
- Activate your account (remove test mode)
- Create same products (Pro $20, Business $200)
- Get production API keys from Developers β API keys
- Set up production webhook:
https://yourdomain.com/api/billing/webhook - Update environment variables:
STRIPE_SECRET_KEY=sk_live_...
STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_PRO_PRICE_ID=[production_pro_price_id]
STRIPE_BUSINESS_PRICE_ID=[production_business_price_id]
STRIPE_WEBHOOK_SECRET=[production_webhook_secret]
STRIPE_SUCCESS_URL=https://yourdomain.com/billing/success
STRIPE_CANCEL_URL=https://yourdomain.com/settings/billing - Redeploy
Add Domain to Vercelβ
- Go to Settings β Domains
- Click Add Domain
- Enter
yourdomain.com - Configure DNS:
A Record (root domain):
Type: A
Name: @
Value: 76.76.21.21
CNAME Record (www):
Type: CNAME
Name: www
Value: cname.vercel-dns.com
- Wait for verification (up to 48 hours, usually 1-2 hours)
Update Environment Variablesβ
Vercel:
NEXT_PUBLIC_APP_URL=https://yourdomain.com
# ENGINE_BASE_URL remains the same (Fly.io subdomain)
Fly.io Engine:
fly secrets set FRONTEND_URL=https://yourdomain.com
Update Service Webhooksβ
Update webhook URLs in all services:
- Clerk:
https://yourdomain.com/api/clerk/webhook - Stripe:
https://yourdomain.com/api/billing/webhook
Configure Clerk for Productionβ
- Settings β Domain: Add
yourdomain.com - Webhooks: Update endpoint URL to production domain
- OAuth Providers (optional):
- Configure Google OAuth with production credentials
- Configure GitHub OAuth with production credentials
- Update redirect URIs to production domain
Configure Resend Custom Domainβ
- Go to Resend dashboard β Domains
- Click Add Domain
- Enter
yourdomain.com - Add DNS records:
SPF Record:
Type: TXT
Name: @
Value: v=spf1 include:resend.com ~all
DKIM Record:
Type: TXT
Name: resend._domainkey
Value: [provided by Resend]
DMARC Record (recommended):
Type: TXT
Name: _dmarc
Value: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
- Wait for verification
- Update environment variable:
RESEND_FROM_EMAIL=hello@yourdomain.com