In SvelteKit, +server.ts files are API route handlers that run on the server. They automatically become serverless functions when deployed.
File Location: Becomes API Endpoint:
/routes/api/dao-agent/+server.ts → https://your-app.com/api/dao-agent
- Development: Runs as a Node.js server locally
- Build: SvelteKit bundles it into a serverless function
- Deploy: Hosting platform runs it as needed (serverless)
-
No Separate Backend Needed
- Frontend and backend in one codebase
- Simplified deployment
- Easier maintenance
-
Serverless by Default
- Auto-scaling
- Pay only for what you use
- No server management
-
Type Safety
- Shared types between frontend and backend
- TypeScript end-to-end
- Fewer bugs
-
Framework Integration
- Built-in routing
- Environment variable handling
- Automatic optimization
Steps:
-
Install Adapter
npm install -D @sveltejs/adapter-netlify
-
Update
svelte.config.jsimport adapter from '@sveltejs/adapter-netlify'; export default { kit: { adapter: adapter() } };
-
Set Environment Variables in Netlify Dashboard
- Go to Site Settings → Environment Variables
- Add your API keys (server-side variables)
-
Deploy
# Option A: CLI netlify deploy --prod # Option B: Git Integration git push origin main
Result:
+server.tsbecomes a Netlify Function- Stored in
.netlify/functions/
Steps:
- Install Adapter
npm install -D @sveltejs/adapter-cloudflare
Verify you have the variable available to the build. Do NOT commit secrets in .env; instead set it in Netlify.
Add PUBLIC_FLOW_NETWORK to your site’s build environment variables (Netlify UI: Site → Site settings → Build & deploy → Environment → New variable) or in netlify.toml:
2. Update svelte.config.js
import adapter from '@sveltejs/adapter-cloudflare';
export default {
kit: {
adapter: adapter()
}
};- Deploy
npm run build npx wrangler pages publish .svelte-kit/cloudflare
Result:
+server.tsbecomes a Cloudflare Worker- Edge computing (very fast!)
When to use:
- Need full control
- Self-hosting
- Specific server requirements
Steps:
-
Install Adapter
npm install -D @sveltejs/adapter-node
-
Update
svelte.config.jsimport adapter from '@sveltejs/adapter-node'; export default { kit: { adapter: adapter() } };
-
Build
npm run build
-
Run
node build/index.js
Result:
- Traditional Node.js server
- You manage the server
- Deploy to VPS, AWS EC2, etc.
# frontend/.env (local only, gitignored)
OPENAI_API_KEY=sk-...
SUPABASE_SERVICE_KEY=...
PUBLIC_SUPABASE_URL=...Server-Side Variables (Secret):
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
SUPABASE_SERVICE_KEY=...
Client-Side Variables (Public):
PUBLIC_SUPABASE_URL=https://...
PUBLIC_FLOW_NETWORK=mainnet
// In +server.ts (server-side)
import { env as PrivateEnv } from '$env/dynamic/private';
const apiKey = PrivateEnv.OPENAI_API_KEY; // ✅ Secure
// In .svelte files (client-side)
import { env as PublicEnv } from '$env/dynamic/public';
const url = PublicEnv.PUBLIC_SUPABASE_URL; // ✅ OK to exposeUser Browser
↓
│ POST /api/dao-agent
│ { messages: [...] }
↓
Serverless Function (Your +server.ts)
↓
│ 1. Receives request
│ 2. Gets API key from env
│ 3. Calls OpenAI/Anthropic
│ 4. Returns response
↓
User Browser
↓
│ Displays AI response
What is it?
- First request after idle period takes longer
- Function needs to "wake up"
- Subsequent requests are fast
Typical Times:
- Cold start: 500ms - 2s
- Warm requests: 50ms - 200ms
Mitigation:
- Use platforms with fast cold starts (Vercel, Cloudflare)
- Keep functions small
- Consider warming strategies for critical paths
- Free Tier: 100GB bandwidth, 100 hours function execution
- Pro: $20/month, more generous limits
- Best for: Most SvelteKit apps
- Free Tier: 100GB bandwidth, 125k function invocations
- Pro: $19/month
- Best for: Static-heavy sites with some API routes
- Free Tier: Unlimited requests, 100k function invocations
- Pro: $20/month
- Best for: Global apps needing edge computing
- Cost: $5-50/month depending on size
- Best for: High traffic, need full control
Platform: Vercel
- Easy setup
- Great DX
- Free tier sufficient
- Automatic deployments
Steps:
# 1. Push to GitHub
git push origin main
# 2. Connect to Vercel
# - Go to vercel.com
# - Import your GitHub repo
# - Add environment variables
# - Deploy!
# 3. Done! Your +server.ts is now livePlatform: Vercel or Cloudflare Pages
- Vercel: If you want simplicity
- Cloudflare: If you want edge performance
Additional Setup:
- Custom domain
- Rate limiting (Cloudflare Workers KV or Upstash Redis)
- Monitoring (Sentry, LogRocket)
- Analytics
npm run build
# Look for:
# ✓ Built server functions
# ✓ Prerendered pages
# ✓ Generated routesnpm run preview
# Test your API:
curl -X POST http://localhost:4173/api/dao-agent \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"test"}]}'# After deployment
curl -X POST https://your-app.vercel.app/api/dao-agent \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"test"}]}'# Check that API key is NOT in client bundle
curl https://your-app.vercel.app/_app/immutable/chunks/*.js | grep -i "sk-"
# Should return nothing!Cause: Environment variable not set in production
Solution:
- Go to platform dashboard
- Add environment variable
- Redeploy
Cause: Dependency not installed or wrong adapter
Solution:
# Ensure correct adapter
npm install -D @sveltejs/adapter-vercel
# Update svelte.config.js
import adapter from '@sveltejs/adapter-vercel';Solutions:
- Use Cloudflare Workers (edge computing)
- Implement warming strategy
- Optimize function size
- Use faster LLM models
Solution: Add CORS headers in +server.ts
export const POST: RequestHandler = async ({ request }) => {
// ... your code ...
return json(response, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
}
});
};# Install
npm install @vercel/analytics
# Add to +layout.svelte
import { inject } from '@vercel/analytics';
inject();// In +server.ts
export const POST: RequestHandler = async ({ request }) => {
console.log('Request received:', {
timestamp: new Date().toISOString(),
// Don't log sensitive data!
});
// ... your code ...
};npm install @sentry/sveltekit
# Configure in hooks.server.ts
import * as Sentry from '@sentry/sveltekit';
Sentry.init({
dsn: 'your-sentry-dsn'
});- Choose hosting platform
- Install correct adapter
- Update
svelte.config.js - Test build locally (
npm run build) - Test preview locally (
npm run preview)
- Set server-side environment variables
- Set client-side environment variables
- Verify no secrets in git history
- Confirm
.envis gitignored
- Push to git
- Connect to hosting platform
- Configure environment variables in dashboard
- Deploy
- Verify deployment
- Test API endpoint
- Verify no API keys in client bundle
- Check error tracking
- Monitor performance
- Set up alerts
- Search YouTube for "Deploy SvelteKit to Vercel"
- SvelteKit official channel
Yes, using +server.ts is absolutely best practice!
Benefits:
- ✅ No separate backend needed
- ✅ Serverless by default
- ✅ Type-safe end-to-end
- ✅ Easy deployment
- ✅ Auto-scaling
- ✅ Cost-effective
For FlowGov:
- Use Vercel (easiest)
- Push to GitHub
- Connect to Vercel
- Add environment variables
- Deploy!
Your +server.ts automatically becomes a secure, scalable API endpoint! 🚀