Skip to main content

Frontend

The frontend is a Vite + React + TypeScript SPA. It consumes the backend through typed helpers and shares a custom Tome visual system.

Routing

web/src/App.tsx owns the top-level route tree:

  • Public auth routes: login, signup, reset, verification, invite landing, OAuth callback.
  • Authenticated app shell routes: campaign list, campaign detail, profile, upcoming sessions, platform settings.
  • Campaign routes use /campaigns/:id/:tab/:sub? so CampaignDetail stays mounted while users move between campaign tabs.

RequireAuth protects the app shell. GuestOnly keeps signed-in users out of login/signup flows.

API Layer

All network calls go through web/src/lib/api.ts. This file also contains the SSE streaming client for Rules Chat.

DTOs live in web/src/types.ts. Keep these synchronized with backend serializers. Do not call fetch from components.

State Boundaries

Global user/session state comes from web/src/lib/auth.tsx. Campaign navigation state is published through web/src/lib/campaign-nav.tsx so the chrome can show campaign tabs in the rail or mobile bottom bar.

Most feature screens keep local state and refetch through API helpers after mutations. Realtime campaign events use web/src/lib/useCampaignEvents.ts.

Screens

ScreenResponsibility
Campaigns.tsxCampaign list and campaign creation entry points.
CampaignDetail.tsxCampaign shell, tab selection, campaign-level data load.
RulesChat.tsxSage chat UI and streamed card rendering.
CampaignDocuments.tsxCampaign document upload/index management.
CampaignCoreSources.tsxCampaign core-rule opt-ins.
CampaignCodex.tsxStory entities, recap review, Codex search/results.
CampaignNpcs.tsxNPC roster and relationship editing.
PlatformSettings.tsxAdmin users, core rules, ingestion settings.
Upcoming.tsxCross-campaign session feed.

Components

Feature widgets live in web/src/components/: combat tracker, encounter list, session list/editor, roll call, NPC cards, stat blocks, loot/table/dice cards, modals, shared form controls, and layout chrome.

Icons must go through web/src/components/Icon.tsx, which maps names to FontAwesome glyphs.

Styling

The visual system lives in web/src/styles/tome.css, with theme values in web/src/lib/theme.ts and theme-provider.tsx.

Prefer existing classes and components. Avoid one-off style systems in feature screens. Keep loading, empty, and error states explicit for every fetch.