feat: live class sessions, CE workflow, and docs (#683)

Adds live-class session scheduling on lessons (join link, date/time,
timezone) with automatic 24h and 1h reminder emails plus a calendar
invite (.ics), a time-change notification with an updated invite, a
teacher-authored welcome email and session invite on enrollment, and a
"Notify students" quiz nudge.

LMS gets an upcoming live-sessions card and Join buttons, plus a
reusable live-session card component (3 states) in @cio/ui with a
Storybook story. The sidebar content tree now reflects sequential
progression locking like the content list, and the course-completion
confetti regression is fixed.

Org-based emails no longer reference ClassroomIO by name. Docs add
live-class, welcome-email, and course-progression guides, expand the
certificates guide (design, signatures, corrected labels), move
plan-required callouts to the top, flatten how-to-guides to the docs
root with redirects, and add screenshots. Includes an add-docs-image
skill.
This commit is contained in:
Rotimi Best
2026-06-22 05:43:48 +01:00
committed by GitHub
parent 3547901de6
commit 81294a47f9
193 changed files with 5477 additions and 805 deletions
+8 -1
View File
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
import type * as PageTree from 'fumadocs-core/page-tree';
import browserCollections from 'fumadocs-mdx:collections/browser';
import { isRouteErrorResponse, useLoaderData, useRouteError } from 'react-router';
import { isRouteErrorResponse, redirect, useLoaderData, useRouteError } from 'react-router';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
@@ -26,6 +26,13 @@ const clientLoader = browserCollections.docs.createClientLoader({
export async function loader({ params }: { params: Record<string, string | undefined> }) {
const slug = params['*'];
// How-to guides were flattened to the docs root; permanently redirect the old
// `.../how-to-guides/<page>` URLs to `.../<page>`.
if (slug && slug.includes('how-to-guides/')) {
throw redirect('/' + slug.replace('how-to-guides/', ''), 301);
}
const slugs = slug ? slug.split('/') : ['home'];
const { getDocsRouteData } = await import('@/lib/source.server');
const routeData = await getDocsRouteData(slugs);