courtmitra / DEPLOY.md
Hetansh Waghela
feat: Full Clerk Google OAuth + user profiles + combined API/Worker deploy
f69e867
|
Raw
History Blame
10.3 kB

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):
  • OpenRouter API key (or OpenCode / OpenAI key) for LLM calls

Step 1: Clerk + Google OAuth (10 min)

  1. Go to dashboard.clerk.com β†’ Create Application.
  2. 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.
  3. Copy your Publishable Key and Secret Key from Clerk Dashboard β†’ API Keys.
  4. 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
    
  5. That's it β€” the frontend has Clerk wired with SignInButton, UserButton, and <Show when="signed-in"> components.
  6. 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)

  1. Go to neon.tech β†’ New Project β†’ copy the connection string.
  2. Save it as DATABASE_URL and DIRECT_DATABASE_URL.
  3. 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)

  1. Push this repo to GitHub.
  2. In Vercel β†’ Add New Project β†’ import the repo.
  3. 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
    
  4. Deploy. Vercel will auto-detect Next.js in apps/web.

Tip: next.config.mjs already has output: "standalone", so Vercel optimizes automatically.


Step 4: Backend β†’ Hugging Face Spaces (25 min)

4a. Create the Space

  1. Go to huggingface.co/spaces β†’ Create new Space.
  2. Space name: courtmitra-api
  3. SDK: Docker
  4. Visibility: Public (free tier)
  5. 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:

  1. Open your Vercel URL β†’ click Sign In β†’ choose Google.
  2. After signing in, you should see your avatar in the top-right corner.
  3. Click Get Started (hero CTA) β†’ describe a problem.
  4. The API call should reach HF Spaces, create a user in the DB, and create a mission.
  5. Visit /{locale}/profile β†’ you should see your profile and the mission you just created.
  6. Check https://your-hf-space.hf.space/api/admin/health to 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 pnpm is missing, the Dockerfile installs it via corepack.
  • 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_KEY is 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_URL is set and migrations ran.
  • Verify OPENROUTER_API_KEY is 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 to origin: ["https://your-vercel.app"] in apps/api/src/main.ts.

Clerk sign-in fails:

  • Make sure NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY are 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_KEY and INNGEST_SIGNING_KEY are 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

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! πŸš€