Files
teaching-design/docs/superpowers/specs/2026-06-16-frontend-routing-design.md

3.3 KiB

Frontend Routing Design

Goal

Add URL-backed frontend routing so users can refresh or directly open the main app views without losing their place.

Scope

In scope:

  • Add routes for login, book list, book workspace, and admin user management.
  • Keep the existing component structure: LoginPage, BookListPage, WorkspaceView, and AdminPage.
  • Preserve the existing auth behavior and API calls.
  • Preserve the existing backend API routes and static SPA fallback.
  • Add focused tests for routing behavior.

Out of scope:

  • Adding nested lesson-level URLs.
  • Adding a new navigation layout.
  • Replacing the current auth model.
  • Adding a third-party router package unless the existing code makes a local router impractical.

Approaches Considered

The recommended approach is a small local router built around window.history and popstate. The project does not currently use vue-router, and the app only needs four top-level route states. A local router keeps the change small and avoids a new dependency.

A second option is adding vue-router. It would be more conventional for a growing Vue app, but it adds dependency and setup overhead for a narrow routing surface.

A third option is hash routing, such as /#/books/b1. It avoids server fallback concerns, but the server already serves dist/index.html for unknown paths, so clean history URLs are a better fit.

Routes

The frontend will support these clean URLs:

  • /login shows LoginPage.
  • /books shows BookListPage.
  • /books/:bookId shows WorkspaceView for the selected book.
  • /admin shows AdminPage.

Unknown paths redirect to the best available default: /books when logged in and /login when logged out.

Auth Behavior

App.vue still calls fetchMe() on mount. While logged out, any route except /login resolves to the login page and updates the URL to /login.

After login succeeds, the app routes to /books. Logout continues to clear tokens through useAuth; when the app observes the logged-out state, it routes to /login.

The admin page remains visible only through the existing admin entry point in BookListPage. If a non-admin user reaches /admin directly, the backend admin API will still return authorization errors. The frontend may render the page shell, but protected data will not load.

Component Behavior

BookListPage keeps emitting open and admin. App.vue will translate those events into route changes:

  • open(id) navigates to /books/{id}.
  • admin navigates to /admin.

WorkspaceView keeps emitting back; App.vue maps it to /books.

AdminPage keeps emitting back; App.vue maps it to /books.

This preserves component contracts and confines route ownership to the app shell.

Error Handling

Book load errors remain handled by WorkspaceView. Its existing "返回列表" action navigates back to /books.

Route parsing should be strict enough to avoid invalid view state. Empty or malformed book IDs fall back to /books.

Testing

Add or update App.test.ts coverage for:

  • Starting at /books renders the book list.
  • Opening a book updates the URL to /books/:bookId and renders the workspace.
  • Pressing workspace back updates the URL to /books.
  • Opening admin updates the URL to /admin.
  • Logged-out users are routed to /login.

Run the focused app tests and the project build after implementation.