React Forum
Blog & Guide Responses
Feb 05, 2023 · 04:00 PM

[Guide] Build a Learning Platform (Route Layout Templates) - implementation notes

Started by Ari Novak
guidelearninglayout routestemplatesroute groupingglobal state in layoutcontent motioncontracts

The Learning Platform guide frames layouts as templates: layout routes own shared state (course progress, current module), route grouping organizes content motion, and navigation becomes a contract rather than an emergent property of nested components. I like the "template" framing because it makes shared state location obvious, but I'm curious how it plays out when the UI gets complex.

Read the guide

What did you let the layout own (progress, sidebar expansion, playback posture) versus leaving to child routes? How did you model route grouping so module/lesson navigation stayed coherent with back/forward? What evidence did you render so screenshots show current template + module + lesson identity and motion keys? How did you avoid the layout becoming a mega component with too many responsibilities?

Comments (18)

Back to latest
Marisol Vega
Feb 08, 2023 · 08:08 AM

Layout-as-template worked for us because it forced us to decide what is truly shared.

If the sidebar needs to stay stable while lessons change, the sidebar state belongs in the template.

Dmitri Kline
Feb 10, 2023 · 10:10 AM

We logged layout contract transitions and it made navigation bugs diagnosable:

txt
[tips] layoutTemplate=courseShell module=m3 lesson=l2 reason=nav:click
[tips] routeGroup=module motion=lesson:swap remountKey=lesson:l2
[tips] layoutState progress=0.63 reason=derive:progress

Then we render data-template, data-module, data-lesson, and data-motion on the shell.

Keira Santos
Feb 16, 2023 · 04:16 PM

Counterpoint: layouts owning global state can turn into a hidden global store if you're not careful.

We kept layout state to navigation-adjacent values only. Anything domain-y lived in a course document keyed by courseId.

Ari Novak
Feb 19, 2023 · 04:04 AM

Yes. Template state isn't "everything" state.

If a value isn't required to keep navigation and shared chrome coherent, it probably shouldn't live in the layout.

Grace McCoy
Feb 28, 2023 · 10:22 PM

Route grouping helped us avoid "one route per UI" chaos.

We grouped by user mental model: course -> module -> lesson, and motion keys matched that model.

Jasper Nguyen
Mar 14, 2023 · 02:14 PM

Long-form take: learning platforms fail when the chrome (nav/progress) and the content disagree.

Layouts as templates solve that because they colocate the chrome contract with the state that drives it.

But you must render evidence of identity (course/module/lesson) or support can't debug anything.

Nina Kapoor
Mar 29, 2023 · 03:03 AM

We stored derived progress in the layout because it influences multiple routes (sidebar, header, next lesson CTA). And we logged progress derive so it didn't feel like magic:

txt
[tips] derive=progress course=c7 ratio=0.63 reason=lesson:complete
Camille Duarte
Apr 18, 2023 · 06:18 PM

Counterpoint: putting progress in layout can make it update too often and hurt perf.

We introduced a tick posture (warm/cool) for progress derive and made it explicit in logs + evidence.

Owen Price
May 10, 2023 · 10:10 AM

We avoided layout bloat by treating the layout as a composition point, not a logic point.

Logic lived in small docs/derivers; layout just renders outputs and wires motion keys.

Benji Rios
Jun 01, 2023 · 06:06 AM

Long-form counterpoint: templates can encourage teams to couple unrelated features because "it's shared chrome".

We had to enforce boundaries: template gets navigation + progress, not messaging, not billing, not random banners.

Lina Ortega
Jun 25, 2023 · 10:22 PM

Docs tie-in: routing + app router mindset pages are basically the rationale for template layouts + grouping.

Related: Routing and Navigation and The App Router Mindset.

Amina Farouk
Jul 21, 2023 · 07:07 AM

We also rendered a data-template-version so we could correlate layout changes with navigation bugs.

It sounds like overkill, but it saved us during refactors.

Evan Brooks
Aug 19, 2023 · 07:19 PM

Motion keys were the hidden win: module switches remount, lesson switches preserve sidebar state.

Once you encode that as keys, the UI becomes calmer.

Harper Iqbal
Sep 18, 2023 · 12:12 PM

Counterpoint: preserving sidebar state across lessons can be confusing if the sidebar content changes per lesson.

We scoped the preserved state to expansion/collapse only; selected item derived from route identity.

Priya Liao
Oct 15, 2023 · 03:15 PM

We logged route grouping decisions when parsing URLs (defaults, normalizations).

It prevented subtle "wrong lesson" bugs because you can see how the URL was interpreted.

Theo Bennett
Nov 12, 2023 · 04:04 AM

Long-form argument: layouts as templates are a way to keep UX constraints close to the routing model.

If the UX says "sidebar persists", the route model needs to encode that persistence, not rely on component happenstance.

Salma Qureshi
Dec 20, 2023 · 06:18 PM

We also kept a small "template summary" string for support (course/module/lesson/tick posture).

Once that existed, most navigation bugs were diagnosable from a single screenshot.

Rowan Pierce
Dec 29, 2023 · 09:09 AM

If you're implementing this, start by deciding your identity boundaries (courseId/moduleId/lessonId) and how keys remount.

Everything else is detail once those boundaries are explicit.

Tomas Rivera
Dec 31, 2023 · 09:09 AM

The guide reads like a routing document disguised as a UX guide, which is exactly what it should be.

Learning platforms live or die by navigation coherence.