I kept repeating the same painful cycle: build something in Cursor, then spend 2-3 hours copy-pasting Dockerfiles,
debugging nginx SSL configs, and fixing GitHub Actions YAML before I could actually ship.
So I packaged everything into Vibe Deploy Kit.
## What I built
3 deployment template packs, each covering a different stack:
- next-production-kit → Next.js 14+ to Vercel or self-hosted VPS
- fastapi-deploy-kit → FastAPI + Python to Railway (free tier)
- react-supabase-kit → React + Vite + Supabase to Vercel
## How I built it
Started by listing every file I was copy-pasting project to project. Turned out it was always the same ~5 files:
- Dockerfile (multi-stage, non-root user, Alpine base)
- docker-compose.yml (app + nginx services, healthcheck)
- nginx.conf (rate limiting, SSL, security headers, gzip)
- GitHub Actions workflow (preview on PR, prod on push to main)
- .env.example (every required variable documented)
## next-production-kit — the Dockerfile
Multi-stage build keeps the final image small. Non-root user for security:
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json* pnpm-lock.yaml* yarn.lock* ./
RUN \
if [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
else npm i; fi
FROM node:20-alpine AS runner
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
USER nextjs
CMD ["node", "server.js"]
Requires output: 'standalone' in next.config.js.
## fastapi-deploy-kit — rate limiting
The FastAPI kit uses slowapi so you don't get hammered on Railway's free tier:
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
@app.get("/api/hello")
@limiter.limit("30/minute")
async def hello(request: Request):
return {"message": "Hello"}
## react-supabase-kit — the client setup
One thing vibe-coded apps almost never have is a proper ErrorBoundary. The kit includes one, plus a Supabase client
with auto-refresh:
export const supabase = createClient(url, anonKey, {
auth: {
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true,
},
});
## nginx WebSocket config
If you're self-hosting Next.js, you need this or hot reload breaks:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
## Tools used
- Docker + nginx for self-hosted path
- Vercel + Railway + Supabase for zero-cost cloud path
- GitHub Actions for CI/CD
- Gumroad for distribution
## Result
A ZIP you drop into any project. Fill in .env, push to main → deployed.
Available for $9: peachjed.gumroad.com/l/frosbp
Top comments (0)