SPA sidebar navigation compounds URL path across successive clicks (stale root_path-relative links) #70
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
In a static
zetl builddeployed under a SPA shell (_static/spa.js), successive in-app navigations via the persistent sidebar compound the URL path instead of replacing it. After two clicks you get URLs like:which 404 (or fall back), breaking navigation.
Affects zetl 0.9.1 (static build +
spa.js).Root cause
spa.js(swap()) replaces only the[data-zetl-volatile]element and intentionally keeps the shell — including the sidebar — mounted:But the sidebar links are depth-relative, built from the page's
root_path(e.g.themes/default/base.htmlsidebar tree:href="{{ root_path }}{{ node.slug }}/{{ index_file }}").root_pathis computed for the page that was originally loaded from the static host. SPA navigation changesdocumentURL (the base for resolving relative links) viapushStatewithout re-rendering the sidebar, so the sidebar keeps hrefs relative to the original page's depth.When the new document URL is deeper than the original, those stale relative hrefs resolve against the wrong (deeper) base, appending instead of replacing. Each further sidebar click compounds again.
Exact trace (matches the reported URL)
/→root_pathis empty, so sidebar link to insight-exchange isorgs/insight-exchange/index.html, to datafication isresearch/datafication-of-metoo/index.html, etc./→/orgs/insight-exchange/index.html.pushStatesets URL there. Sidebar is not re-rendered — still homepage-relative.research/datafication-of-metoo/index.html): now resolves against base/orgs/insight-exchange/→/orgs/insight-exchange/research/datafication-of-metoo/index.html. Compounded.research/tech-abuse-and-coercive-control/index.html): resolves against the depth-3 base →/orgs/insight-exchange/research/datafication-of-metoo/research/tech-abuse-and-coercive-control/index.html. Exactly the reported URL.The
getAttribute('href')→a.hrefpath in the click handler uses the browser's resolution against the currentdocument.baseURI, which is why the stale relative hrefs drift.Reproduction
Deploy a
zetl buildto a static host (e.g. Cloudflare Pages). From the homepage, click a sidebar entry in a subfolder, then click a second sidebar entry. The address bar shows a compounded path and the page fails to load.Suggested fix
The persistent shell can't use depth-relative links that go stale on
pushState. Options:{{ site_base }}/orgs/...) rather thanroot_path-relative, so resolution is independent of the current document depth (respecting any sub-path deploy base).spa.jsafterswap(), rebase the persistent shell'shref/srcfor the new URL (or re-render the sidebar from the fetched document).<base href>and keep it correct across navigations (note<base>affects all relative URLs).Add a test simulating two successive SPA navigations from the homepage into a subfolder and asserting the resulting URL is not compounded.
Fixed in zetl 0.9.2. spa.js now pins persistent-shell links to absolute URLs at load, so successive sidebar navigations no longer compound the path.