Frontend
The frontend is a React 19 single-page app bundled by Vite 7.
Entry points
src/main.tsx mounts <App />. App.tsx branches on the current window:
- A live display window renders
<DisplayProvider />inside aThemeProviderand nothing else. - The main window renders the startup dialog, the licenses sheet, and then
either
<EmptyShow>, the edit UI (AppSidebar+EditableShowBody), or<PerformMode>, depending on the mode and whether the show is empty.
The window type is decided by isDisplayWindow() in src/lib/window.ts, which
reads the Tauri webview window label (main, live-display-N, …).
Component map
| Area | Components |
|---|---|
| Shell | App.tsx, app-sidebar.tsx, editable-show-body.tsx |
| Show editing | section-row.tsx, section-children.tsx, section-cues.tsx, cue.tsx |
| Perform | perform-mode/perform-mode.tsx, perform-toolbar.tsx, cue-table.tsx |
| Live display | display/display-provider.tsx, display/display.tsx |
| Dialogs & sheets | startup-dialog.tsx, license-sheet.tsx, ocr-import-progress.tsx |
| Atoms | atoms/click-to-edit-component.tsx, confirm-delete.tsx, tooltip-icon-button.tsx |
| Primitives | components/ui/* — shadcn/ui, managed by the CLI, never edited manually |
Styling
- Tailwind CSS 4 via the Vite plugin, with design tokens defined in
src/App.cssand component styling via utility classes. - shadcn/ui (radix-mira style) primitives live in
src/components/ui/. Add new ones withpnpm sh:add <component>rather than copying files. - Class names are merged with
cn()fromsrc/lib/utils.ts(clsx + tailwind-merge).
Theming
src/providers/theme-provider.tsx supplies light/dark theme context, persisted
to localStorage. The app defaults to dark mode to suit stage environments.
Platform bindings
Three small modules isolate Tauri from the rest of the UI:
src/lib/tauri.ts— typed wrappers overinvokefor every command.src/lib/events.ts— event name constants and payload types.src/lib/window.ts— window-label helpers.
Keep these thin: components should call the wrappers, not invoke directly
(the perform toolbar's open_display_window call is the one direct exception).
Conventions
- Path alias
@/maps tosrc/. - Component files are kebab-case; type-only files are PascalCase.
- Prettier: double quotes, semicolons, 2-space indent, trailing commas.
- Strict TypeScript with
noUnusedLocalsandnoUnusedParameters.