Application routes and navigation
View as MarkdownIdentity
Section titled “Identity”Generated packages/frontend/src/App.tsx,
packages/frontend/src/SapportaApp.tsx, and
packages/frontend/src/SapportaRoutes.tsx.
Application contributions
Section titled “Application contributions”The generated App.tsx exports five values:
import type { ReactElement } from "react";import { Navigate, Route } from "react-router-dom";import type { Navigation } from "@sapporta/frontend/shell";
export const appNavigation: Navigation = [ { label: "Views", items: [{ label: "Progress", to: "/projects/progress" }], },];
export const appHomeRoute = ( <Route index element={<Navigate to="/projects/progress" replace />} />);
export const appPublicHomeRoute: ReactElement | null = null;
export const appPublicRoutes = ( <Route path="status" element={<PublicStatus />} />);
export const appProtectedRoutes = ( <Route path="projects/progress" element={<ProjectProgress />} />);appNavigationis a readonly array of labeled sections. Each item has alabel, an absoluteto, and an optional icon.appHomeRouteis the index route at/. It renders insideAuthGate, so it opens for a signed-in session and is where sign-in returns.appPublicHomeRouteis an optional index route at/for a visitor without a session. It isnullin a generated project. A non-null value takes/in place ofappHomeRoute, so an app that needs both an anonymous landing page and a signed-in home screen gives the signed-in screen its own path inappProtectedRoutes.appPublicRoutesandappProtectedRoutesare JSX route fragments, not route object arrays.
Nested React Router path values omit the leading slash. Navigation to values
are absolute. The current extension points are singular appNavigation and
appHomeRoute; there are no generated appNavigationItems or appHomeRoutes
exports.
Bootstrap and route order
Section titled “Bootstrap and route order”The current starter mounts one application QueryClientProvider around the
router. SapportaApp.tsx then composes routes in this order:
- Sapporta’s framework public routes, outside application bootstrap.
BootLoader, which restores the browser session and loads table metadata for an authenticated session before rendering the shell.appPublicHomeRouteandappPublicRoutes, insideAppShelland outsideAuthGate.appHomeRoute,appProtectedRoutes, and Sapporta’s protected routes, insideAuthGate.appHomeRouteis mounted only whileappPublicHomeRouteisnull.
SapportaApp.tsx performs that composition. The ordinary way to change where a
screen renders is to move it between the App.tsx slots.
An application public route can render for a guest, but it still participates in
the application bootstrap and shell. Put it in appPublicRoutes only when its
page and data are intentionally anonymous. A protected contribution renders only
after session bootstrap has settled and an authenticated workspace is available.
Feature modules reuse the starter’s QueryClient. A nested provider would split cache invalidation, error handling, and DevTools state from the rest of the application.
Screens from @sapporta/frontend
Section titled “Screens from @sapporta/frontend”SapportaRoutes.tsx mounts the screens the library ships. Each page is lazily
imported from @sapporta/frontend, so a screen’s code loads when its URL is
first visited, and SapportaApp.tsx composes what the file exports.
sapportaPublicRoutes—login,signup,verify-email,forgot-password, andreset-password.loginandsignuprender insidePublicOnlyGate, which sends a session that already exists to the application instead.sapportaProtectedRoutes—account/profile,account/password,workspace/settings,tables/:tableName, andtables/:tableName/new. The workspace settings screen is where an owner changes the workspace time zone.sapportaNotFoundRoute—*, renderingNotFoundView.
Generated table navigation
Section titled “Generated table navigation”Use /tables/:tableName for the generated table screen and
/tables/:tableName/new for its create screen. For example, the project create
target is /tables/projects/new.
There is no generated browser detail route at /tables/:tableName/:id. Record
interaction stays in the generated table workflow unless the application
contributes its own detail route. The
generated record surfaces reference
owns the complete generated-route inventory.
Authorization boundary
Section titled “Authorization boundary”AuthGate redirects guest and workspace-required browser sessions. It also
redirects an unverified session when the project’s email-verification policy is
enabled. That protected-route boundary is application UX. It does not authorize
an API operation or enforce row visibility.
Generated table handlers and application API routes must still enforce their server-side ability, authority, row-scope, and write-integrity rules. Navigation visibility, hidden fields, fixed filters, route parameters, and client cache keys are not authorization.
getApiBase and the router bridge provide platform integration for project
screens; neither changes that server boundary.