# Project export: graider

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Our AI grading system automates grading for essays and exams, reducing workload and offering personalized feedback to students, highlighting mistakes and giving guidance on how to improve.
- Devpost: https://devpost.com/software/graider-axtu51
- GitHub: https://github.com/saumyajain1/graider
- Team: 0 GitHub contributor(s) — 

## Devpost submission (written by the team)

### Inspiration

We realized that grading papers is time-consuming and repetitive, often lacking meaningful feedback for students. This inspired us to create a solution that automates grading and enhances student feedback.

### What it does

Graider grades essays, assignments, and exams based on a provided rubric or one generated from the exam sheet. It also includes a feedback section for both students and graders, making the process more efficient and insightful.

### How we built it

We built the platform entirely using Python, leveraging Reflex to develop both the frontend and backend seamlessly. We also utilized the Groq LLM library to handle the complexities of grading papers accurately and efficiently

### Challenges we ran into

Working with Reflex, a new technology, was challenging. As we adapted to it, we faced a steep learning curve in scaling our project quickly using only our knowledge of Python.

### Accomplishments we're proud of

We’re proud of building an entire system using Python (thanks to Reflex). Additionally, we explored new tools provided by our sponsors—VAPI, Groq, and Fetch AI—which helped us enhance the project by integrating advanced AI capabilities.

### What we learned

We gained a deep understanding of Reflex and how to build frontend applications entirely in Python. We also explored different LLM models, refining our approach to achieve optimal latency rates suitable for the project’s needs.

### What's next

We plan to add a chatbot feature that allows graders to adjust student grades via voice commands. Additionally, we aim to incorporate image scanning to grade handwritten papers automatically. Our goal is to scale Graider to educational institutions across the country.

## README (from the GitHub repository)

# Graider MVP

Graider is a local-first MVP for AI-assisted grading. It lets a teacher:

- register and sign in
- create an assignment from pasted text, `.txt`, or `.pdf`
- generate questions, reference answers, and rubric criteria with an OpenAI LLM
- add student submissions manually or by CSV
- run an AI grading pass
- review and edit scores and feedback
- finalize results and export a CSV

## Stack

- `backend/`: Django + Django REST Framework + SQLite
- `frontend/`: React + Vite + Tailwind
- OpenAI models: `gpt-5.4-mini` for all current AI tasks

## Local setup

1. Copy `.env.example` to `.env`.
2. Set `OPENAI_API_KEY` in `.env`.
3. Create and activate a virtualenv, then install backend dependencies:

```bash
python -m venv .venv
source .venv/bin/activate
pip install -r backend/requirements.txt
```

4. Install frontend dependencies:

```bash
cd frontend
npm install
cd ..
```

5. Apply migrations:

```bash
.venv/bin/python backend/manage.py migrate
```

## Run locally

Start the backend:

```bash
.venv/bin/python backend/manage.py runserver 127.0.0.1:8000
```

Start the frontend:

```bash
cd frontend
npm run dev
```

Open `http://localhost:5173`.

## CSV format

Graider accepts CSV imports with:

- required: `student_name`
- required: `response_text` or `raw_response_text`
- optional: `student_identifier` or `student_id`

## Notes

- This is an MVP, not a production grading platform.
- AI features fail loudly if the OpenAI key is missing, but manual editing still works.
- The export endpoint is `GET /api/assignments/:id/export.csv`.


## Detected evidence (automated analysis)

Indexed codebase: 76 recognized source files, 313 KB.
- CSS (language) — detected in the code
- Django (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (84 of 84)

```
.env.example
.gitignore
backend/apps/__init__.py
backend/apps/accounts/__init__.py
backend/apps/accounts/admin.py
backend/apps/accounts/apps.py
backend/apps/accounts/migrations/__init__.py
backend/apps/accounts/migrations/0001_initial.py
backend/apps/accounts/models.py
backend/apps/accounts/serializers.py
backend/apps/accounts/tests.py
backend/apps/accounts/urls.py
backend/apps/accounts/views.py
backend/apps/assignments/__init__.py
backend/apps/assignments/admin.py
backend/apps/assignments/apps.py
backend/apps/assignments/migrations/__init__.py
backend/apps/assignments/migrations/0001_initial.py
backend/apps/assignments/models.py
backend/apps/assignments/serializers.py
backend/apps/assignments/services.py
backend/apps/assignments/tests.py
backend/apps/assignments/urls.py
backend/apps/assignments/views.py
backend/apps/grading/__init__.py
backend/apps/grading/admin.py
backend/apps/grading/apps.py
backend/apps/grading/migrations/__init__.py
backend/apps/grading/migrations/0001_initial.py
backend/apps/grading/models.py
backend/apps/grading/serializers.py
backend/apps/grading/services/__init__.py
backend/apps/grading/services/generation.py
backend/apps/grading/services/grading_pipeline.py
backend/apps/grading/services/openai_client.py
backend/apps/grading/services/schemas.py
backend/apps/grading/services/submission_io.py
backend/apps/grading/services/submission_workflow.py
backend/apps/grading/tests.py
backend/apps/grading/urls.py
backend/apps/grading/views.py
backend/config/__init__.py
backend/config/asgi.py
backend/config/settings.py
backend/config/urls.py
backend/config/wsgi.py
backend/manage.py
backend/requirements.txt
frontend/.gitignore
frontend/eslint.config.js
frontend/index.html
frontend/package.json
frontend/postcss.config.js
frontend/README.md
frontend/src/api/assignments.ts
frontend/src/api/auth.ts
frontend/src/api/client.ts
frontend/src/api/errors.ts
frontend/src/api/grading.ts
frontend/src/app/providers.tsx
frontend/src/app/routeGuards.tsx
frontend/src/app/router.tsx
frontend/src/components/layout/AppShell.tsx
frontend/src/hooks/useAuth.ts
frontend/src/index.css
frontend/src/main.tsx
frontend/src/pages/AssignmentCreatePage.tsx
frontend/src/pages/AssignmentOverviewPage.tsx
frontend/src/pages/AssignmentQuestionsPage.tsx
frontend/src/pages/AssignmentReferenceAnswersPage.tsx
frontend/src/pages/AssignmentReviewPage.tsx
frontend/src/pages/AssignmentRubricPage.tsx
frontend/src/pages/AssignmentSubmissionsPage.tsx
frontend/src/pages/DashboardPage.tsx
frontend/src/pages/LoginPage.tsx
frontend/src/pages/SubmissionReviewPage.tsx
frontend/src/vite-env.d.ts
frontend/tailwind.config.js
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts
graider_v_1_design_doc.md
README.md
```

### Dependencies

- backend/requirements.txt: Django@==5.2.12, django-cors-headers@==4.9.0, djangorestframework@==3.17.1, openai@==2.29.0, pydantic@==2.12.5, pypdf@==6.9.2, python-dotenv@==1.2.2, reportlab@==4.4.10
- frontend/package.json: @eslint/js@^9.13.0, @tanstack/react-query@^5.95.2, @types/node@^25.5.0, @types/react@^18.3.12, @types/react-dom@^18.3.1, @vitejs/plugin-react@^4.3.3, autoprefixer@^10.4.27, clsx@^2.1.1, eslint@^9.13.0, eslint-plugin-react-hooks@^5.0.0, eslint-plugin-react-refresh@^0.4.14, globals@^15.11.0, postcss@^8.5.8, react@^18.3.1, react-dom@^18.3.1, react-router-dom@^6.30.3, tailwindcss@^3.4.17, typescript@~5.6.2, typescript-eslint@^8.11.0, vite@^5.4.10

### Recent commits (newest first)

- docs: refine the public V1 design overview
- Update README.md
- feat: add submission review and export screens
- feat: grade imported student submissions end to end
- feat: add reference answers and rubric authoring
- feat: generate question maps from assignment source text
- feat: add assignment authoring and manual question setup
- feat: build teacher authentication and a protected workspace
- chore: scaffold the Django and React workspaces
- chore: establish the public repository baseline

## Key source files (fetched from GitHub, selected and truncated for size)

### graider_v_1_design_doc.md

```markdown
# Graider V1 Design Overview

## Purpose

Graider is an AI-assisted grading MVP for teachers. It helps a teacher turn an assignment into structured grading artifacts, run an initial grading pass over student submissions, and review the results before finalizing marks.

The product is intentionally teacher-controlled:

1. Create an assignment from pasted text, `.txt`, or `.pdf`.
2. Build or generate question parts.
3. Create reference answers and rubric criteria.
4. Add student submissions manually, from uploaded files, or by CSV.
5. Run AI-assisted grading.
6. Review, edit, finalize, and export results.

AI output is never the final authority. Teachers can edit every important artifact before using it.

## Product Principles

- **Human in the loop:** AI proposes; the teacher decides.
- **Structured workflow:** grading artifacts are stored as data, not as chat transcripts.
- **Editable outputs:** questions, answers, rubric criteria, scores, and feedback remain teacher-editable.
- **Teacher-scoped data:** assignments and grading records are only accessible to their owner.
- **Simple MVP scope:** the system favors a clear end-to-end workflow over production-scale infrastructure.

## Current MVP Scope

### Included

- Teacher registration, login, logout, and session-protected routes
- Assignment creation from text, `.txt`, or `.pdf`
- Manual question editing plus AI-assisted question decomposition
- Reference-answer generation and editing
- Rubric generation and editing
- Manual, file, and CSV submission intake
- AI-assisted answer mapping and grading
- Teacher review of scores and feedback
- Finalization and CSV export

### Deliberately out of scope

- Student accounts or student-facing submission flows
- LMS integrations
- Multi-teacher collaboration
- Advanced analytics
- Background job infrastructure
- Production storage, deployment, and compliance hardening

## System Shape

### Frontend

- React
- TypeScript
- Vite
- Tailwind CSS
- React Router
- TanStack Query

The frontend is organized around the assignment workflow:

- dashboard
- assignment overview
- questions
- reference answers
- rubric
- submissions
- review

### Backend

- Django
- Django REST Framework
- SQLite for the current MVP
- OpenAI API integration
- Pydantic schemas for structured model outputs

The backend is split into three application areas:

- `accounts`: teacher authentication and identity
- `assignments`: assignment source text and question-part setup
- `grading`: generated artifacts, submissions, grading workflow, review, and export

LLM-facing work is kept behind service modules so request handlers stay focused on HTTP concerns and the model provider can be changed later without rewriting the rest of the app.

## Key Design Decisions

### Fixed workflow instead of autonomous agents

Graider uses a predictable grading pipeline rather than giving an agent open-ended control over grading. That keeps the workflow easier to test, easier to review, and easier for teachers t
[truncated — 8526 more characters]
```

### backend/requirements.txt

```
Django==5.2.12
django-cors-headers==4.9.0
djangorestframework==3.17.1
openai==2.29.0
pydantic==2.12.5
pypdf==6.9.2
python-dotenv==1.2.2
reportlab==4.4.10

```

### frontend/package.json

```
{
  "name": "frontend",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@tanstack/react-query": "^5.95.2",
    "clsx": "^2.1.1",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.30.3"
  },
  "devDependencies": {
    "@eslint/js": "^9.13.0",
    "@types/node": "^25.5.0",
    "@types/react": "^18.3.12",
    "@types/react-dom": "^18.3.1",
    "@vitejs/plugin-react": "^4.3.3",
    "autoprefixer": "^10.4.27",
    "eslint": "^9.13.0",
    "eslint-plugin-react-hooks": "^5.0.0",
    "eslint-plugin-react-refresh": "^0.4.14",
    "globals": "^15.11.0",
    "postcss": "^8.5.8",
    "tailwindcss": "^3.4.17",
    "typescript": "~5.6.2",
    "typescript-eslint": "^8.11.0",
    "vite": "^5.4.10"
  }
}

```

### frontend/src/main.tsx

```typescript
import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'react-router-dom'

import { AppProviders } from './app/providers'
import { router } from './app/router'
import './index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <AppProviders>
    <RouterProvider router={router} />
  </AppProviders>,
)

```

### frontend/postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

```

### frontend/tailwind.config.js

```javascript
/** @type {import('tailwindcss').Config} */
export default {
  content: ['./index.html', './src/**/*.{ts,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
}

```

### frontend/vite.config.ts

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': {
        target: 'http://127.0.0.1:8000',
        changeOrigin: true,
      },
    },
  },
})

```

### frontend/index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

```

### backend/manage.py

```python
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
    """Run administrative tasks."""
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == "__main__":
    main()

```

### frontend/eslint.config.js

```javascript
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'

export default tseslint.config(
  { ignores: ['dist'] },
  {
    extends: [js.configs.recommended, ...tseslint.configs.recommended],
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
    plugins: {
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'react-refresh/only-export-components': [
        'warn',
        { allowConstantExport: true },
      ],
    },
  },
)

```

[58 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]