Changelog
- 2.7.0 — 2026-09-06
- 2.6.0 — 2026-08-17
- 2.5.0 — 2026-08-15
- 2.4.0 — 2026-08-15
- 2.3.0 — 2026-08-15
- 2.2.0 — 2026-08-15
- 2.1.0 — 2026-08-14
- 2.0.1 — 2026-08-11
- 1.0.0-beta.5
- 1.0.0-beta.4
- 1.0.0-beta.3
- 1.0.0-beta.2
- 1.0.0-beta.1
- 1.0.0-alpha.15
- 1.0.0-alpha.14
- 1.0.0-alpha.12
- 1.0.0-alpha.11
- 1.0.0-alpha.10
- 1.0.0-alpha.9
- 1.0.0-alpha.7
- 1.0.0-alpha.4
- 1.0.0-alpha.3
- 1.0.0-alpha.2
- 1.0.0-alpha
- 0.8.0
- 0.7.2
- 0.7.1
- 0.7.0
- 0.6.0
- 0.5.1
- 0.5.0
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.0
- 0.1.2
- 0.1.1
- 0.1.0
- 0.0.8
- 0.0.5
Full changelog
2.7.0 (2026-09-06)
⚠ BREAKING CHANGES
- atoms:
rootAtomis renamedrootRoute,createRootAtomtorootRouteAtom,redirectAtomtoredirectRouteAtom,queryParamAtomtoqueryParamRouteAtom, andvalidateAtomtovalidateRouteAtom. Their options types follow:RootOptionsbecomesRootRouteOptionsandQueryParamOptionsbecomesQueryParamRouteOptions.locationAtom,queryAtom,notAtom,navigationGuardAtomand every name already ending inRouteAtomare unchanged.
Ticket: 789
- atoms:
resolvedAtomis removed.resolvedAtom(route, load)becomesasyncRouteAtom(route, name, load).data, wherenameis what the loaded object binds to if the route is ever used for gating.followResolvedRedirectsis renamedfollowAsyncRedirectsand takes.dataatoms.preloadRoutesis renamedpreloadAsyncRoutes, matchinghydrateAsyncRoutes/followAsyncRoutes. TheResolverandRouteLookuptypes are replaced by oneRouteLoader, andAsyncRouteAtom.lookupis renameddata.hydrateAsyncRoutes,followAsyncRoutesandAsyncRouteSnapshotare unchanged.
Ticket: 675
- jarl-atoms:
notAtomtakes a single route atom rather than a spread of them. Combine several withunionRouteAtom([...])first.
Ticket: 420
- changelog: suppression' mid-paragraph, no colon, not a real footer, and the parser swept it (plus the trailing Co-Authored-By line) into the release notes as a fabricated BREAKING CHANGES entry.
What it described was also stale even if it had been real: the very next commit (2db21b1) abandoned that reset-to-2.0.1 plan and continued from 2.5.0 instead, once it turned out npm's dependent-check and dist-tags made the rollback impossible. Nothing about jarl's public API actually broke in 2.6.0 - every other entry in the release is an internal release-process change. Safe to hand-edit: @semantic-release/changelog only ever prepends new releases, it never rewrites past entries.
Features
- atoms: add validateAtom for constraints spanning several segments (794f8c0)
- atoms: one asyncRouteAtom API for async route data (d67c00c)
- docs: 678 — routing demo that switches on a page route atom (b5a0aec)
- docs: 907 — host an llms.txt for coding agents installing jarl (daff689)
- docs: demo page for cancelling navigation on dirty edits (5870133)
- docs: demo page for custom path atoms (yyyy-mm-dd, name.ext) (f89999e)
- docs: link jarl-atoms/jarl-react identifiers in code blocks to their API reference (045b894), closes #slug
- docs: link local relative imports in demo source to GitHub (2cc8dfb)
- jarl-atoms: 420 — notAtom takes one route and an options object (de0e997)
- jarl-atoms: 420 — unionRouteAtom combines several routes into one (a2af36c)
- jarl-atoms: 778 — veto any navigation with navigationGuardAtom (9ac8b10)
- jarl-atoms: 927 — enumRouteAtom binds a path segment from a fixed set of values (5b43305)
- jarl-react: 435 — forward NavOptions through useNavigate (5311c85)
- jarl-react: 778 — useNavigationGuard binding (4b934d2)
Bug Fixes
- docs: bundle the production SSR server self-contained (82c9772)
- docs: stop exporting non-component values from Fast Refresh boundaries (abfccd6)
- e2e: 823 — update registry-smoke to the exports 675/789 renamed (3befb44)
- infra: JARL1183 — reach the SSR instance directly, dropping the load balancer (48ede6c)
- infra: JARL1188 — detach the /ssr/* behaviour so the VPC origin can be updated (3e1b2e9)
- infra: JARL1188 — restore the /ssr/* behaviour on the repointed VPC origin (3292e96)
- infra: JARL1337 — pin the SSR AMI so deploys stop replacing the instance (6771c3e)
Documentation
- changelog: remove the bogus 2.6.0 BREAKING CHANGES section (59f9c94)
Code Refactoring
- atoms: 789 — name every route atom
*RouteAtom, and only route atoms (cf4d08e)
2.6.0 (2026-08-17)
Features
- atoms: add asyncRouteAtom for routes an async lookup decides (9cc4f6c)
- atoms: add numericRouteAtom for numeric path segments (6199066)
- atoms: drop redundant module-level comment in asyncRouteAtom (9c07ea7)
- docs: add blog routing demo (409d271)
- docs: async-lookup demo, and a real 404 status from SSR (6c0b9a1)
- docs: browse changelog releases with per-version routes (a718546)
- docs: data grid filter/sort demo driven by query params (d0c2557)
- docs: syntax-highlight code blocks with highlight.js (fa39824)
- roll the SSR server on every deploy (627a414)
Bug Fixes
- docs: await the now-async render in the production SSR server (a615556)
- docs: keep release-note sections inside their changelog entry (67da666)
- pin conventional-changelog-conventionalcommits to the release-notes-generator-compatible v8 line (eec26a5)
Continuous Integration
- release: reset the published line to 2.0.1 and open 2.1.x at 2.1.1 (25a5aa3)
2.5.0 (2026-08-15)
Features
- docs: add GitHub, Discord and npm links to the toolbar (ceb3ec8)
- docs: generate the API reference from package doc comments (60d4351)
Code Refactoring
- atoms: split
routeAtom.tsinto one file per primitive atom (1b777f5) - atoms: restore the
Pathtype export to keep the public API intact (0b9ba90) - docs: replace
main.csswith@emotion/styledcomponents (71288ab)
Documentation
- point the doc site's links at
randomdev.co.ukafter the repo transfer (7b4f2b9) - new tagline, "Routing for the atomic age" (2fb91d8)
Continuous Integration
- wire the deploy job — OIDC role,
cdk deploy --all, S3 sync and invalidation (eba8115) - bump
checkout/setup-nodeto v5 for Node 24 action runtimes (e716935)
2.4.0 (2026-08-15)
Features
- infra: Route53 zone, ACM certificate and alias records for
jarl.randomdev.co.uk(78bb9a0)
Bug Fixes
- emit
dist/index.d.ctsfor both packages and fix therequirecondition types (433d863) - make
jotaia peer dependency ofjarl-atomsandjarl-reactrather than a bundled one (80e88aa)
Tests
- smoke-test the published packages from a clean consumer project (450d7d5)
2.3.0 (2026-08-15)
Features
- jarl-react: add
Switchfor first-match routing with a fallback (3ab1ca5)
2.2.0 (2026-08-15)
Features
- add
notAtomfor catch-all and unmatched routes (7de8802) - infra: static-site stack — private S3 bucket behind CloudFront (0231ced)
- infra: SSR stack — EC2 behind the shared CloudFront front (3f2dca6)
Documentation
- Viking dark theme, gold accents and a monospace code font (cfed963, df7bdb6)
- adopt the chosen font pairing — Cinzel headings, Source Sans 3 body (4406851)
- adopt the candidate-01 helmet as the logo and favicon (b400fd0)
Tests
- wire the e2e fixture app to
queryAtom/redirectAtom/resolvedAtom(39d3ced)
2.1.0 (2026-08-14)
Published no library change: the only edits under packages/ were the version fields themselves
and a Discord invite link in both READMEs. The work below is the first infrastructure for the doc
site, under infra/, which is not published — it reached npm because the release pipeline
analysed every commit on master, not only those touching the published packages.
Features
- infra: add the CDK app scaffold for
jarl.randomdev.co.uk(d419da0)
Documentation
- update the Discord invite link in both package READMEs (aef4bec)
2.0.1 (2026-08-11)
The first release of the v2 rewrite.
JARL v2 is a ground-up rewrite around an atomic routing model. Routing state lives in
jotai atoms rather than in a router component's internal state: a route
resolves into atoms, and anything that needs the current location, query or resolved route reads
the atom directly instead of threading props or context down the tree. jarl-atoms holds that
framework-agnostic core, and jarl-react is the React binding over it — the two are released
together and always share a version number.
The v1 implementation and its url-pattern dependency are gone; v2 is not a drop-in upgrade from
the v1 beta line.
2.0.1 rather than 2.0.0 because v2.0.0 exists only as a baseline tag marking where the
rewrite reached version 2 — it was never published to npm, so this is the first v2 version
installable from the registry.
Features
- rewrite the docs around the atomic routing model (c303649)
- wire semantic-release into a CI publish job, with major-bump suppression (7973010, 084cda5)
- add a
betaprerelease branch to the release pipeline (1831d5a)
Bug Fixes
- correct package metadata and tarball contents for
jarl-atomsandjarl-react(fed93f0) - release: unblock the first publish (0371bbd)
Code Refactoring
Continuous Integration
- fix the e2e job to install its own dependencies, and drop
continue-on-error(c699f10) - bump CI to Node 24 to match the jsdom/undici engine requirements (d9d4e8b)
JARL: Version History
v1.0.0-beta.5
- Minor fix to avoid mangling URLs in some contexts
v1.0.0-beta.4
- Started testing React Native integration
- Interim release to get this working
v1.0.0-beta.3
- Fix: Got
activeworking everywhere properly, in particular inside demos - Fix: Edge case crash on redirect demos
- Demo: Code splitting now loads something substantial and is actually code splitting properly
- Demo: Code splitting shows a PDF which can also be navigated via routing
- Build: Made Webpack more aggressive about chunks
v1.0.0-beta.2
- New feature: improved API to accessing
resolveobjects. They are now available via theroutingHOC or theRouterFaC, alongside thelocationprops - Huge improvements and additions to docs
- Code splitting demo and main JARL API docs finally work properly
v1.0.0-beta.1
- Really actually fix deployment for good this time
- Got the code samples and Markdown docs looking much better
- Decided this can probably be called beta now 🎉
v1.0.0-alpha.15
- Fix rendering CHANGELOG
- Added some E2E tests around the demo shell
v1.0.0-alpha.14
- I screwed up. Had to bump another couple of versions to test the pipeline.
- Some improvments on the demo site:
- Syntax highlighted code examples
- Removed broken Redux Integration demo
- Switched UI over to Semantic UI
- Added the CHANGELOG
- Added API docs for JARL Native
v1.0.0-alpha.12
CI/CD
- Only tagged builds publish and deploy to production
- PRs and master untagged builds will deploy a staging demo site
- Build number added on docs site
- Really fixed prod deployment
- Created a Discord server: https://discord.gg/6yGq39rJ63
- Added a Discord bot to make build announcments in #build
v1.0.0-alpha.11
- Final deployment to production site was not working correctly, fixed this
- Run E2E against staging site, because why not
v1.0.0-alpha.10
- Some more work on generating API docs
- Added version number from package.json to site header
v1.0.0-alpha.9
- Moved away from Yarn workspaces (was being pretty buggy)
- Docker build and deployment of demo site (finally!)
- Docs and demos live at: https://jarl.downplay.co ❤️
v1.0.0-alpha.7
Deployment
- CircleCI!
- Jest, Cypress, eslint, plus builds all running in a shiny new CI pipeline
- Fixed some flaky time-based tests
- Got a build working for the demo/docs site
- Added new E2E tests and fixed all the broken ones
- Started adding tests to RN package
- Improved some of the local dev scripts
- Moved to Yarn workspaces
- Continuous deployment to npm
- Version took a large bump since last release due to multiple deployments whilst figuring out CI
Bugs
- Fixed that active status of links would be wrong on first page load
v1.0.0-alpha.4
- Fixed error due to missing actionTypes.js in
jarl-react-redux
v1.0.0-alpha.3
- Slightly relaxed error throwing in the case of an invalid Link. Don't really want to stop the whole app rendering (or even really throw at all) just because a Link was null, but we do want pretty obvious console errors if a location is unresolvable as that definitely indicates a bug.
v1.0.0-alpha.2
- React Native support! A new package
jarl-react-nativebrings a reasonably comprehensive RN compatible integration including:- A router wrapper,
NativeProvider, using createMemoryHistory - A variant of the Link component using TouchableHighlight
- Back Button (Android) and Deep Linking support. Both optional via props on the NativeProvider.
- A router wrapper,
v1.0.0-alpha
Breaking
The big rename landed! Massively simplified the API while providing more flexibility. (I hope!)
NavigationProvideris nowRoutingProviderperformInitialNavigation->performInitialRoutingonNavigateStartandonNavigateEndare collapsed into a singleonChange. The router is fully controlled: any additional transitions or preloading can be executed before you update location so advanced possibilities are still accounted for. Redux integration's API is unchanged but the whole package might be heading for deprecation.SimpleProvideris nowStateProviderwithContext,withLocation,withNavigateall disappeared and are replaced byroutingRouteMapperis nowRouteMapstatehas been renamed tolocationin some places:RoutingProviderandStateProvider's state prop- Signature of
onChangecallback - Return of
matchfunction onRouteMap - It has not changed on
Routeas this is clearly distinct and is generally just part of the whole location.
Other breaking:
resolvefunctions now execute in series; results aren't stored in state anymore but they are made available thruresolvedon the onChange handler
New features
- Brand new
routingHOC which provides all the functionality of the old HOCs (but with default parameters acts just likewithLocationused to) Routercomponent is a new function-as-child version ofwithLocation- Recent changes to
Linksupport all the functionality ofwithContextandwithNavigate(i.e. URL serialization, and navigate/redirect) with a function-as-child API.
v0.8.0
- Breaking: renamed
componentprop onLinktoelementto be more consistent with PropTypes - Breaking: changed the method signature of onNavigateStart and onNavigateEnd callbacks. They now emit an event object in the form
{ state, path, branch, action }and are now consistent with onNavigateError. - Added
actionto the callback emitted from onNavigateStart/onNavigateEnd/onNavigateError. This will be the action received from thehistorylistener and be one of: PUSH, REPLACE, or POP for actions triggered byhistory, or INITIAL or RELOAD for initial navigation or reloaded routes triggered by JARL. - Fixed nested stringifiers
- Proper implementation of isActive. Now considers the route hierarchy rather than looking purely at the URL -- meaning it will work with partial paths and query strings
- Added a function-as-child API to
<Link>; provideshref,activeandonClickprops so you can render anything that links to a route - Redirect now causes a history.replace() instead of history.push()
- Another big push on documentation
- Upgraded demos site to Webpack 4 / React Hot Loader 4
- Added
sideEffects: falseto package.json, for Webpack 4's "pure module" support - Bug fixes and other minor improvements
v0.7.2
- Fixed nested match
- Add a
componentprop to Link to override default anchor rendering
v0.7.1
- Fixed the build process for IE11 and other older browsers
v0.7.0
- New feature: redirects. Can be triggered from
state,match, orresolveby returning aredirectobject. See examples in demos. - Added a half-decent example to the README
v0.6.0
- Now supports
matchandstringifyfunctions on routes. These allow custom transforming both ways between state and URLs, for example converting :year/:month/:day into a Date object and back again - Fix: Removed usage of Object.values due to no support in older browsers and requirement of a polyfill
v0.5.1
- Fix: ES5 build was missing a file so imports would fail in some conditions
v0.5.0
- Major: official support for query strings (adds dependency on
qsfromhapijs) - Support most of path syntax within query strings, e.g.
/foo?q=:searchTime&bar=(:optionalParam)&*=:rest - Added property to NavigationProvider:
performInitialNavigation - Added property to NavigationProvider:
basePath - Breaking: renamed
withStateHOC towithLocationto avoid naming conflict withrecompose(andstatein general) - New
withContextHOC to get access tostringifyand other functions from the provider - Additional logic can now be added to route matching use
resolveproperty on your routes - Use empty location
{}for default Redux state - NavigationProvider's
routesproperty can now accept an array instead of a RouteMapper - Can now use
resolveon route objects - Allow
pathto be empty on routes; these can be used as containers to apply state, resolvers, query fragments in a grouped fashion; seethemesin thequeryStringsdemo! - Big sort out of the demos! A lot more use cases are now demonstrated and working properly
- Added tests to many things
v0.3.2
- Easier integration with and a new demo for Redux
<Provider/>component injarl-react-reduxis a standard integration that will (probably) do what you need- Named matches now automatically run through decodeURIComponent to handle special characters properly
- Correctly reattach to history in CWRP (necessary for React Hot Reload among other things)
v0.3.1
- Fix withNavigate's default props mapper
v0.3.0
- Breaking: Rename resolve->stringify. Resolve is already an overloaded term in JS. Stringify is much clearer meaning.
- Breaking: Rename withRouting->withNavigate. This HOC only injects a
navigatefunction so the name was confusing - Breaking: Restructured to monorepo design with
lerna. Redux extensions are now in separatejarl-react-reduxpackage - Properly sorted out build targets (CJS, UMD, ES) in both packages
- Better errors on stringification failure to debug state problems
- Add a new withState HOC to inject the current route's state
- Added many tests! Including E2E tests with cypress
- Started writing some proper documentation, updated README a bit
- Switched to custom build of
url-patternto support named wildcards with syntax:/*:name
v0.2.0
- Added route matching and path resolution for nested routes
v0.1.2
- Don't completely override Link's own onClick handler
v0.1.1
- Call onClick handler when Link is clicked (e.g. allowing consumers to call
event.stopPropagation())
v0.1.0
- Routes with dynamic path segments now resolve to URLs correctly
v0.0.8
- Link now supports string values for
toprop - Add enzyme config and a Link test
v0.0.5
- Initial release