Skip to content

management-ui: migrate HashRouter to BrowserRouter - #359

Open
mrFlick72 wants to merge 6 commits into
mainfrom
fix/325-browserrouter-migration
Open

management-ui: migrate HashRouter to BrowserRouter#359
mrFlick72 wants to merge 6 commits into
mainfrom
fix/325-browserrouter-migration

Conversation

@mrFlick72

Copy link
Copy Markdown
Owner

Summary

  • Swap HashRouterBrowserRouter in src/admin/index.tsx, with basename="/secure/admin" and a catch-all redirect route
  • Update nginx SPA fallback in docker/default.conf.template for BrowserRouter deep links

Closes #325

Test plan

  • Clean URLs (/secure/admin/roles, not /secure/admin/#/roles)
  • Hard refresh on a deep route loads correctly instead of 404ing
  • Browser back/forward navigation works across admin routes
  • Full login flow (redirect to IdP → callback → returnTo restoration) lands back on the originating deep route
  • Unmatched path under /secure/admin/* redirects to home
  • Verified manually via local/docker-compose.yml

mrFlick72 and others added 6 commits August 29, 2026 17:18
Falls back to index.html for any unmatched path under /secure/admin
instead of 404ing. No-op under the current HashRouter, but required
before deep links / refreshes work once the router moves to
BrowserRouter (#357).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019KZoBG7SfG9ZXu5T4y34Qm
Set basename="/secure/admin" (the app isn't served at domain root)
and add a catch-all route redirecting to home, since the nginx SPA
fallback (previous commit) now serves index.html for any unmatched
path.

Verified manually against the local docker-compose stack: clean URLs,
hard refresh on a deep route, browser back/forward, and the full
login -> callback -> returnTo redirect flow all land on the correct
route. Legacy hash-style bookmarks intentionally land on home instead
of the old target (BrowserRouter ignores the fragment) - acceptable
for this internal admin tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019KZoBG7SfG9ZXu5T4y34Qm
The hamburger icon in AdminTemplate.tsx was wrapped in <a href="#">, a
HashRouter-era "go home" trick (an empty hash resolved to path "/").
Under BrowserRouter that's a no-op fragment link, so the button did
nothing. Replaced it with react-router's <Link to="/">, matching the
pattern already used in MenuCard.tsx.

Also update management-ui/AGENTS.md, which still documented
HashRouter as the current routing style and instructed future agents
to preserve it - now describes BrowserRouter + the /secure/admin
basename, and calls out that internal navigation must go through
Link/useNavigate rather than raw <a href> tags.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S2ymDVQMGTkRWSh5NHZrWV
webpack's HtmlWebpackPlugin bakes a relative script src into
secure/admin/index.html, computed once at build time for that file's
own nesting depth (e.g. src="../../admin.js"). Since nginx's SPA
fallback serves that same physical file for every URL under
/secure/admin/*, the relative path only resolves correctly when the
browser URL has exactly the same depth as the build output.

Routes with more path segments than the build depth - all of
/client-applications/list, /client-applications/save,
/client-applications/edit/:id, /accounts/edit/:email - resolved the
script to a wrong nested URL. nginx's fallback then serves
index.html for that request too, so the browser tries to execute
HTML as JS ("Unexpected token '<'") and the app never mounts: a
blank page on refresh. Only single-segment routes (/roles, /accounts,
/keys, /email-templates) happened to work, which is why the issue's
own example (/secure/admin/accounts) didn't catch it.

Set output.publicPath to an absolute "/" so every emitted script tag
is root-relative regardless of which URL served the HTML. Verified
via a headless-browser hard load of
/secure/admin/client-applications/edit/abc123 against a build with
and without the fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S2ymDVQMGTkRWSh5NHZrWV
Home was routed at basename root ("/", i.e. /secure/admin), but the
established convention documented in auth-server/local/readme.md is
.../secure/admin/index. Route the home page at /index instead, point
the hamburger menu link and the catch-all redirect at it, and let
bare /secure/admin fall through the catch-all to /index so both still
resolve to the same page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S2ymDVQMGTkRWSh5NHZrWV
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate management-ui router from HashRouter to BrowserRouter

1 participant