Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

7 Commits

Repository files navigation

Assignmento — AI Assessment Creator

An AI-powered assessment and question paper generator for teachers. Create professional, exam-ready question papers in minutes.

Important

Current Limitation: PDF and image uploading for context is currently disabled. Free AI models on OpenRouter do not yet support direct file/image analysis. AI generation relies on the user's "Additional Information" field only.


Architecture Overview

Assignmento uses an asynchronous, worker-based architecture to handle AI generation without blocking the UI.

graph TD
A[Frontend: Next.js 16] -- POST /api/assignments --> B[Backend: Express 5]
B -- Zod Validation --> B
B -- Create Doc --> C[MongoDB Atlas]
B -- Queue Job --> D[Upstash Redis + BullMQ]
D -- Process --> E[AI Worker]
E -- Call AI --> F[OpenRouter]
F -- AI_MODELS fallback chain --> E
E -- Update Doc --> C
E -- Emit Event --> G[Socket.io]
G -- Notify Client --> A
Loading

Tech Stack

LayerTechnology
FrontendNext.js 16 (App Router), TypeScript, TailwindCSS 4
StateZustand, React Context
BackendNode.js, Express 5
DatabaseMongoDB Atlas (Mongoose)
QueueBullMQ + Upstash Redis
Real-timeSocket.io
AIOpenRouter — hardcoded AI_MODELS fallback chain
PDFhtml2canvas + jsPDF
IconsLucide React

Project Structure

Assignmento/
├── backend/
│ ├── server.js # Entry point — HTTP server, Socket.io, worker init
│ ├── app.js # Express app — middleware, routes
│ ├── .env # Local environment variables
│ ├── .env.example # Environment variables template
│ ├── config/
│ │ ├── db.js # MongoDB connection
│ │ ├── openrouter.js # OpenRouter AI client
│ │ └── redis.js # Redis/ioredis client
│ ├── models/
│ │ ├── assignmentModel.js # Assignment schema with nested questions
│ │ ├── sectionSchema.js # Nested schema for paper sections
│ │ ├── questionSchema.js # Nested schema for questions
│ │ └── questionConfigItemSchema.js # Question type configuration schema
│ ├── controllers/
│ │ └── assignmentController.js # HTTP handlers for assignment endpoints
│ ├── routes/
│ │ └── assignmentRouter.js # CRUD endpoints for assignments
│ ├── middlewares/
│ │ └── errorHandler.js # Global error handler
│ ├── services/
│ │ ├── assignmentService.js # Business logic + Redis caching
│ │ └── aiService.js # AI prompt execution + JSON parsing
│ ├── prompts/
│ │ └── assessmentPrompt.js # Builds AI system prompt from question config
│ ├── queues/
│ │ └── aiQueue.js # BullMQ queue setup
│ ├── workers/
│ │ └── aiWorker.js # Background AI job processor
│ └── socket/
│ └── socketHandler.js # Socket.io room subscriptions
│
└── frontend/
├── app/
│ ├── layout.tsx # Root layout (ToastProvider)
│ ├── page.tsx # Redirects to /assignments
│ ├── globals.css # Global styles + CSS variables (light/dark)
│ └── assignments/
│ ├── page.tsx # Assignment list/dashboard
│ ├── create/page.tsx # Create assignment form
│ └── [id]/page.tsx # Assignment detail + PDF preview
├── components/
│ ├── layout/
│ │ ├── AppShell.tsx # Main layout wrapper
│ │ ├── Header.tsx # Top bar — page label, dark mode toggle
│ │ ├── Sidebar.tsx # Desktop sidebar navigation
│ │ ├── MobileHeader.tsx # Mobile top bar
│ │ └── BottomNav.tsx # Mobile bottom navigation
│ ├── assignments/
│ │ ├── AssignmentCard.tsx # Individual assignment card
│ │ ├── AssignmentGrid.tsx # Grid + infinite scroll
│ │ ├── AssignmentsShimmer.tsx # Skeleton loading state
│ │ ├── SearchBar.tsx # Search input
│ │ └── EmptyState.tsx # Empty list illustration
│ ├── create/
│ │ ├── CreateAssignmentForm.tsx # Main creation form
│ │ ├── QuestionConfigSection.tsx # Question type config table
│ │ └── QuestionTypeRow.tsx # Single question type row (steppers)
│ ├── output/
│ │ ├── QuestionPaper.tsx # Full paper container
│ │ ├── PaperHeader.tsx # School/exam header
│ │ ├── SectionBlock.tsx # Paper section (MCQ, short answer, etc.)
│ │ ├── QuestionItem.tsx # Individual question display
│ │ ├── AnswerKeySection.tsx # Answer key
│ │ └── ActionBar.tsx # Print / Download / Back buttons
│ └── ui/
│ ├── Button.tsx # Reusable button (primary/secondary/danger/ghost)
│ ├── Toast.tsx # Toast notifications
│ ├── ThreeDotMenu.tsx # Context menu (view/delete)
│ ├── GenerationStartedModal.tsx # Modal on generation start
│ ├── GenerationCompleteToast.tsx # Toast on generation complete
│ └── LoadingSpinner.tsx # Spinner component
├── context/
│ └── ToastContext.tsx # Global toast state
├── hooks/
│ ├── useAssignments.ts # Assignment fetch/delete hooks
│ ├── useSocket.ts # Socket.io connection per page
│ └── useBackgroundSocket.ts # Background listener for generation events
├── lib/
│ ├── api.ts # Axios instance (withCredentials)
│ ├── socket.ts # Socket.io client init
│ └── pdf.ts # HTML → PDF utility
├── store/
│ └── useAssignmentStore.ts # Zustand — assignments, loading, generation status
└── types/
└── assignment.ts # TypeScript types

API Endpoints

Assignments — /api/assignments

MethodPathDescription
GET/api/assignmentsList assignments (paginated + search)
POST/api/assignmentsCreate assignment + queue AI generation
GET/api/assignments/:idGet assignment detail
DELETE/api/assignments/:idDelete assignment
POST/api/assignments/:id/regenerateRe-queue AI generation

Socket.io Events

Event (client → server)Description
subscribe:dashboardJoin dashboard room for global updates
subscribe:assignmentJoin room for a specific assignment's updates
unsubscribe:assignmentLeave assignment room
Event (server → client)Description
generation:processingAI job started
generation:completeAI generation finished
generation:errorAI generation failed

Setup

Prerequisites

  • Node.js 20+
  • MongoDB Atlas URI
  • Upstash Redis URL (TLS)
  • OpenRouter API key — openrouter.ai

1. Backend

cd backend
npm install

Create backend/.env:

PORT=3000MONGO_URI=your_mongodb_atlas_uriREDIS_URL=your_upstash_redis_urlOPENROUTER_API_KEY=your_openrouter_keyFRONTEND_URL=http://localhost:8080

The AI models are hardcoded as a fallback chain in backend/config/openrouter.js (AI_MODELS). The worker tries each model in order and falls through to the next if one is removed/renamed (404), rate-limited, or returns bad output — so there's no single model to misconfigure.

npm run dev

2. Frontend

cd frontend
npm install

Create frontend/.env.local:

NEXT_PUBLIC_BACKEND_URL=http://localhost:3000
npm run dev

The app runs at http://localhost:8080.


How It Works

  1. Create assignment — User fills in the form (subject, class, question config). Frontend POSTs to /api/assignments.
  2. Async generation — Backend validates with Zod, saves a pending Assignment, and pushes a job onto the BullMQ Redis queue. The response returns immediately.
  3. Background worker — Picks up the job, calls the OpenRouter AI API with a structured JSON prompt, parses the response, and saves the generated content to MongoDB. Emits Socket.io events throughout.
  4. Real-time updates — Frontend listens on Socket.io. When generation completes a toast appears with a link to the result.
  5. PDF output — The question paper is rendered to HTML and converted to a downloadable PDF via html2canvas + jsPDF.

Features

  • AI question paper generation — Configurable question types, marks, and counts
  • Async job queue — Generation never blocks the UI; runs in the background
  • Real-time notifications — Socket.io push when generation completes
  • Dark / Light mode — Toggleable theme, persisted in localStorage
  • PDF download & print — Print-optimized A4 layout
  • Infinite scroll — Paginated assignment list
  • Search — Debounced assignment search

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages