feat(cohorts): rename Programs to Cohorts with data migration (#694)

* feat(cohorts): rename Programs to Cohorts with data migration

- Add cohort database tables and Drizzle migration alongside legacy program tables
- Introduce migrate-programs-to-cohorts script to copy existing program data safely
- Rename API routes (/cohort), services, queries, validation, and error codes
- Rename dashboard feature module, routes (/cohorts), navigation, and translations
- Update docs, emails, and internal compliance cron endpoints for cohort terminology
- Keep legacy program tables in place for rollback until explicitly removed

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(db): restore migrate:answer-data script alongside cohort migration

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(db): cast program enums when migrating data to cohort tables

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(db): truncate cohort tables before program-to-cohort copy

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(db): report accurate row counts in programs-to-cohorts migration

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>
This commit is contained in:
Rotimi Best
2026-07-02 12:10:31 +01:00
committed by GitHub
co-authored by Rotimi Best Cursor Agent
parent fe9f8c441f
commit ec61bfe7d9
115 changed files with 19703 additions and 6046 deletions
+54
View File
@@ -0,0 +1,54 @@
---
title: Cohorts
description: Learn what Cohorts are in ClassroomIO, how goals work, and what students see in the Cohorts view.
---
import { Callout } from 'fumadocs-ui/components/callout';
**Cohorts** group multiple courses into a structured learning path. Use them when students need to complete a set of courses toward a shared outcome (onboarding, certification prep, role-based training). Individual courses still live in the LMS; cohorts add goals and a dedicated **Cohorts** view for students.
## Cohorts vs courses
| Concept | Scope | Student view |
| --- | --- | --- |
| **Course** | Single content container with lessons | **Home**, **My Learning**, **Explore** |
| **Cohort** | Multiple courses with shared goals | **Cohorts** in the LMS |
A student can be enrolled in courses without belonging to a cohort, and in a cohort that references several courses. See [Student Dashboard](/docs/student-dashboard) for how those views fit together.
## Admin workflow
From the admin dashboard:
1. Create a cohort and add courses to it.
2. Configure cohort **Settings** (metadata, visibility, assignments).
3. Add **Goals** that define what success looks like.
4. Assign students to the cohort (existing students or by email invite).
Students assigned to a cohort see it under **Cohorts** in the LMS.
## Cohort goal types
Goals measure progress across the cohort's courses. Supported types:
| Type | What it measures |
| --- | --- |
| **Complete all** | Every selected course is completed |
| **N of M** | A minimum number of selected courses completed |
| **Score** | Per-learner score threshold on every selected course |
| **Pass rate** | Team-wide pass-rate threshold |
| **Readiness** | No deadline; tracks completion without a due date |
Deadlines can be absolute, relative to when the student joins, recurring, or none.
## Student experience
In the LMS, students open **Cohorts** to see cohorts they belong to. Each cohort hub includes:
- **Newsfeed** — updates from instructors
- **Courses** — linked courses with progress
- **Goals** — personal goal status when goals are configured
<Callout type="info">
Legacy deployments may still have data in the original `program` tables. Run the migration script `pnpm --filter @cio/db migrate:programs-to-cohorts` after applying the cohort schema migration to copy existing data into the new tables without dropping the legacy tables.
</Callout>
+1 -1
View File
@@ -8,7 +8,7 @@
"---Core Features---",
"course",
"programs",
"cohorts",
"api",
"mcp",
"tags",
+3 -3
View File
@@ -25,10 +25,10 @@ On creation, each org gets `https://<siteName>.myclassroomio.com` as its academy
Share your academy URL with students. The generic `app.classroomio.com` host is for platform access when no org subdomain applies. Course and enroll links should use your academy when possible.
</Callout>
## Courses and programs inside an org
## Courses and cohorts inside an org
- **Courses** are individual learning containers. See [Course](/docs/course).
- **Programs** group courses with shared goals. See [Programs](/docs/programs).
- **Cohorts** group courses with shared goals. See [Cohorts](/docs/cohorts).
- **Students** use the [Student Dashboard](/docs/student-dashboard) after they sign in.
## Related guides
@@ -39,4 +39,4 @@ On creation, each org gets `https://<siteName>.myclassroomio.com` as its academy
- [Roles and Permissions](/docs/roles-and-permissions)
- [How Course Enrollment Works](/docs/course-enrollment)
- [Course](/docs/course)
- [Programs](/docs/programs)
- [Cohorts](/docs/cohorts)
-67
View File
@@ -1,67 +0,0 @@
---
title: Programs
description: Learn what Programs are in ClassroomIO, how goals work, and what students see in the Programs view.
---
import { Callout } from 'fumadocs-ui/components/callout';
**Programs** group multiple courses into a structured learning path. Use them when students need to complete a set of courses toward a shared outcome (onboarding, certification prep, role-based training). Individual courses still live in the LMS; programs add goals and a dedicated **Programs** view for students.
## Programs vs courses
| Concept | Scope | Student view |
| --- | --- | --- |
| **Course** | Single content container with lessons | **Home**, **My Learning**, **Explore** |
| **Program** | Multiple courses with shared goals | **Programs** in the LMS |
A student can be enrolled in courses without belonging to a program, and in a program that references several courses. See [Student Dashboard](/docs/student-dashboard) for how those views fit together.
## Admin workflow
From the admin dashboard:
1. Create a program and add courses to it.
2. Configure program **Settings** (metadata, visibility, assignments).
3. Add **Goals** that define what success looks like.
4. Assign students to the program (existing students or by email invite).
Students assigned to a program see it under **Programs** in the LMS.
## Program goal types
When you add a goal in **Programs → Settings → Goals**, you pick a **type**. Each type measures progress differently.
| Type | Label in the app | What it measures |
| --- | --- | --- |
| `complete_all` | Complete all selected courses | Every selected course must be finished |
| `n_of_m` | Complete N of M selected courses | Student must finish a required count from the courses you select |
| `score` | Score above threshold on every course | Minimum score on each selected course |
| `pass_rate` | Team pass-rate threshold | Aggregate pass rate across the group |
| `readiness` | Readiness (no deadline) | Readiness tracking without a fixed deadline |
### Complete N of M selected courses (`n_of_m`)
This type asks: "finish at least **N** courses from the list I picked." You select the courses, then set **required count** (N). N cannot be larger than the number of courses selected.
If you see wording like "N of M" in the dropdown, **M** is the number of courses you selected, not a separate field called "cells."
<Callout type="info" title="Deadlines on goals">
Goals can also have deadline settings (absolute date, relative to join, recurring, or none). Configure these in the same goal form when creating or editing a goal.
</Callout>
## What students see
Students who belong to a program open **Programs** in the LMS to see their tracks and goal progress. Individual course lessons still open from enrolled courses in **Home** or **My Learning**.
| Need | Where to look |
| --- | --- |
| Progress on a program track | **Programs** |
| Lessons inside one course | **Home** or **My Learning** |
| Optional courses not yet joined | **Explore** |
## Related guides
- [Student Dashboard](/docs/student-dashboard) — Programs vs My Learning vs Explore
- [How Course Enrollment Works](/docs/course-enrollment) — how students join courses inside a program
- [Course](/docs/course) — single-course overview
- [Roles and Permissions](/docs/roles-and-permissions) — who can manage programs and courses
+9 -9
View File
@@ -1,6 +1,6 @@
---
title: Student Dashboard
description: Learn how students navigate the LMS, including Home, My Learning, Programs, and Explore.
description: Learn how students navigate the LMS, including Home, My Learning, Cohorts, and Explore.
---
import { Callout } from 'fumadocs-ui/components/callout';
@@ -15,7 +15,7 @@ Students reach the LMS after they sign in on your academy. The left sidebar list
| --- | --- | --- |
| **Home** | `/lms` | Enrolled courses with progress |
| **My Learning** | `/lms/mylearning` | Enrolled courses only, grouped by status |
| **Programs** | `/lms/programs` | Programs the student belongs to |
| **Cohorts** | `/lms/cohorts` | Cohorts the student belongs to |
| **Explore** | `/lms/explore` | Published courses they are not enrolled in yet |
| **Exercise** | `/lms/exercises` | Exercises (if enabled for your org) |
| **Community** | `/lms/community` | Community (if enabled for your org) |
@@ -48,17 +48,17 @@ Both show enrolled courses. My Learning adds clearer filtering for students mana
Explore is useful when you want students to discover optional or elective courses without assigning them manually.
## Programs
## Cohorts
**Programs** are separate from individual courses. A program groups courses under shared goals (for example, complete all courses in an onboarding track). Students who belong to a program see it under **Programs** in the LMS.
**Cohorts** are separate from individual courses. A cohort groups courses under shared goals (for example, complete all courses in an onboarding track). Students who belong to a cohort see it under **Cohorts** in the LMS.
| Concept | Where students see it |
| --- | --- |
| Individual enrolled courses | Home, My Learning |
| Courses not yet joined | Explore |
| Multi-course tracks with goals | Programs |
| Multi-course tracks with goals | Cohorts |
For how admins create programs and set goals, see [Programs](/docs/programs).
For how admins create cohorts and set goals, see [Cohorts](/docs/cohorts).
## What students see right after enrolling
@@ -71,18 +71,18 @@ When a student enrolls in a course (from a landing page, invite link, or admin a
If you added them from **People** but they have not signed in yet, they may show as **Pending** in the admin People list until they accept the invite or create an account.
## Courses vs programs: quick comparison
## Courses vs cohorts: quick comparison
| Question | Answer |
| --- | --- |
| Where do I see courses I am taking? | **Home** or **My Learning** |
| Where do I find courses I have not joined? | **Explore** |
| Where do I see structured learning paths? | **Programs** |
| Where do I see structured learning paths? | **Cohorts** |
| Can one student use all three views? | Yes. They work together. |
## Related guides
- [How Course Enrollment Works](/docs/course-enrollment) — how students join courses and what settings control access
- [How to Invite Students](/docs/invite-students) — send enrollment links by email
- [Programs](/docs/programs) — multi-course tracks and goals for admins
- [Cohorts](/docs/cohorts) — multi-course tracks and goals for admins
- [Create a Course Landing Page](/docs/course-landingpage) — what prospects see before enrolling