Feature Tour
A map of where each part of the product lives in the code — the hubs, the portals, and the platform console.
You've met the patterns — the data layer, the design system, side panels and surfaces. Now the question changes from "how is this built?" to "where does feature X live?" This group is that map. It won't re-explain a pattern; it'll point you at the right folder and tell you what you'll find when you open it.
The product isn't one app — it's five experiences sharing one codebase, and which one you land in depends on who you are.
Who routes where
Every signed-in user passes through getUserDestination, which reads their user type and sends them to the right home. There are five types, and the switch is short enough to read in one breath:
switch (me.user.type) {
case 'platform_admin': return { to: '/platform/hub' }
case 'guest': return { to: '/guest' }
case 'student': return { to: '/student/hub' }
case 'guardian': return { to: '/guardian/hub' }
case 'staff': {
// school hub when they can see the school dashboard, else their campus hub
if (hasSchoolDashboard(me)) return { to: '/staff-hub/school/hub' }
return { to: '/staff-hub/campus/$campusId/hub', params: { campusId } }
}
}Staff are the interesting case. If they hold school_dashboard read (or manage all), they land in the school hub; otherwise they drop into the campus hub for their assigned campus, and if they somehow have neither, a no-campus fallback. The mechanics of this are covered in User Types and Permissions — here it's enough to know that user type is the fork in the road.
The academic structure, briefly
Most of what staff manage hangs off one nested tree — School → Campus → (Academic Year → Term → Stream) → Class → Subject → Enrollment. Almost every route and query domain you'll see below is a view onto one node of that tree, and inside the campus hub every year-scoped view reads the viewing academic year from the URL. The full shape, with what each level means, lives on The Product — don't try to hold it all in your head here; just know the hierarchy exists and the folders mirror it.
The five clusters
Here's the lay of the land. Each cluster has its own page that goes one level deeper.
- Staff Hub — the big one. Two halves: school-level admin (
/staff-hub/school/*) and campus-level admin (/staff-hub/campus/$campusId/*). - CBT — computer-based testing. Exams, questions, and assignments, reached from inside subjects and streams in the campus hub.
- Admissions & Recruitment — student applications and staff job vacancies, with both a guest-facing and a staff-facing side.
- Portals — the lighter experiences for guests, students, and guardians.
- Platform Console — the cross-school control room for platform admins: schools, operators, and shared curriculum.
Staff Hub
School-level and campus-level admin — the largest surface in the app.
CBT
Computer-based testing — exams, questions, and stream assignments.
Admissions and Recruitment
Student applications and staff hiring, guest-side and staff-side.
Portals
The guest, student, and guardian experiences.
Platform Console
The cross-school control room for platform admins.
Two source trees that matter
Wherever a feature lives, it's almost always split across the same two trees — and once you internalize that split, navigating the codebase gets a lot quieter.
Routes live under src/routes/_authenticated/. The folder names read like a sitemap: staff-hub/school/, staff-hub/campus.$campusId/, platform/, guest/, student/, guardian/. The $campusId in a folder name is a route param — that's how one set of campus pages serves every campus.
staff-hub/school/{students,staff,campuses,inquiries,jobs,...}
staff-hub/campus.$campusId/{subjects,classes,classrooms,my-subjects,...}
platform/{schools,operators,curriculum}
guest/{admissions,jobs} student/hub guardian/hubData lives under src/queries/<domain>/, one folder per domain — student, staff, campus, enrollment, cbt-examination, application, job, and so on. When a page needs data, it reaches into the matching query domain rather than calling the API directly. The full convention is on The Data Layer.
A page is usually a route folder plus a query domain
When you go hunting for a feature, look in two places — the route folder under src/routes/_authenticated/ for the UI, and the matching folder under src/queries/ for the data. The names line up: students routes pair with the student query domain.
The shared UI you'll meet everywhere
Three families of shared components show up across every cluster, so it's worth knowing them by name before you start exploring:
src/components/data-tables/— the list views (students, staff, applications, exams). See Data Tables.src/components/side-panels/andsrc/components/surfaces/— the slide-in panels and modal surfaces used for detail and create-edit flows. See Panels and Surfaces.src/components/navigation/— the per-experience sidebars, navbars, and breadcrumbs (admin-staff.*,guardian.*,platform.*) that give each cluster its own shell.
That's the whole map. Each cluster page below tells you which routes and query domains it owns, and which of these shared pieces it leans on.