A command center dashboard for university instructors to manage high-stakes student presentations with randomization, timing, and grading capabilities.
- Session Management: Create sessions with configurable presentation and Q&A durations
- Roster Import:
- Bulk CSV import (Team Name, Member1, Member2, ...)
- Manual team entry
- Duplicate team name prevention
- Rubric Builder:
- Create custom grading criteria with max scores and weights
- Save and load rubric templates
- Rubric locks after first presentation starts (ensures fairness)
- Random Team Selection: Fair randomization from eligible pool
- Smart Timer System:
- Manual start (never auto-starts)
- Visual warnings at 2-minute mark
- Overtime tracking (counts into negative with clear indication)
- Separate presentation and Q&A timers
- Browser crash recovery (auto-resumes from saved state)
- Flexible Controls:
- Skip/Defer absent teams (returns them to pool)
- Emergency Stop with resume or restart options
- Stop & Grade for early finishes
- Grading Interface:
- Score entry with validation (0 to max score)
- Auto-calculated total scores
- Public feedback (student-visible) and private notes
- Cannot submit invalid scores
- View Completed Presentations: See all graded teams with scores and feedback
- Edit Grades: Modify scores/notes for any completed presentation
- Audit Trail: Timestamps logged when grades are edited
- CSV Export: Download all grades with team info and feedback
- PostgreSQL Database: All data persists in cloud-hosted database
- Browser Crash Recovery: Automatically resume active presentations with exact timer state
- Cloud-Deployed: Accessible from anywhere with internet connection
- Frontend: Next.js 15 (React) with TypeScript
- Backend: Next.js API Routes (Node.js)
- Database: PostgreSQL with @vercel/postgres
- Styling: Tailwind CSS
- Authentication: JWT with httpOnly cookies
- Deployment: Vercel with GitHub Actions CI/CD
Live URL: Deployed on Vercel
- Node.js 18+
- npm (or pnpm/yarn)
- Docker (for local Postgres) OR PostgreSQL installed locally
- Clone the repository:
git clone <repo-url>
cd the-painters-code- Install dependencies:
npm install- Setup Local Postgres:
# Option A: Using Docker (recommended)
docker run --name classroom-postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres
# Create database
psql -U postgres -c "CREATE DATABASE classroom_dev;"
# Run migration
psql -U postgres -d classroom_dev -f scripts/init-postgres.sql- Set up environment variables (
.env.local):
POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/classroom_dev
JWT_SECRET=your-secure-random-string-here- Run the development server:
npm run dev- Open http://localhost:3000 in your browser
- Navigate to the signup page and create an account
- Login with your credentials
- Create a new session with:
- Session name (e.g., "CSC491 Week 5")
- Presentation duration (minutes)
- Q&A duration (minutes)
- Add teams using bulk CSV or manual entry
- Create rubric criteria or load from a saved template
- Click "Start Presentation Session"
Format each line as: Team Name, Member1, Member2, Member3, ...
Example:
Team Alpha, Alice Smith, Bob Jones
Team Beta, Carol White, Dave Brown, Eve Green
Team Gamma, Frank Miller
- Pick Next Team: Randomly selects from eligible pool
- Start Presentation: Manually start the timer
- Monitor Timer:
- Green = plenty of time
- Yellow = 2 minutes warning
- Red = overtime
- Controls:
- Switch to Q&A: End presentation phase, start Q&A
- Stop & Grade: For early finishes or end of Q&A
- Emergency Stop: Pause with option to resume or defer
- Grade: Fill in scores, add feedback, submit
- Repeat: Pick next team when ready
- Team Absent: Click team, then use defer to return them to pool
- Technical Issues: Emergency Stop → Defer (they can go later)
- Student Emergency: Emergency Stop → option to restart or defer
- Go to "View History"
- Find the presentation
- Click "Edit Grades"
- Modify scores/feedback
- Save (creates audit trail entry)
- Go to "View History"
- Click "Export to CSV"
- Downloads file with all team scores and feedback
the-painters-code/
├── app/
│ ├── api/ # API routes
│ │ ├── auth/ # Authentication endpoints
│ │ ├── session/ # Session management
│ │ ├── teams/ # Team operations
│ │ ├── rubric/ # Rubric and templates
│ │ ├── presentations/# Presentation state
│ │ ├── grades/ # Grading operations
│ │ └── export/ # CSV export
│ ├── dashboard/ # Main dashboard page
│ ├── login/ # Login page
│ ├── signup/ # Signup page
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Home (redirects)
│ └── globals.css # Global styles
├── components/
│ ├── Dashboard.tsx # Main dashboard container
│ ├── SetupPhase.tsx # Session/roster/rubric setup
│ ├── PresentationPhase.tsx # Randomizer, timer, grading
│ └── HistoryView.tsx # Completed presentations
├── lib/
│ ├── db.ts # Postgres connection (@vercel/postgres)
│ └── auth.ts # JWT utilities
├── types/
│ └── index.ts # TypeScript type definitions
├── scripts/
│ └── init-postgres.sql # Database schema migration
├── .github/
│ └── workflows/
│ └── deploy.yml # GitHub Actions deployment workflow
└── docs/
├── deployment-justification.md # Architecture decisions
└── architecture-diagram.png # System architecture diagram
- users: Instructor accounts
- sessions: Presentation sessions with timer configs
- teams: Team rosters with members
- rubric_templates: Saved rubric configurations
- rubric_criteria: Session-specific grading criteria
- presentations: Presentation records with timer state
- grades: Individual criterion scores
- feedback: Public and private feedback
- grade_audit: Edit history for grades
- session_state: Recovery state for browser crashes
npm run build
npm startnpx tsc --noEmitnpm run lint- Create Vercel Account: Sign up at https://vercel.com
- Import Repository: Connect GitHub repository to Vercel
- Create Postgres Database:
- Go to Storage tab in Vercel dashboard
- Create new Postgres database
- Connect to project
- Run
scripts/init-postgres.sqlin SQL editor
- Set Environment Variables in Vercel dashboard:
JWT_SECRET: Generate withnode -e "console.log(require('crypto').randomBytes(32).toString('hex'))"POSTGRES_URL,POSTGRES_PRISMA_URL,POSTGRES_URL_NON_POOLING: Auto-provided by Vercel
- Deploy: Push to main branch, Vercel auto-deploys
Workflow: .github/workflows/deploy.yml
Triggers: Git tags (e.g., v1.0.0)
Setup GitHub Secrets (in repo Settings → Secrets → Actions):
VERCEL_TOKEN: From Vercel Settings → TokensVERCEL_ORG_ID: From.vercel/project.jsonafter first manual deployVERCEL_PROJECT_ID: From.vercel/project.json
To Deploy via Workflow:
git tag v1.0.0
git push origin v1.0.0Workflow will automatically trigger and deploy to production.
- JWT tokens stored in httpOnly cookies (XSS protection)
- Passwords hashed with bcryptjs
- Database uses foreign keys and constraints
- Input validation on all API endpoints
- Change JWT_SECRET for production deployments
- Multi-instructor support with isolated data
- Multiple concurrent sessions
- Real-time presentation view for projection
- Student-facing grade viewing portal
- Advanced analytics and reporting
- Email notifications
- Mobile responsive improvements
MIT
For issues or questions, please open an issue on GitHub.