馃 distributed transcription service
thistle.dunkirk.sh
Class System Specification#
Overview#
Restructure Thistle from individual transcript management to class-based transcript organization. Users will manage transcripts grouped by classes, with scheduled meeting times and selective transcription.
User Flow#
1. Classes Page (Home)#
- Replaces the transcript page as the main view after signup
- Displays grid of class cards organized by semester/year
- Each section (semester/year combo) separated by horizontal rules
- Each card shows:
- Course code (e.g., "CS 101")
- Course name (e.g., "Introduction to Computer Science")
- Professor name
- Semester and year (e.g., "Fall 2024")
- Archive indicator (if archived)
- Final card in grid is "Register for Class" with centered plus icon
- Empty state: Only shows register button if user has no classes
2. Individual Class Page (/classes/:id)#
- Lists all recordings and transcripts for the class
- Shows meeting schedule (flexible text, e.g., "Monday Lecture", "Wednesday Lab")
- Displays recordings with statuses:
- Pending: Uploaded but not selected for transcription
- Selected: Marked for transcription by admin
- Transcribed: Processing complete, ready to view
- Failed: Transcription failed
- Upload button to add new recordings
- Each recording tagged with meeting time
3. Recording Upload#
- Any enrolled student can upload recordings
- Must select which meeting time the recording is for
- Recording enters "pending" state
- Does not auto-transcribe
4. Admin Workflow#
- Admin views pending recordings
- Selects specific recording to transcribe for each meeting
- Only selected recordings get processed
- Can manage classes (create, archive, enrollments)
Database Schema#
Classes Table#
CREATE TABLE classes (
id TEXT PRIMARY KEY, -- stable random ID (nanoid or similar)
course_code TEXT NOT NULL, -- e.g., "CS 101"
name TEXT NOT NULL, -- e.g., "Introduction to Computer Science"
professor TEXT NOT NULL,
semester TEXT NOT NULL, -- e.g., "Fall", "Spring", "Summer"
year INTEGER NOT NULL, -- e.g., 2024
archived BOOLEAN DEFAULT FALSE,
created_at INTEGER NOT NULL
);
Class Members Table#
CREATE TABLE class_members (
class_id TEXT NOT NULL,
user_id TEXT NOT NULL,
enrolled_at INTEGER NOT NULL,
PRIMARY KEY (class_id, user_id),
FOREIGN KEY (class_id) REFERENCES classes(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
Meeting Times Table#
CREATE TABLE meeting_times (
id TEXT PRIMARY KEY,
class_id TEXT NOT NULL,
label TEXT NOT NULL, -- flexible text: "Monday Lecture", "Wednesday Lab", etc.
created_at INTEGER NOT NULL,
FOREIGN KEY (class_id) REFERENCES classes(id) ON DELETE CASCADE
);
Updated Transcripts Table#
-- Add new columns to existing transcripts table:
ALTER TABLE transcripts ADD COLUMN class_id TEXT;
ALTER TABLE transcripts ADD COLUMN meeting_time_id TEXT;
ALTER TABLE transcripts ADD COLUMN status TEXT DEFAULT 'pending';
-- status: 'pending' | 'selected' | 'transcribed' | 'failed'
-- Add foreign keys:
FOREIGN KEY (class_id) REFERENCES classes(id) ON DELETE CASCADE
FOREIGN KEY (meeting_time_id) REFERENCES meeting_times(id) ON DELETE SET NULL
Note: Add indexes for performance:
class_members(user_id)- lookup user's classesclass_members(class_id)- lookup class memberstranscripts(class_id)- lookup class transcriptstranscripts(status)- filter by statusmeeting_times(class_id)- lookup class schedule
Permissions#
Class Access#
- Users can only view classes they're enrolled in
- Admins can view all classes
- Non-enrolled users get 403 when accessing
/classes/:id
Recording Permissions#
- Upload: Any enrolled student can upload recordings
- Delete: Students can delete their own recordings
- Select for transcription: Admin only
- View: All enrolled students can view all transcripts in their classes
Class Management#
- Create: Admin only (via admin UI)
- Archive: Admin only (via admin UI)
- Enroll students: Admin only (via admin UI)
- Remove students: Admin only (via admin UI)
Archive Behavior#
When a class is archived:
- Students can still view the class and all transcripts
- No new recordings can be uploaded
- No recordings can be deleted
- No transcription selection allowed
- No enrollment changes
- Class appears with archive indicator in UI
- Organized with active classes by semester/year
API Endpoints#
Classes#
GET /api/classes- List user's classes (grouped by semester/year)GET /api/classes/:id- Get class details (info, meeting times, transcripts)POST /api/classes(admin) - Create new classPUT /api/classes/:id/archive(admin) - Archive/unarchive classDELETE /api/classes/:id(admin) - Delete class
Class Members#
POST /api/classes/:id/members(admin) - Enroll student(s)DELETE /api/classes/:id/members/:userId(admin) - Remove studentGET /api/classes/:id/members(admin) - List class members
Meeting Times#
GET /api/classes/:id/meetings- List meeting timesPOST /api/classes/:id/meetings(admin) - Create meeting timePUT /api/meetings/:id(admin) - Update meeting time labelDELETE /api/meetings/:id(admin) - Delete meeting time
Recordings/Transcripts#
GET /api/classes/:id/transcripts- List all transcripts for classPOST /api/classes/:id/recordings- Upload recording (enrolled students)PUT /api/transcripts/:id/select(admin) - Mark recording for transcriptionDELETE /api/transcripts/:id- Delete recording (owner or admin)GET /api/transcripts/:id- View transcript (enrolled students)
Frontend Components#
Pages#
/classes- Classes grid (home page, replaces transcripts page)/classes/:id- Individual class view/admin- Update to include class management
New Components#
class-card.ts- Class card componentregister-card.ts- Register for class card (plus icon)class-detail.ts- Individual class pagerecording-upload.ts- Recording upload formrecording-list.ts- List of recordings with statusadmin-classes.ts- Admin class management interface
Navigation Updates#
- Remove transcript page links
- Add classes link (make it home)
- Update auth redirect after signup to
/classes
Migration Strategy#
Breaking change: Reset database schema to consolidate all migrations.
- Export any critical production data (if needed)
- Drop all tables
- Consolidate migrations in
src/db/schema.ts:- Include all previous migrations
- Add new class system tables
- Add new columns to transcripts
- Restart with version 1
- Existing transcripts will be lost (acceptable for this phase)
Admin UI Updates#
Class Management Tab#
- Create new class form:
- Course code
- Course name
- Professor
- Semester dropdown (Fall/Spring/Summer/Winter)
- Year input
- List all classes (with archive status)
- Archive/unarchive button per class
- Delete class button
Enrollment Management#
- Search for class
- Add student by email
- Remove enrolled students
- View enrollment list per class
- Future: Bulk CSV import
Recording Selection#
- View pending recordings per class
- Select recording to transcribe for each meeting
- View transcription status
- Handle failed transcriptions
Empty States#
- No classes: Show only register card with message "No classes yet"
- No recordings in class: Show message "No recordings yet" with upload button
- No pending recordings: Show message in admin "All recordings processed"
Future Enhancements (Out of Scope)#
- Share/enrollment links for self-enrollment
- Notifications when transcripts ready
- Auto-transcribe settings per class
- Student/instructor roles
- Search/filter classes
- Bulk enrollment via CSV
- Meeting time templates (MWF, TTh patterns)
- Download all transcripts for a class
Open Questions#
None - spec is complete for initial implementation.
Implementation Phases#
Phase 1: Database & Backend#
- Consolidate migrations and add new schema
- Add API endpoints for classes and members
- Update permissions middleware
- Add admin endpoints
Phase 2: Admin UI#
- Class management interface
- Enrollment management
- Recording selection interface
Phase 3: Student UI#
- Classes page with cards
- Individual class pages
- Recording upload
- Update navigation
Phase 4: Testing & Polish#
- Test permissions thoroughly
- Test archive behavior
- Empty states
- Error handling