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

[Guide] Build a "One Page App" (Still Use a Router) - implementation notes

Started by Harper Iqbal
guiderouterone pageapp shellfile routercomponent routesglobal statepostureextensions path

The One Page App guide is a useful reminder that "single screen" doesn't mean "no routing". The guide treats the router as an organization tool and future-proofing contract: file route for the shell, component routes for internal motion, and global state only where posture truly needs to be global.

Read the guide

If the UI is truly one page, what did you use routes for: internal panels, search state, or just future expansion? How did you split file router vs component router responsibilities without duplicating state? What global state did you allow, and how did you keep it from becoming a dumping ground? Did you render route evidence (active panel, active tab) so screenshots are actionable?

Comments (24)

Back to latest
Jun Park
Feb 23, 2023 · 06:20 AM

We used routes for panels + deep links, even though the UI is one page.

It made support and QA way easier.

Mei Tan
Feb 27, 2023 · 08:08 AM

The router was mostly for naming posture: panel=editor, panel=preview, tab=settings.

Once posture is explicit, you stop passing flags everywhere.

Rafael Soto
Mar 05, 2023 · 05:05 AM

We followed the guide pretty closely: file route owns chrome, component routes own internal motion. The biggest win was that we could log motion as routing decisions:

txt
[tips] routeFile shell=app reason=boot
[tips] componentRoute enter panel=editor reason=deepLink
[tips] componentRoute enter panel=preview reason=userClick
Grace McCoy
Mar 09, 2023 · 09:30 AM

Docs tie-in: the "router as contract" framing fits the routing docs well.

Related: Routing and Navigation and Getting Started.

Arman Qadir
Mar 23, 2023 · 03:03 AM

Concrete alternative: no router, just local state.

We tried that first. The moment we needed shareable links and back/forward to work, we re-invented routing anyway. The guide is right that you should just start with a router.

Harper Iqbal
Mar 24, 2023 · 06:18 PM

Exactly. The real question is whether you want to invent a private router or adopt a public one.

Even a tiny one page app benefits from having a named motion model.

Nina Kapoor
Apr 04, 2023 · 04:04 AM

We allowed global state only for user posture (theme, account, feature flags). Everything else was route state or local state.

If a state value affects navigation, it should probably be route state so you can deep link it.

Liam Osei
Apr 18, 2023 · 08:20 AM

The guide's best advice is "leave an extensions path". We created fake routes (disabled) in the file tree so future sections had a place to land.

It sounds like busywork, but it prevented a painful reorg later.

Dmitri Kline
May 06, 2023 · 06:06 AM

Long-form: people treat routers like infrastructure, but in practice they're product vocabulary.

A one page app still has product states: which panel, which selection, which mode. If those are implicit, your app becomes difficult to support and difficult to test.

By making them routes (file or component), you get identity, evidence, and replay. That makes debugging feel like reading a script rather than guessing.

Kaitlyn Wells
May 21, 2023 · 11:11 AM

We rendered data-panel, data-tab, data-mode on the shell and it made screenshots genuinely useful.

Without that, bug reports were basically "it didn't work".

Salma Qureshi
Jun 11, 2023 · 10:10 AM

Small disagreement: I don't love component routes for tiny apps.

But I do love file route as the shell and route state as the one place for shareable posture. That alone solves 80%.

Benji Rios
Jun 26, 2023 · 03:33 AM

We implemented a very small component router wrapper with a strict contract (only accepts an enum + evidence).

The constraint prevented people from smuggling in arbitrary navigation strings and kept it maintainable.

Priya Liao
Jul 17, 2023 · 07:07 AM

Hot take: the router is worth it just for back/forward support.

Rowan Pierce
Aug 09, 2023 · 09:09 AM

If you want the guide's approach to feel real, add a route-flow test that navigates through panels and asserts evidence keys.

It makes refactors safe.

Evan Brooks
Aug 28, 2023 · 02:14 PM

We used router state for search query too, because it made sharing links straightforward.

We still kept a local draft so typing didn't spam navigation. Commit/draft split was important.

Lina Ortega
Sep 12, 2023 · 12:12 PM

Long-form counterpoint: there is a risk of over-architecting a one page app.

The guide can be misread as "always build a full router system". I think the real advice is "name motion and posture". If you can name it without building a big abstraction, do that.

Keira Santos
Oct 20, 2023 · 08:20 PM

We used a single file route plus a component route map for internal panels. It stayed stable as we added features.

The biggest win was that teams could add panels without touching global state.

Ari Novak
Nov 11, 2023 · 11:11 AM

The guide's approach also makes analytics easier because routes give you stable event names.

If the app is one page with 40 states, you need those names somewhere.

Anika Sharma
Nov 20, 2023 · 03:03 AM

Takeaway: don't confuse one page with one state bucket.

Use routing (file or component) to keep state surfaces honest.

Tomas Rivera
Dec 01, 2023 · 09:10 AM

If you're planning to add anything later, start with the router now.

Otherwise you'll be migrating ad-hoc booleans into a route model under deadline.

Liam Osei
Dec 10, 2023 · 04:10 PM

One thing we did differently: global state for selection, route state for panel.

Selection is often not share-worthy; panel is.

Amina Farouk
Dec 18, 2023 · 06:18 PM

Evidence suggestion: print a compact route string on the footer in dev builds.

It's like a built-in reproduction script.

Camille Duarte
Dec 22, 2023 · 07:19 PM

This guide convinced me to stop being allergic to routers in small apps.

Soren Malik
Dec 27, 2023 · 08:20 PM

A practical note: if you do route state for internal panels, make sure you normalize/validate it.

We had a bug where an old link pointed to an invalid panel, and without normalization the UI crashed.

Noah Vance
Dec 31, 2023 · 10:22 PM

Long-form: the still use a router message is really about maintaining a stable contract as teams grow.

Once you have multiple people shipping changes, you want motion to be a shared language, not an emergent property.