| Field | Value |
|---|---|
| Status | Backlog |
| Priority | P1 |
| Created | 2026-02-19 |
| Owner | (unassigned) |
The new routing namespace and routing.* sub-package provide a comprehensive statechart-driven routing system for Fulcro apps. The Guide.adoc covers the basics (lines 1035-1303) but reads more like a feature checklist than a tutorial. A developer new to this system would struggle to understand:
istate vs rstateistate and child chartsThe routing-demo2 app shows all of these patterns but isn't referenced from the Guide.
Expand the "Hierarchical Routing" section of Guide.adoc to be a comprehensive guide. The section should be reorganized and expanded to cover the following areas, each with working code examples:
A complete, sequential walkthrough showing every step from zero to working routes:
1. install-fulcro-statecharts! with :on-save and :async? true
2. Define the routing chart with routing-regions / routes / rstate
3. register-statechart! (if using istate with pre-registered child charts)
4. start! the router
5. install-url-sync! (optional, with cleanup for hot reload)
6. mount! the Fulcro app
Include the defonce cleanup pattern for shadow-cljs hot reload. Reference the demo app setup (routing-demo2/app.cljs).
Document what route target components need:
:preserve-dynamic-query? true on any component that renders routes (already in Invariants, needs prominence)ui-current-subroute for serial regions, ui-parallel-route for parallelistate Deep-Dive: Composition and Code Splitting (NEW)This is the most underdocumented and most powerful feature. Cover:
istate does: invokes a child statechart when the route is entered, tears it down on exitsfro/statechart component option (chart definition lives on the component)sfro/statechart-id (for code-splitting: child chart in separate namespace, registered separately):route/reachable — explain that the parent chart can route to targets that only exist in the childsend-to-self! works — sending events from a component (or any of its UI children) to the nearest ancestor's co-located child chartcurrent-invocation-configuration — querying the child chart's state (also walks parent chain)exit-target, on-donesfro/actors — passing additional actors to the child chartUse the admin panel from routing-demo2 as the running example:
istate with :route/reachableadmin_chart.cljc) is a separate statechart with its own routesroute-to! targets that live inside the childDocument the bookmark/restore pattern from routing-demo2:
route-to.* eventssave-bookmark function capturing the denied route eventreplay-bookmark! on dashboard entry after successful loginThis is a very common need and the demo shows an excellent pattern.
Document the URLCodec protocol and how to write a custom implementation:
encode-url and decode-urlTransitBase64Codec behavior (transit+base64 in _p query param)install-url-sync! via :url-codecThe current section is too brief. Expand to cover:
:route/params #{:id} on rstateroute-to! event data -> on-entry handler -> [:routing/parameters state-id] in data modelevent-data, not data)Expand the brief section to explain:
sfro/busy? predicaterouting-info modal state (built into routing-regions)record-failed-route! / force-continue-routing! / abandon-route-change! lifecycle:routing/guarded? false on child charts to avoid double-guardingThe current section shows the basic pattern but needs:
current-configuration, active-leaf-routeshistory-stack, history-cursorurl_sync_headless_spec.cljcA concise table of all public functions in the routing namespace, grouped by category:
| Category | Functions |
|---|---|
| Setup | start!, install-url-sync!, url-sync-on-save |
| Navigation | route-to!, route-back!, route-forward!, send-to-self! |
| State Query | active-leaf-routes, route-denied?, has-routes?, current-invocation-configuration, reachable-targets |
| Route Denial | record-failed-route!, force-continue-routing!, abandon-route-change! |
| Rendering | ui-current-subroute, ui-parallel-route |
| DSL | routing-regions, routes, rstate, istate |
| Validation | validate-route-configuration |
A troubleshooting section:
:preserve-dynamic-query? true:on-save handler calling url-sync-on-savebusy?:route/reachable declaration on istate:route/segment to disambiguateroute-to! does nothing: Target not found in chart; check target keyword matches :route/targetui-current-subroute instead of ui-parallel-routerouting.cljc is mentioned somewhererouting_options.cljc constants are all documentedURLCodec and URLHistoryProvider protocols are both explainedGuide.adoc — Replace lines 1035-1303 with expanded content (estimated ~600-800 lines)src/main/com/fulcrologic/statecharts/integration/fulcro/routing.cljc — All public functionssrc/main/com/fulcrologic/statecharts/integration/fulcro/routing_options.cljc — Component optionssrc/main/com/fulcrologic/statecharts/integration/fulcro/routing/url_codec.cljc — Codec protocolsrc/main/com/fulcrologic/statecharts/integration/fulcro/routing/url_codec_transit.cljc — Default codecsrc/main/com/fulcrologic/statecharts/integration/fulcro/routing/url_history.cljc — History protocolsrc/main/com/fulcrologic/statecharts/integration/fulcro/routing/browser_history.cljc — Browser implsrc/main/com/fulcrologic/statecharts/integration/fulcro/routing/simulated_history.cljc — Test implsrc/routing-demo2/com/fulcrologic/statecharts/routing_demo2/chart.cljc — Demo main chartsrc/routing-demo2/com/fulcrologic/statecharts/routing_demo2/admin_chart.cljc — Demo child chartsrc/routing-demo2/com/fulcrologic/statecharts/routing_demo2/ui.cljs — Demo componentssrc/routing-demo2/com/fulcrologic/statecharts/routing_demo2/app.cljs — Demo setupsrc/test/com/fulcrologic/statecharts/integration/fulcro/routing/url_sync_headless_spec.cljc — Test exampleCan 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 |