Spaces:
Sleeping
Deployment Guide β CourtMitra MissionOS
Target: Vercel (frontend) + Hugging Face Spaces (backend + worker) + Google OAuth (Clerk) + Neon (Postgres)
Honest Time Estimate
| Milestone | Time |
|---|---|
| Clerk setup (Google OAuth) + env vars | 10 min |
| Neon Postgres + run migrations | 10 min |
| Frontend on Vercel | 5 min |
| API + Worker on Hugging Face Spaces | 20β30 min |
| Wire frontend β backend + smoke test | 10 min |
| Running frontend + API + Worker + DB + Google Auth | ~1 hour (if everything goes smoothly) |
Prerequisites
- GitHub repo pushed and public (or HF Pro for private Spaces)
- Accounts (all have generous free tiers):
- Vercel
- Clerk
- Hugging Face
- Neon
- Inngest (optional β for background workflows)
- OpenRouter API key (or OpenCode / OpenAI key) for LLM calls
Step 1: Clerk + Google OAuth (10 min)
- Go to dashboard.clerk.com β Create Application.
- In the Social Connections section, enable Google.
- For development, use Clerk's shared OAuth credentials (just toggle it on).
- For production, add your own Google Client ID/Secret.
- Copy your Publishable Key and Secret Key from Clerk Dashboard β API Keys.
- Set these in Vercel (Step 3) and locally:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... NEXT_PUBLIC_CLERK_SIGN_IN_URL=/en/sign-in NEXT_PUBLIC_CLERK_SIGN_UP_URL=/en/sign-up - That's it β the frontend has Clerk wired with
SignInButton,UserButton, and<Show when="signed-in">components. - Backend Clerk verification: The API verifies Clerk JWTs from the
Authorization: Bearer <token>header. On first API call, it auto-creates a user in the DB and links their Google identity.
Step 2: Neon Postgres (10 min)
- Go to neon.tech β New Project β copy the connection string.
- Save it as
DATABASE_URLandDIRECT_DATABASE_URL. - Run migrations against the Neon DB:
# At repo root export DATABASE_URL="postgres://..." export DIRECT_DATABASE_URL="postgres://..." pnpm db:migrate pnpm db:seed
Step 3: Frontend β Vercel (5 min)
- Push this repo to GitHub.
- In Vercel β Add New Project β import the repo.
- Set these Environment Variables in the Vercel dashboard:
NEXT_PUBLIC_API_BASE_URL=https://your-hf-space.hf.space/api NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... NEXT_PUBLIC_CLERK_SIGN_IN_URL=/en/sign-in NEXT_PUBLIC_CLERK_SIGN_UP_URL=/en/sign-up - Deploy. Vercel will auto-detect Next.js in
apps/web.
Tip:
next.config.mjsalready hasoutput: "standalone", so Vercel optimizes automatically.
Step 4: Backend β Hugging Face Spaces (25 min)
4a. Create the Space
- Go to huggingface.co/spaces β Create new Space.
- Space name:
courtmitra-api - SDK:
Docker - Visibility: Public (free tier)
- Hardware: Free CPU
4b. Deploy the Dockerfile
The repo root has Dockerfile.hf which builds the monorepo and runs the NestJS API + Inngest Worker in ONE container.
Push it to HF (or link your GitHub repo in HF Space settings):
git add Dockerfile.hf
git commit -m "Add HF Spaces Dockerfile (API + Worker combined)"
git push origin main
Then in your HF Space β Settings β Repository β link your GitHub repo.
4c. Set Environment Variables
In your HF Space β Settings β Variables & Secrets:
PORT=7860
API_PORT=7860
DATABASE_URL=postgres://... (Neon)
DIRECT_DATABASE_URL=postgres://... (Neon)
AI_PROVIDER=openrouter
OPENROUTER_API_KEY=sk-or-v1-...
AI_MODEL=google/gemini-2.0-flash-exp:free
AI_VISION_MODEL=google/gemini-2.0-flash-exp:free
APP_BASE_URL=https://your-hf-space.hf.space
API_BASE_URL=https://your-hf-space.hf.space
WEBHOOK_BASE_URL=https://your-hf-space.hf.space
LOCAL_STORAGE_DIR=/app/.storage
JWT_SECRET=hackathon-jwt-secret-change-me
PII_HASH_SALT=hackathon-salt
TOKEN_ENCRYPTION_KEY=hackathon-enc-key-min-32-chars!!
CLERK_SECRET_KEY=sk_test_...
CLERK_JWT_KEY=... (optional β for networkless JWT verification)
Optional (for email actions):
RESEND_API_KEY=re_...
RESEND_FROM=noreply@yourdomain.com
Optional (for Inngest background workflows):
INNGEST_EVENT_KEY=... (from Inngest Cloud)
INNGEST_SIGNING_KEY=... (from Inngest Cloud)
INNGEST_BASE_URL=https://api.inngest.com
Optional (for local dev without Clerk):
DEMO_MODE=true
4d. Verify the API
Once the Space builds, visit:
https://your-space.hf.space/api/admin/healthβ should return{"status":"ok"}https://your-space.hf.space/api/inngestβ should return the Inngest registration JSON
Step 5: Wire Frontend β Backend
Update your Vercel environment variable:
NEXT_PUBLIC_API_BASE_URL=https://your-hf-space.hf.space/api
Redeploy the frontend (or Vercel will auto-redeploy on save).
Architecture (Combined Container)
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Hugging Face Spaces β Port 7860 β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β Fastify HTTP Server (NestJS) β β
β β βββββββββββββββ ββββββββββββββββββ β β
β β β API Routes β β /api/inngest β β β
β β β /api/* β β (Worker Fns) β β β
β β β β β β β β
β β β - missions β β - intake β β β
β β β - actions β β - evidence β β β
β β β - users β β - route-plan β β β
β β β - evidence β β - execute β β β
β β βββββββββββββββ ββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β β
β Neon Postgres (Cloud) β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
Quick Smoke Test
After both are deployed:
- Open your Vercel URL β click Sign In β choose Google.
- After signing in, you should see your avatar in the top-right corner.
- Click Get Started (hero CTA) β describe a problem.
- The API call should reach HF Spaces, create a user in the DB, and create a mission.
- Visit
/{locale}/profileβ you should see your profile and the mission you just created. - Check
https://your-hf-space.hf.space/api/admin/healthto confirm backend is alive.
New Features
| Feature | Status |
|---|---|
| Google OAuth via Clerk | β Frontend + Backend verified |
| User auto-creation on first API call | β
Creates users + userIdentities rows |
Profile page (/{locale}/profile) |
β Shows avatar, name, email, editable phone + language |
| My Missions list on profile | β Lists user's own missions |
| Mission ownership | β Users only see their own missions |
| Combined API + Worker container | β One HF Space serves both |
| Demo mode | β
DEMO_MODE=true bypasses auth for local dev |
Known Limitations for Hackathon Demo
| Feature | Status in 1-hour deploy |
|---|---|
| Frontend + Google OAuth on Vercel | β Works |
| API + Worker + DB on HF + Neon | β Works |
| Mission CRUD (user-scoped) | β Works |
| Evidence upload | β Works (if storage configured) |
| Background AI workflows | β οΈ Needs Inngest Cloud keys for production webhooks |
| Email sending via Resend | β οΈ Needs Resend key + verified domain |
| WhatsApp / Telegram channels | β Needs Meta Business verification (days) |
| Portal automation / eCourts | β Phase 2 only |
Troubleshooting
HF Space build fails:
- Check Factory Logs in HF. If
pnpmis missing, the Dockerfile installs it viacorepack. - If out of disk: HF free tier has ~50GB disk. The Dockerfile removes frontend packages (
next,react) from the API deploy to save space.
API returns 401 Unauthorized:
- Make sure
CLERK_SECRET_KEYis set in HF Space env vars. - Make sure the frontend passes
Authorization: Bearer <token>header. Check browser DevTools Network tab.
API returns 500:
- Verify
DATABASE_URLis set and migrations ran. - Verify
OPENROUTER_API_KEYis set (some endpoints call LLMs).
CORS errors from frontend:
- The API has
app.enableCors({ origin: true })which reflects the request origin. If blocked, add your Vercel domain toorigin: ["https://your-vercel.app"]inapps/api/src/main.ts.
Clerk sign-in fails:
- Make sure
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYandCLERK_SECRET_KEYare set in Vercel. - In Clerk Dashboard β Social Connections β Google, ensure it's enabled.
- Add your Vercel domain to Clerk Dashboard β URLs β Allowed Origins.
Inngest events not firing:
- Make sure
INNGEST_EVENT_KEYandINNGEST_SIGNING_KEYare correct. - Check the Inngest Cloud dashboard for failed runs.
- HF free-tier Spaces sleep after inactivity. Use a paid Space or keep-alive ping for reliable background processing.
Local Dev
# 1. Start local Postgres + Inngest
pnpm infra:up
# 2. Copy env and fill in keys
cp infra/.env.example .env
# 3. Run everything
pnpm dev
- Web: http://localhost:3000
- API: http://localhost:3001/api
- Inngest Dev Server: http://localhost:8288
Note: For local dev without Clerk, set DEMO_MODE=true in .env. The API will skip JWT verification and use a demo user.
Good luck at the hackathon! π