Vertical packs
Class Scheduling & Booking (Education)
Indicative price, not an offer: €29/mo; calendar sync, no-show prevention, class-size limits
Generated from docs/plan/paid/class-scheduling-booking/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
Class scheduling and booking system for education allowing students to reserve spaces in recurring classes. Calendar shows available classes with capacity; students sign up, receive confirmations. Admin manages class definitions, enforces capacity limits, tracks no-shows. Reduces manual signup friction and provides occupancy visibility.
The problem
Students cannot easily book classes. Schools use manual signup sheets, emails, or spreadsheets, leading to overbooking, confusion on who registered, and no-show tracking. Teachers have no visibility into class occupancy until the day. Parents don’t know which classes their child enrolled in.
What it does
- Class definition (subject, level, instructor, start/end time, capacity, weekly recurrence)
- Student signup with auto-confirmation email
- Student cancellation (manual removal from class)
- Calendar view (week view showing available classes + occupancy)
- No-show tracking (mark student absent, record on student profile)
- Class-size limit enforcement (prevent overbooking above capacity)
- Waitlist when class full (auto-notify when seat opens)
- Admin class CRUD (create/edit/delete classes)
- Admin occupancy reporting (heatmap by week, fill rate %)
- iCalendar export for students and instructors
What it deliberately does NOT do
Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.
- Make-up class scheduling — if student no-shows, they need to re-enroll in next session; we do not auto-enroll or credit them. Reason: requires teacher + student interaction, outside booking scope.
- Google Calendar / Outlook integration — two-way sync with external calendars adds OAuth complexity, sync failure liability, and HA burden. Reason: trust boundary; merchant owns their calendar.
- Per-class billing — charging students by class is transaction-heavy; use membership/subscription system instead. Reason: billing complexity outside this scope.
Data model
New tables: classes (classId, subjectId, instructorId, startTime, endTime, capacity, isRecurring, recurringRule). class_instances (classInstanceId, classId, date, status (scheduled/cancelled/completed), enrollment_count, no_show_count). enrollments (enrollmentId, classInstanceId, studentId, signup_time, status (booked/cancelled/no_show/waitlisted), confirmation_sent_at). Customer schema: add isStudent role. Migration: add columns if using relational storage; blob storage stores nested objects.
API
- GET /api/classes
- GET /api/classes/{classId}/instances
- POST /api/classes/{classId}/instances/{instanceId}/enroll
- DELETE /api/enrollments/{enrollmentId}
- GET /api/students/{studentId}/enrollments
- POST /api/admin/classes
- PUT /api/admin/classes/{classId}
- GET /api/admin/classes/{classId}/occupancy-report
- GET /api/classes/{classId}/instances/{instanceId}/calendar.ics
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Class CRUD UI (create/edit/delete with subject, level, time, capacity). Recurring rule builder (weekly/biweekly/monthly for next 12 weeks). Occupancy dashboard (heatmap: rows=classes, cols=weeks, color=fill%). No-show report (per student, per class, by date range). Student enrollment list per class with manual add/remove/mark-no-show.
The seam — why this is paid
Core owns: class + enrollment schema, calendar UI, email confirmations, no-show tracking. Paid pack owns: waitlist logic, capacity enforcement, occupancy aggregation, iCalendar export.
Support commitment: calendar conflict resolution, student reminders, teacher scheduling
Dependencies
- Customer/user system (student role)
- Email system
- Calendar/scheduling engine
- Webhook system (optional: notify on waitlist promotion)
Acceptance checks
Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.
- A recurring weekly class creates instances for next 12 weeks on the same day/time
- A student enrolls when occupancy < capacity; confirmation email sent within 2 minutes
- Occupancy dashboard shows class 15/20 capacity for week of Sept 1
- Student enrolls when full; goes to waitlist; receives email when seat opens
- Student cancels 48 hours before class; cancellation email sent, occupancy decremented
- Admin marks student no-show; occupancy report shows 1 no-show for that student in that class
- Exporting calendar as iCalendar (.ics) shows only student’s enrolled classes with times
- Admin cancels class instance; status = Cancelled, no further signups allowed
- Two concurrent enrollments do not exceed capacity (atomic check-and-insert)
- Occupancy heatmap by week shows which classes trending full (color intensity)
Risks
No idempotency: rapid double-click enrolls student twice, wastes seat. Timezone handling: student thinks CEST, system stores UTC, shows wrong time. Waitlist auto-promotion not atomic: two seats open, two waitlisted students both get emailed, conflict. Occupancy report counts no-show rate wrong (includes drops after deadline vs actual no-show). Recurring rule generates too many instances (e.g., daily for 5 years); database bloat.
Commercial context
| Suggested price | €29/mo; calendar sync, no-show prevention, class-size limits |
| Rival anchor | Acuity Scheduling: €15-299/mo; custom build: €2000+ |
The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.
Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full
catalogue and ../../AI-GUIDE.md for how to work on this repository.