Status: backlog Priority: P1 Created: 2026-02-17 Owner: conductor Depends on: ui-routing2-core (Phase 1 + Phase 2 + Phase 3)
A complete working demo application that exercises all features of the new ui-routing2
system. The demo must prove that the architecture works end-to-end with:
istates with rstatesThis is NOT a toy. It should be a realistic enough app structure that we can identify design problems before committing to the API.
A mock Fulcro app with a mock server remote (pathom-based, in-memory) that simulates:
Statechart hierarchy:
:state/root (initial → :state/initializing)
:state/initializing — check for existing session
:state/login — login form
:state/logged-in — wrapper for all authenticated routes
routes (routing-regions)
:state/dashboard — rstate, simple landing
:state/projects — rstate, list view with async load
:state/project — rstate, detail with async load (nested under projects)
:state/admin — istate, invokes admin-panel chart
admin-panel chart:
:state/users — rstate, user list
:state/user — rstate, user detail (nested)
:state/settings — rstate, app settings
:state/error — error recovery
The admin panel is a separate chart invoked via istate with :route/reachable
declaring all its targets. This demonstrates cross-chart composition.
On app start, the chart enters :state/initializing which runs an async "check session"
call. If valid session exists → :state/logged-in. If not → :state/login.
When not authenticated, ANY route-to.* event targeting a route inside :state/logged-in
must be caught by the route guard, saved as a bookmark, and the user sent to login.
After successful login, the saved bookmark is automatically replayed — the user lands on the deep route they originally requested.
Demonstrate the full flow: user requests /admin/users/42 while logged out →
redirected to login → logs in → automatically navigated to user 42 detail in the
admin panel (cascading through istate invoke + child routing).
Each data-loading on-entry returns a promise (simulated delay).
The async processor parks until it resolves before entering the next state.
Navigating to :state/project (which is inside :state/projects) should:
:state/projects, async load project list, park:state/project, async load project detail, parkprocess-event! callFailed async loads raise error events handled by the chart (similar to routing demo).
The bookmark is the generalized "save and replay" from ui-routing2-core's Phase 3.
It uses the :route/guard system — the guard returns :not-authenticated,
which triggers record-failed-route!.
The :state/logged-in on-entry includes a script that checks for a saved bookmark
and replays it (calls override-route! or equivalent).
If no bookmark exists, :state/logged-in enters its default child (dashboard).
Simple but functional Fulcro components — enough to visually verify routing works. Each screen shows:
A "state inspector" panel that shows:
src/routing-demo2/ — demo app source tree
chart.cljc — top-level statechart definitionadmin_chart.cljc — admin panel child chartmodel.cljc — async data loaders (mock)mock_server.cljc — mock pathom remote for auth + datadata.cljc — seed dataui.cljs — Fulcro UI componentsapp.cljs — app setup and startupBuild the mock pathom remote with:
(login! {:username :password}) → returns session token after delay(check-session! {:token}) → returns user info or nil after delay(logout! {:token}) → clears sessionBuild the statechart with the hierarchy described above. Key design points:
:state/initializing does async session check, transitions to login or logged-in:state/logged-in contains routing-regions with routesroutes checks authentication state in data model:state/logged-in on-entrySeparate chart with its own routes/rstate definitions. Invoked via istate from
parent chart with :route/reachable #{:admin/users :admin/user :admin/settings}.
Fulcro defsc components for each route target. Each manages its own ident and query.
The root component renders based on statechart configuration.
Write test scenarios (can be REPL-driven or fulcro-spec) that verify:
(route-to! app :admin/user {:user-id 42}) worksCan you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |