Skip to content

Repository files navigation

TopicIQ

AI-generated practice tests with a topic-level breakdown of your results.

Pick a subject (or type a specific topic), sit a timed multiple-choice paper, and get back an analysis that says which topics cost you marks — not just a score.

Built as a single Next.js app: the UI, the API and the database access all live here.


Stack

Layer Choice
Framework Next.js 16 (App Router, React 19, Turbopack)
Language TypeScript (strict)
Styling Tailwind CSS v4, CSS-variable design tokens, light + dark themes via next-themes
Database MongoDB + Mongoose 9
Auth JWT in an httpOnly cookie, signed with jose; passwords hashed with bcryptjs
AI Google Gemini (gemini-3.6-flash) with a JSON response schema
Charts Recharts for the accuracy trend; plain HTML bars for topic breakdowns
Validation Zod on every API route

Getting started

Prerequisites

1. Install

npm install

2. Configure environment variables

cp .env.example .env.local

Then fill in .env.local — see Environment variables below.

3. Run

npm run dev

Open http://localhost:3000, create an account, and generate your first test.


Environment variables

All of these go in .env.local (git-ignored). .env.example is the template.

Variable Required What it is
MONGODB_URI Yes MongoDB connection string. Atlas: mongodb+srv://<user>:<pass>@<cluster>.mongodb.net/topiciq?retryWrites=true&w=majority. Local: mongodb://127.0.0.1:27017/topiciq
JWT_SECRET Yes Secret that signs the session cookie. At least 32 characters. Changing it signs everyone out.
GEMINI_API_KEY Yes Google AI Studio key used to generate questions.
GEMINI_MODEL No Overrides the model. Defaults to gemini-3.6-flash.

Generate a JWT_SECRET with:

node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))"

No NEXT_PUBLIC_* variables are needed — the browser never talks to Gemini or MongoDB directly, only to this app's own API routes.


How it works

  1. /start — you choose level, subject, optional topic, difficulty, length and duration.
  2. POST /api/tests — the server asks Gemini for questions using a strict JSON response schema, shuffles each question's options, and saves the paper as a Test document with status in_progress.
  3. /test/[testId] — the runner loads the questions without their correct answers. It tracks per-question time, supports flagging and keyboard entry, and saves progress to localStorage so a refresh does not lose the attempt.
  4. POST /api/tests/[testId]/submit — the server grades the attempt against the stored questions, computes accuracy and marks the test completed. Submitting twice is a no-op.
  5. /analysis/[testId] — accuracy, pace, per-topic performance and a full worked review of every question, filterable by correct / incorrect / skipped.
  6. /dashboard — accuracy over time, topic mastery across all papers, strongest and weakest topics, and your test history.

Correct answers only ever reach the browser once a test is submitted, and grading happens on the server — the score cannot be edited from the client.


Project structure

src/
  app/
    layout.tsx               root layout, fonts, theme provider
    page.tsx                 landing page
    auth/                    sign in / sign up
    (app)/                   signed-in shell (header, footer, auth guard)
      dashboard/
      start/
      analysis/[testId]/
    test/[testId]/           distraction-free test runner
    api/
      auth/{signup,login,logout}/
      tests/                 POST: generate + create a paper
      tests/[testId]/submit/ POST: grade and complete
  components/                UI, charts, runner, review
  lib/
    mongodb.ts               cached connection
    models/                  Mongoose schemas
    session.ts / auth.ts     JWT cookie + server guards
    gemini.ts                question generation
    queries.ts               server-side reads for pages
  proxy.ts                   route protection (Next 16 proxy convention)

Scripts

npm run dev      # development server
npm run build    # production build
npm run start    # serve the production build
npm run lint     # eslint

Deploying

Works on any Node host. On Vercel, add MONGODB_URI, JWT_SECRET and GEMINI_API_KEY as project environment variables, and allow your deployment's IPs in MongoDB Atlas network access (0.0.0.0/0 for a quick start).

Question generation for 30 questions can take longer than a free-tier function timeout. The route sets maxDuration = 120; make sure your plan allows it, or keep tests to 10–20 questions.

About

Full-stack Next.js app for AI-generated practice tests. Uses Google Gemini to create questions, grades papers on the server, and provides topic-level performance analytics via interactive dashboards.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages