A full-stack SaaS starter template built with SvelteKit, Convex, and modern web technologies.
git clone <your-repo-url>
cd saas-starter
bun install
# Initialize Convex project
bunx convex dev
Create .env.local:
CONVEX_DEPLOYMENT=your-deployment-name
PUBLIC_CONVEX_URL=https://your-deployment-name.convex.cloud
https://[your-deployment-name].convex.site/api/auth/callback/googlebunx convex env set AUTH_GOOGLE_ID your_google_client_id
bunx convex env set AUTH_GOOGLE_SECRET your_google_client_secret
This project uses Resend for production-ready email delivery.
[email protected] for testing)# Set your Resend API key
bunx convex env set RESEND_API_KEY re_xxxxxxxxxxxx
# Set your sender email address
bunx convex env set AUTH_EMAIL "[email protected]"
For testing: You can use [email protected] as your sender while in development.
For email event tracking (delivery confirmations, bounces, etc.):
https://your-deployment-name.convex.site/resend-webhook
bunx convex env set RESEND_WEBHOOK_SECRET whsec_xxxxxxxxxxxx
bun run dev
Visit http://localhost:5173 to see your app!
The admin panel requires at least one admin user. To promote your first admin:
Sign up with the email you want to be admin
Run the seed command:
bunx convex run admin/mutations:seedFirstAdmin '{"email":"[email protected]"}'
This is a one-time setup. The command will:
Note: After the first admin is set up, additional admins can be promoted via the Admin Panel โ Users page.
If you had admin users before the notification preferences feature was added, run this one-time migration to sync them:
bunx convex run admin/notificationPreferences/mutations:syncAllAdminPreferences
This ensures all existing admins appear in the Admin Settings โ Notification Recipients page. Safe to run multiple times.
bun run dev - Start development serverbun run build - Build for productionbun run preview - Preview production buildbun run test - Run all tests (E2E + unit)bun run test:e2e - Run E2E tests onlybun run test:unit - Run unit tests onlybun run lint - Lint codebun run format - Format codesrc/
โโโ lib/
โ โโโ convex/ # Convex backend functions and schema
โ โโโ demo/ # Demo chat application components
โ โโโ svelte/ # Svelte auth components
โ โโโ sveltekit/ # SvelteKit auth utilities
โโโ routes/
โ โโโ +layout.svelte # Root layout with auth setup
โ โโโ +page.svelte # Home page
โ โโโ product/ # Protected product page
โ โโโ signin/ # Sign-in page
โโโ app.html # HTML template
This starter includes a complete authentication system:
See SvelteKit Auth Documentation for detailed setup and usage.
Powered by Convex:
See Convex Documentation for schema and functions.
Configure test environment variables:
# Copy the example file
cp .env.test.example .env.test
# Edit .env.test and ensure it contains:
# AUTH_E2E_TEST_SECRET=test-secret
# PUBLIC_E2E_TEST=true
Configure Convex backend:
# Set the test secret in your Convex deployment
bunx convex env set AUTH_E2E_TEST_SECRET test-secret
# Initialize test data
bunx convex run tests:init
For GitHub Actions (CI/CD):
AUTH_E2E_TEST_SECRET: Set to test-secretTEST_CONVEX_URL: Your development Convex URL (for running tests)PUBLIC_CONVEX_URL: Your production Convex URL (for deployment).github/workflows/quality-checks.ymlInstall Playwright and run tests:
# Install Playwright
bunx playwright install
# Run tests
bun run test:e2e
Important: The AUTH_E2E_TEST_SECRET must be configured in three places:
.env.test file (for local development)Note: CI/CD tests run against the development Convex deployment to keep production data clean. The TEST_CONVEX_URL secret points to your development environment while PUBLIC_CONVEX_URL is used for production deployments.
bun run test:unit
Get your Convex deployment URL and deploy key:
.env.local for PUBLIC_CONVEX_URL (e.g., https://intent-snake-818.convex.cloud)Set environment variables in Vercel:
Without Convex Pro, preview deployments should use your development Convex deployment while production uses your production deployment.
Using Vercel CLI:
# Production environment (uses production Convex)
echo "https://your-prod-deployment.convex.cloud" | vercel env add PUBLIC_CONVEX_URL production
echo "prod:your-prod-deployment|your-prod-key" | vercel env add CONVEX_DEPLOY_KEY production
# Preview environment (uses development Convex)
echo "https://your-dev-deployment.convex.cloud" | vercel env add PUBLIC_CONVEX_URL preview
echo "dev:your-dev-deployment|your-dev-key" | vercel env add CONVEX_DEPLOY_KEY preview
Or via Vercel Dashboard:
For Production:
PUBLIC_CONVEX_URL: Your production Convex URLCONVEX_DEPLOY_KEY: Your production deploy key (prod:...)For Preview (PR deployments):
PUBLIC_CONVEX_URL: Your development Convex URLCONVEX_DEPLOY_KEY: Your development deploy key (dev:...)Why this setup?
With Convex Pro, you can create separate preview deployments for each PR.
Using Vercel CLI:
# Set production Convex for both environments
echo "https://your-deployment.convex.cloud" | vercel env add PUBLIC_CONVEX_URL production preview
echo "prod:your-deployment|your-key" | vercel env add CONVEX_DEPLOY_KEY production preview
Or via Vercel Dashboard:
PUBLIC_CONVEX_URL: Your production Convex URLCONVEX_DEPLOY_KEY: Your production deploy keySee Convex Preview Deployments for more details.
Configure Build Command:
Vercel needs to deploy your Convex functions before building SvelteKit to generate the required _generated files.
Via Vercel Dashboard (Recommended):
bunx convex deploy --cmd 'bun run build'Why this is needed:
_generated directory is gitignored (as it should be)bunx convex deploy deploys your Convex functions and generates these filesbun run build to build your SvelteKit appENOENT: no such file or directory errorsNote: Use the Project Settings section (not Production Overrides) so both production and preview deployments work correctly.
Deploy:
vercel --prod
With CONVEX_DEPLOY_KEY set, your workflow is simple:
bunx convex dev # Updates dev deployment locally
# Make changes
git push # Automatically deploys BOTH frontend + Convex functions to production
# Set production OAuth credentials
bunx convex env set AUTH_GOOGLE_ID your_google_client_id --prod
bunx convex env set AUTH_GOOGLE_SECRET your_google_client_secret --prod
# Set production email configuration
bunx convex env set RESEND_API_KEY your_resend_api_key --prod
bunx convex env set AUTH_EMAIL "[email protected]" --prod
bunx convex env set RESEND_WEBHOOK_SECRET your_webhook_secret --prod
After deploying to production, set up your first admin:
Sign up on your production site with your admin email
Run the seed command against production:
bunx convex run admin/mutations:seedFirstAdmin '{"email":"[email protected]"}' --prod
This enables access to the Admin Panel at /admin.
src/lib/convex/auth.config.tssrc/app.css for global stylestailwind.config.jssrc/lib/convex/schema.ts to add your data modelssrc/lib/convex/ for your business logicgit checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)MIT License - see the LICENSE file for details.