Status: done Priority: P1 Created: 2026-02-11 Completed: 2026-02-18 Owner: conductor
The prior design had :route/path declarations on each route state, hierarchical path
composition, parameterized path segments, and plans for named query params + unified URL
encoding. This was overengineered.
The simplified design: URL paths are derived automatically from the chart's route target
hierarchy using simple component names. No :route/path option. Params are encoded as a
single opaque transit+base64 query param (as the existing system already does).
URL/history integration is an external system — decoupled from the core routing
statechart (which is what ui_routing2 provides). The URL layer observes state changes
and translates between URLs and route-to events.
/AdminPanel/AdminUserDetail?_p=<base64-transit of {:user-id 7}>
::ui/AdminUserDetail → AdminUserDetail._p containing transit+base64 encoded map of all active
route state params, keyed by state ID:
_p = base64(transit({:AdminPanel {:tab "users"}, :AdminUserDetail {:user-id 7}}))
Only present when at least one active route state has params. Not human-readable.route-to!
event is sent for the leaf; intermediate states enter automatically as ancestors in the
statechart hierarchy. Each intermediate state's on-entry picks up its own params slice
from the event data.[:routing/parameters <state-id>] in
the data model (via establish-route-params-node). States can use assign to mutate
their params over time. The URL layer observes these changes and updates the URL
(replace, not push) to stay in sync.When the statechart configuration changes, the URL layer:
:route/targetname part of the keyword)/ to form the path[:routing/parameters <id>], collects them
into a map keyed by state ID_p (omitted if no state has params)On page load or URL change from external source:
_p query param (if present) to get the state-id→params maproute-to! for the leaf with the full decoded params map as event dataestablish-route-params-node picks up its own slice from the params mapIntermediate path segments (e.g. AdminPanel in /AdminPanel/AdminUserDetail) serve as:
For restoration, the intermediate segments can be used to disambiguate but are not strictly required if leaf names are unique.
:on-save HookThe URL layer hooks into the statechart system via the :on-save callback on
install-fulcro-statecharts! (fulcro.cljc:234). This fires on
save-working-memory! (fulcro_impl.cljc:254) every time a statechart reaches a
stable configuration after processing an event. It receives (session-id wmem).
Internal → URL (event causes screen/param change):
save-working-memory! → :on-save fires_p paramBrowser back/forward → Chart (popstate):
route-to! for the decoded leaf target:on-save firesParam mutation (assign changes params without route change):
assign on [:routing/parameters <id>]save-working-memory! → :on-save fires:route/params on rstate/istate — declares accepted param keywords. Already in
ui_routing2.cljc.establish-route-params-node — stores params from event data into data model. Already works.route_url.cljc (encode-params, decode-params).route_history.cljc — HTML5 history integration, route->url/url->route callbacks.:on-save callback — install-fulcro-statecharts! option, fires on every stable
configuration save. fulcro_impl.cljc:256.:route/path — path segments are auto-derived from target names_p param (drop _sc_ and _rp_ dual encoding):on-save hook — push/replace logic depends on whether the change
was internal navigation, browser back/forward, or param-only mutation_p, keyed by state ID
3a. States can mutate their params via assign; URL layer syncs changes (replace, not push)route->url / url->route callbacks remain the extension point for custom URL schemes| File | Role |
|---|---|
integration/fulcro/route_url.cljc | URL encoding/decoding — simplify to single _p param |
integration/fulcro/route_history.cljc | History integration — update path generation/restoration |
integration/fulcro/ui_routing2.cljc | Core routing — no changes needed (:route/params already exists) |
AdminPanel istate containing AdminUserDetail rstate → /AdminPanel/AdminUserDetail{:AdminPanel {:tab "users"} :AdminUserDetail {:user-id 7}} → ?_p=<base64 transit>?_p=<base64 transit> → state-id-keyed map passed as event data, each state picks up its slice/AdminPanel/AdminUserDetail?_p=... sends single route-to for AdminUserDetail_p param
6a. [ ] State using assign to change its params triggers URL update (replace, not push)route->url / url->route callbacks still work for custom schemes:on-save hook on install-fulcro-statecharts!Can 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 |