diff --git a/assistant/src/config/vellum-skills/deploy-fullstack-vercel/SKILL.md b/assistant/src/config/vellum-skills/deploy-fullstack-vercel/SKILL.md new file mode 100644 index 00000000000..0a9d737aa7d --- /dev/null +++ b/assistant/src/config/vellum-skills/deploy-fullstack-vercel/SKILL.md @@ -0,0 +1,179 @@ +--- +name: "Deploy Fullstack to Vercel" +description: "Build and deploy a full-stack app (React frontend + Python/FastAPI backend) to Vercel as a serverless demo with seeded data" +metadata: {"vellum": {"emoji": "🚀"}} + +--- + +# Deploy Fullstack to Vercel + +Deploy a full-stack app with a React/Vite frontend and Python/FastAPI backend to Vercel as a serverless demo. No auth required — meant for demos, portfolio pieces, and quick showcases. + +## When to Use + +- User says "deploy this to Vercel", "host this", "publish this" +- User has a project with a frontend + backend they want live +- User wants a quick demo deployment (no persistent database needed) + +## Prerequisites + +- A project with a frontend (React/Vite) and backend (FastAPI/Python) +- Vercel CLI installed (`npm install -g vercel`) and authenticated (`vercel login`) + +## Workflow + +### 1. Build the Frontend + +```bash +cd /frontend +npm install +npx vite build +``` + +This produces static files in `frontend/dist/`. + +### 2. Create the Vercel Deploy Directory + +``` +/vercel-deploy/ +├── api/ +│ ├── index.py ← FastAPI app wrapper (entry point) +│ ├── database.py ← DB config (use /tmp for SQLite) +│ ├── models.py +│ ├── schemas.py +│ ├── seed_data.py ← Must seed ALL required data (users, etc.) +│ ├── routers/ +│ │ ├── __init__.py +│ │ └── *.py +│ └── requirements.txt ← Python deps (fastapi, sqlalchemy, pydantic) +├── index.html ← From frontend/dist/ +├── assets/ ← From frontend/dist/assets/ +└── vercel.json +``` + +**Key steps:** +```bash +mkdir -p /vercel-deploy/api + +# Copy frontend build output to deploy root +cp -r /frontend/dist/* /vercel-deploy/ + +# Copy backend files into api/ +cp /backend/models.py /vercel-deploy/api/ +cp /backend/database.py /vercel-deploy/api/ +cp /backend/schemas.py /vercel-deploy/api/ +cp /backend/seed_data.py /vercel-deploy/api/ +cp -r /backend/routers /vercel-deploy/api/ +cp /backend/requirements.txt /vercel-deploy/api/ +``` + +### 3. Create api/index.py (Serverless Entry Point) + +```python +import sys, os +sys.path.insert(0, os.path.dirname(__file__)) + +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from database import engine, Base, SessionLocal +from seed_data import seed_exercises, seed_default_user # all seed functions +from routers import users, exercises, workouts, schedule, progress + +# Create tables and seed on EVERY cold start +Base.metadata.create_all(bind=engine) +db = SessionLocal() +try: + seed_exercises(db) + seed_default_user(db) # IMPORTANT: seed all required data +finally: + db.close() + +app = FastAPI(title="MyApp") + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +app.include_router(users.router) +# ... other routers + +@app.get("/api/health") +def health_check(): + return {"status": "ok"} +``` + +### 4. Update database.py for Vercel + +**Critical:** Vercel serverless functions can only write to `/tmp`. Update the SQLite path: + +```python +SQLALCHEMY_DATABASE_URL = "sqlite:////tmp/app.db" +``` + +### 5. Seed ALL Required Data + +**This is the #1 gotcha.** Since `/tmp` is ephemeral, every cold start gets a fresh database. If your frontend assumes certain data exists (like user ID 1), you MUST seed it: + +```python +def seed_default_user(db: Session): + count = db.query(UserProfile).count() + if count > 0: + return + user = UserProfile(name="Demo User", ...) + db.add(user) + db.commit() +``` + +### 6. Create vercel.json + +```json +{ + "rewrites": [ + { "source": "/api/(.*)", "destination": "/api/index.py" }, + { "source": "/((?!assets/).*)", "destination": "/index.html" } + ] +} +``` + +This routes: +- `/api/*` → Python serverless function +- Everything else → React SPA (index.html) + +### 7. Deploy + +```bash +cd /vercel-deploy +vercel --yes --prod +``` + +### 8. Verify + +```bash +curl -s /api/health +# Should return: {"status":"ok"} +``` + +## Gotchas & Limitations + +| Issue | Solution | +|-------|----------| +| SQLite resets on cold start | Seed ALL required data in index.py startup | +| No persistent storage | Acceptable for demos. For production, use Vercel Postgres or Supabase | +| No auth | Fine for demos/portfolios. Add auth layer for real apps | +| `requirements.txt` location | Must be inside `api/` folder (next to index.py) | +| Module imports in routers | Use `sys.path.insert(0, os.path.dirname(__file__))` in index.py | +| CORS | Set `allow_origins=["*"]` for demo deployments | +| `--name` flag deprecated | Don't use `--name` with Vercel CLI, just deploy from the directory | + +## Vercel CLI Quick Reference + +```bash +npm install -g vercel # Install +vercel login # Authenticate (opens browser) +vercel --yes --prod # Deploy to production (skip prompts) +vercel logs --project # Check function logs +```