Deployment Overview
PancakeJS applications can be deployed anywhere that runs Node.js or supports serverless functions.
Build for Production
# Build all packages
pnpm universal-apps buildThis generates:
- Server bundle ready for Node.js
- Widget HTML files in
dist/widgets/
Directory Structure After Build
dist/
├── server/
│ └── index.js # Compiled server
└── widgets/
├── widget1.html # Standalone widget HTML
└── widget2.htmlDeployment Options
☁️ Cloudflare Workers
Edge-first deployment with global distribution. Recommended for best latency.
▲ Vercel
Zero-config deployment for Next.js applications.
🚂 Railway
Simple container deployments with automatic SSL.
🐳 Docker
Self-hosted deployments on any infrastructure.
Node.js Server
Deploy to any Node.js hosting:
# Start production server
pnpm universal-apps start --port 8080Recommended platforms:
- Railway
- Render
- Fly.io
- DigitalOcean App Platform
- AWS ECS/Fargate
Serverless Functions
Adapt for serverless with minor changes:
// For Vercel/AWS Lambda
export default async function handler(req, res) {
const runtime = app.getRuntime();
const result = await runtime.executeToolCall(
req.body.tool,
req.body.input
);
res.json(result);
}Docker
FROM node:20-alpine
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile --prod
COPY dist ./dist
EXPOSE 3000
CMD ["node", "dist/server/index.js"]Widget Hosting
Widgets are standalone HTML files that can be served from:
Static Hosting (Recommended)
- Cloudflare Pages
- Vercel
- Netlify
- AWS S3 + CloudFront
# Upload dist/widgets to your CDN
aws s3 sync dist/widgets s3://my-bucket/widgets/Same Server
Serve widgets from your main server:
app.listen({
port: 3000,
dev: false,
// Widgets served from dist/widgets by default
});Environment Configuration
Production Config
Create universal-apps.config.ts:
export default {
widgets: {
outDir: 'dist/widgets',
},
csp: {
connectDomains: ['api.production.com', 'analytics.example.com'],
imgDomains: ['images.cdn.com'],
},
};Environment Variables
# .env
PORT=8080
NODE_ENV=production
WIDGET_BASE_URL=https://widgets.myapp.comCSP Configuration
Production widgets should have strict CSP:
app.widget(
{
name: 'myWidget',
ui: {
entry: 'src/widgets/my.tsx',
csp: {
connectDomains: ['api.myapp.com'],
imgDomains: ['images.myapp.com'],
scriptDomains: [], // No external scripts
styleDomains: [], // No external styles
},
},
},
handler
);Health Checks
Add a health endpoint for monitoring:
app.tool(
{
name: '_health',
description: 'Health check endpoint',
},
async () => textResult('OK')
);Security Checklist
- ☐ Enable HTTPS
- ☐ Configure strict CSP
- ☐ Validate all inputs (Zod schemas)
- ☐ Rate limit API endpoints
- ☐ Audit dependencies regularly
- ☐ Enable logging and monitoring
- ☐ Set up error alerting
Next Steps
We recommend starting with Cloudflare Workers for the best performance and developer experience.
- Deploy to Cloudflare — Detailed Cloudflare guide
- Troubleshooting — Debug deployment issues