By the end of this guide you will have the Innova API running onDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/vruizz22/innova-backend-serverless/llms.txt
Use this file to discover all available pages before exploring further.
http://localhost:3000, a valid JWT in hand, and a successful student attempt response from the rule engine — all without touching real AWS infrastructure. Local SQS and S3 are emulated by LocalStack inside Docker, so every code path (including the telemetry FIFO queue and the LLM fallback queue) works on your laptop.
Setup
Prerequisites
Make sure the following are installed before you begin:
You can create a free Supabase project at supabase.com. Copy the Project URL, anon key, and service role key from the project dashboard — you will need them in the next step.
| Tool | Minimum version | Notes |
|---|---|---|
| Node.js | ≥20 | Use nvm or fnm to manage versions |
| pnpm | ≥9 | corepack enable && corepack prepare pnpm@latest --activate |
| Docker + Docker Compose | v2 | Required for MongoDB and LocalStack |
| Supabase project | — | Needed for Auth (JWKS endpoint) and Postgres |
Configure environment
Copy the example environment file and fill in the required values:Open
The remaining
.env and set at minimum the six required variables below. Leave optional variables (AI provider keys, Resend) blank for local development.| Variable | Description | Example value |
|---|---|---|
DATABASE_URL | Supabase Postgres connection string (local dev uses :5433) | postgresql://postgres:innova_secret@localhost:5433/innova_dev_db?schema=public |
MONGODB_URI | MongoDB Atlas or local telemetry connection | mongodb://root:innova_mongo_secret@localhost:27017/innova_telemetry_local?authSource=admin |
SUPABASE_URL | Your Supabase project URL | https://<project-ref>.supabase.co |
SUPABASE_SERVICE_ROLE_KEY | Server-only admin key (bypasses RLS) | From Supabase dashboard → Settings → API |
AWS_REGION | AWS region for SQS/S3 resources | us-east-1 |
CORS_ORIGINS | Comma-separated allowed browser origins — required at boot | http://localhost:3001,http://localhost:3002 |
SQS_* URLs in .env.example are pre-filled with LocalStack-compatible placeholders. Swap in real ARNs only when deploying to AWS.Start local infra
Bring up MongoDB 7 and LocalStack (SQS + S3) in the background:Verify the containers are healthy:You should see both
mongodb and localstack in a running state. Postgres comes from Supabase (or a local instance pointed to by DATABASE_URL) — it is not managed by Docker Compose in this project.Apply migrations and seed
Run the Prisma migration to create all tables in Postgres, then seed the database with a demo school, courses, students, and exercises:To also import the full
innova-ai-engine error taxonomy into the ErrorTag table (required for the admin catalog and LLM classifier), run the full seed script instead of the plain seed:pnpm seed:full already runs prisma db seed internally — you do not need to run both.Start the dev server
Launch the NestJS dev server with hot reload:NestJS will print its bootstrap log to the terminal. Wait for the
Nest application successfully started message — the server is now listening on http://localhost:3000.Verify the server is up
In a separate terminal, confirm the API is responding:Expected response:A
200 OK with this message means the NestJS app bootstrapped successfully and all module connections (Prisma, Mongoose) initialised.Browse Swagger UI
Open http://localhost:3000/docs in your browser to explore the full interactive OpenAPI specification. Every endpoint is documented with request/response schemas generated directly from the TypeScript DTOs.The raw OpenAPI JSON is available at http://localhost:3000/docs/openapi.json.
Your first API call
In local development, the API uses a local HS256 JWT (issued by
POST /auth/login) rather than a Supabase JWKS RS256 token. Both token types are validated by the same SupabaseAuthGuard — the guard falls through to the local strategy when no Supabase JWKS is reachable. In production, all tokens are RS256 JWTs issued by Supabase Auth.1. Obtain a JWT
Log in with a demo teacher account to receive an access token. If you have not created demo users yet, see the tip below aboutpnpm seed:auth.
accessToken plus a refreshToken and the user profile:
accessToken — you will pass it as a Bearer token in every subsequent request.
2. Submit a student attempt
Send aPOST /attempts request with the student’s rawSteps array, topicCode, expectedAnswer, and studentAnswer. The rule engine classifies the procedural error synchronously and returns the errorTag and updated pKnown mastery value in the response.
errorTag will be "UNCLASSIFIED" and the attempt is queued for async LLM classification via SQS. Poll GET /attempts/:id/status for the resolved classification.
Useful development commands
| Command | What it does |
|---|---|
pnpm start:dev | Starts the NestJS server with hot reload on port 3000 |
pnpm build | Compiles TypeScript with nest build (output in dist/) |
pnpm test | Runs the full Jest unit test suite |
pnpm test:cov | Runs tests with coverage report (gate ≥75%) |
pnpm prisma studio | Opens Prisma Studio — a browser GUI for the Postgres database |
docker compose logs -f | Tails live logs from MongoDB and LocalStack containers |
LocalStack and offline AWS flows: the
docker-compose.yml provides a local LocalStack instance that emulates SQS and S3. This means you can exercise the full attempt telemetry FIFO queue, the LLM classification queue, and the OCR queue without an AWS account or real SQS URLs. To drain the attempt-reprocess queue locally (the OCR→attempt loop), run pnpm consume:reprocess in a separate terminal alongside pnpm start:dev.