Problem
Refreshing the browser on any client-side route (e.g. /app/login, /app/posts/123) returns a 404:
The WebTabResourceModule in WebAssetsModule.kt serves static files from classpath:/web/ at the /app/ prefix, but has no fallback for SPA routes. When the browser requests a path like /app/posts/123, Misk looks for a matching static file or action, finds none, and returns a 404.
Suggested remedy
Add a catch-all SpaFallbackAction mapped to /app/{path:.*} that serves the index.html from classpath resources for non-asset paths (i.e. paths without a file extension). This allows React Router to handle routing client-side while preserving the URL, so the user lands on the correct page as if they had navigated there within the SPA.
Static asset paths (containing a .) should still return 404 to avoid masking genuinely missing files.
Files to change
- New:
src/main/kotlin/.../actions/SpaFallbackAction.kt — catch-all action that loads classpath:/web/index.html and serves it with Content-Type: text/html
- Edit:
src/main/kotlin/.../WebAssetsModule.kt — register SpaFallbackAction via WebActionModule.create<SpaFallbackAction>()
Problem
Refreshing the browser on any client-side route (e.g.
/app/login,/app/posts/123) returns a 404:The
WebTabResourceModuleinWebAssetsModule.ktserves static files fromclasspath:/web/at the/app/prefix, but has no fallback for SPA routes. When the browser requests a path like/app/posts/123, Misk looks for a matching static file or action, finds none, and returns a 404.Suggested remedy
Add a catch-all
SpaFallbackActionmapped to/app/{path:.*}that serves theindex.htmlfrom classpath resources for non-asset paths (i.e. paths without a file extension). This allows React Router to handle routing client-side while preserving the URL, so the user lands on the correct page as if they had navigated there within the SPA.Static asset paths (containing a
.) should still return 404 to avoid masking genuinely missing files.Files to change
src/main/kotlin/.../actions/SpaFallbackAction.kt— catch-all action that loadsclasspath:/web/index.htmland serves it withContent-Type: text/htmlsrc/main/kotlin/.../WebAssetsModule.kt— registerSpaFallbackActionviaWebActionModule.create<SpaFallbackAction>()