ADR-0013: Learning platform frontend stack (Next.js 15 + shadcn/ui)
- Status: Accepted · Date: 2026-05-31 · Approved by: Kevin Wong (CPTO)
- Signed by: Engineering Director
- Related: ADR-0006 (intranet static portal, not superseded), ADR-0008 (Vercel deploy pattern)
Context
IDEA-0001 “Show the Work” specifies a retrieval-first learning platform — a
surface distinct from the intranet (intranet/) where learners query scored
chunk content, complete modules, and track progress. The intranet (ADR-0006,
ADR-0008) is a static Astro portal for the Principal’s personal workspace and is
not a suitable host for interactive, authenticated learner sessions.
Two questions were faced:
-
Where does the platform live? The intranet directory and stack (Astro 6, static) are optimised for a read-only, single-user dashboard. Learner interactions — authentication, retrieval queries, progress persistence, real-time feedback — require a dynamic rendering model. Forcing these onto the static Astro surface would require significant non-idiomatic workarounds.
-
What frontend stack? The default stack (
CLAUDE.md) calls for Next.js 15 (App Router) + React 19 + Tailwind CSS v4 as the web application layer. shadcn/ui (new-york style) is the component system aligned with that stack. Astro-compatible component libraries exist but shadcn/ui is explicitly built for React and relies on Radix UI primitives that require a React runtime — it is not appropriate for the static Astro intranet.
The CPTO reviewed these constraints and made the stack selection. This ADR records that decision.
Decision
Build the learning platform as a Next.js 15 (App Router) + React 19 application
under a new top-level directory platform/, styled with Tailwind CSS v4
and componentised with shadcn/ui (new-york style). Deploy to Vercel,
following the established pattern from ADR-0008.
This creates two parallel product surfaces in the repository:
| Surface | Directory | Stack | Purpose |
|---|---|---|---|
| Intranet | intranet/ |
Astro 6 + Tailwind v4 | Principal’s personal workspace portal |
| Learning platform | platform/ |
Next.js 15 + React 19 + Tailwind v4 + shadcn/ui | IDEA-0001 learner surface |
ADR-0006 is not superseded. The intranet remains the correct tool for a static, single-user, repo-driven dashboard. The two surfaces serve different audiences and interaction models and are expected to coexist indefinitely.
Rationale for Next.js 15 / App Router: server components reduce client-side JavaScript for content-heavy chunk pages; streaming and suspense boundaries suit retrieval-first UX where chunk results arrive asynchronously; the route handler pattern fits future API endpoints for the chunk ingestion pipeline and rubric scoring.
Rationale for shadcn/ui (new-york style): components are copied into the repo (not a runtime dependency), which aligns with the project’s preference for explicit, auditable code over opaque packages; the new-york style’s tighter visual density fits a learning interface where density and scannability matter; Radix UI accessibility primitives are production-proven for interactive components (modals, comboboxes, tabs).
Consequences
platform/becomes a new deployable root alongsideintranet/. Vercel configuration forplatform/follows the pattern from ADR-0008: GitHub- connected, Root Directory =platform/, framework detection = Next.js,npm run build.- shadcn/ui components are initialized via
npx shadcn@latest initand added individually as needed; they live inplatform/src/components/ui/. - Deferred — auth: learner authentication (sign-in, session, role-based access) is not decided here. When warranted, revisit with a dedicated ADR; leading candidates are Clerk and NextAuth as noted in the default stack.
- Deferred — database: chunk storage and learner progress persistence are not decided here. ADR-0006 nominated Supabase as a future candidate; the retrieval-first platform will need a vector-capable store. Record the choice in a new ADR when the first retrieval route is built.
- Deferred — first route: the initial page structure and routing conventions
for
platform/are an Engineering task, not an architectural decision, and are not specified here. - The intranet (
intranet/) is unaffected. No Astro configuration, nointranet/package.json, and no intranet route changes result from this decision. - If shadcn/ui’s new-york default colour tokens conflict with KLMS brand
decisions made later, update
platform/src/app/globals.css; the component copies inui/are already in-tree and can be adjusted freely.