# hejmsdz/slides-web architecture

> Architecture diagram of the GitHub repository hejmsdz/slides-web, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-11). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/hejmsdz/slides-web
- Repository: https://github.com/hejmsdz/slides-web

## Overview

#### Purpose and Runtime
This is a TypeScript React Router application for creating, organizing, and presenting song lyrics as slides. It has a public landing page, authenticated dashboard, shareable/live presentation views, and PDF rendering/export. Client and server entry points are `app/entry.client.tsx`, `app/entry.server.tsx`, and `app/root.tsx`; route registration is centralized in `app/routes.ts`.

#### Routing and Application Shell
Route modules form the primary server/UI boundary: loaders/actions can serve pages and mutations while React renders route content. Public routes include landing, privacy, waitlist, status, invitations, and live views; dashboard routes group authenticated management workflows. Core paths: `app/routes/_index.tsx`, `app/routes/dashboard.tsx`, `app/routes/$live.tsx`, and `app/routes/$live.pdf.tsx`.

#### Authentication, Sessions, and Authorization
Authentication is server-side and exposed through dedicated auth routes, including Google login/callback, nonce callback, and logout. Session and cookie concerns are isolated from route modules, while API endpoints likely provide current-user/team context. Relevant boundaries: `app/auth.server.ts`, `app/session.ts`, `app/cookies.server.ts`, `app/routes/auth.google.ts`, and `app/routes/auth.google.callback.ts`. Local session storage is represented by `data/sessions`.

#### Dashboard Domain: Users, Teams, and Songs
The dashboard is the management surface for account settings, team membership/invitations, and song CRUD. Song editing is routed per song; account/team mutations are explicit action routes, helping keep ownership and authorization at server boundaries. Primary modules: `app/routes/dashboard.songs.$id.tsx`, `app/routes/dashboard.songs.new.tsx`, `app/routes/dashboard.settings.tsx`, `app/routes/dashboard.teams.$id.invite.ts`, and `app/routes/dashboard.account.update.tsx`.

#### API and Client Data Access
Server API modules separate domain access from UI routes: bootstrap/live data, authentication, users, teams, and songs. Client hooks consume dashboard and paginated-song data, while `app/cache.client.ts` indicates browser-side cache coordination. Main paths: `app/api/api.ts`, `app/api/bootstrap.ts`, `app/api/live.ts`, `app/api/songs.ts`, `app/api/teams.ts`, `app/hooks/use-dashboard-data.ts`, and `app/hooks/use-paginated-songs.ts`.

#### Song-to-Presentation Pipeline
Song authoring components collect lyrics and typesetting settings, generate slide previews, and feed presentation/PDF views. A live identifier route exposes presentation output separately from the dashboard, including a PDF-specific route. Key components: `app/components/songs/song-form.tsx`, `app/components/songs/lyrics-editor.tsx`, `app/components/songs/typesetting.tsx`, `app/components/songs/slides-preview.tsx`, and `app/components/pdf/pdf-presentation.tsx`.

#### Presentation Delivery and Infrastructure
Presentation styling and PDF client behavior are isolated for display-oriented rendering. Static Cast assets include PDF.js and its worker, suggesting browser/device presentation support without routing through the app server. The deployment artifact is Docker-based, with a GitHub workflow for image builds. Paths: `app/styles/presentation.css`, `app/components/pdf/pdf.client.ts`, `public/cast/index.html`, `public/cast/pdf.js`, `Dockerfile`, and `.github/workflows/docker-image.yml`.

Main entry points: [`app/routes.ts`](https://github.com/hejmsdz/slides-web/blob/main/app/routes.ts) (Route registry), [`app/components/songs/song-form.tsx`](https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/song-form.tsx) (Song authoring), [`app/auth.server.ts`](https://github.com/hejmsdz/slides-web/blob/main/app/auth.server.ts) (Auth service), [`app/routes/dashboard.tsx`](https://github.com/hejmsdz/slides-web/blob/main/app/routes/dashboard.tsx) (Dashboard shell)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["App Runtime"]
  node_client["Client entry<br/>React bootstrap<br/>[entry.client.tsx]"]
  node_server["Server entry<br/>SSR runtime<br/>[entry.server.tsx]"]
  node_root["Root shell<br/>React shell<br/>[root.tsx]"]
  node_routes["Route registry<br/>route map<br/>[routes.ts]"]
  node_public["Public landing<br/>public route<br/>[_index.tsx]"]
end

subgraph group_auth["Identity"]
  node_auth_service{{"Auth service<br/>server auth<br/>[auth.server.ts]"}}
  node_session[("Session layer<br/>session storage<br/>[session.ts]")]
  node_cookies["Cookie handling<br/>server cookies<br/>[cookies.server.ts]"]
  node_google_auth["Google auth routes<br/>[auth.google.ts]"]
  node_google_callback["Google callback<br/>auth route"]
end

subgraph group_dashboard["Dashboard"]
  node_dashboard["Dashboard shell<br/>authenticated route<br/>[dashboard.tsx]"]
  node_song_editor_route["Song editor route<br/>song CRUD route"]
  node_song_form["Song authoring<br/>editor UI<br/>[song-form.tsx]"]
  node_lyrics_editor["Lyrics editor<br/>authoring component<br/>[lyrics-editor.tsx]"]
  node_typesetting["Typesetting<br/>authoring component<br/>[typesetting.tsx]"]
  node_dashboard_data["Dashboard data hook<br/>client data hook"]
  node_songs_api{{"Songs API<br/>server domain API<br/>[songs.ts]"}}
  node_teams_api{{"Teams API<br/>server domain API<br/>[teams.ts]"}}
end

subgraph group_presentation["Presentation"]
  node_live_route["Live presentation<br/>public live route<br/>[$live.tsx]"]
  node_slides_preview["Slide preview<br/>presentation component<br/>[slides-preview.tsx]"]
  node_pdf_route["PDF presentation<br/>PDF route<br/>[$live.pdf.tsx]"]
  node_pdf_presentation["PDF renderer<br/>PDF component"]
  node_live_api{{"Live API<br/>presentation API<br/>[live.ts]"}}
end

subgraph group_delivery["Delivery"]
  node_cast_assets["Cast PDF assets<br/>static viewer assets<br/>[index.html]"]
  node_container{{"Docker image<br/>deployment artifact"}}
  node_ci["Image build workflow<br/>CI workflow<br/>[docker-image.yml]"]
end

node_client -->|"hydrates"| node_root
node_server -->|"renders"| node_root
node_routes -->|"registers"| node_public
node_routes -->|"registers"| node_dashboard
node_routes -->|"registers"| node_google_auth
node_routes -->|"registers"| node_google_callback
node_routes -->|"registers"| node_live_route
node_routes -->|"registers"| node_pdf_route
node_google_auth -->|"starts login"| node_auth_service
node_google_callback -->|"completes login"| node_auth_service
node_auth_service -->|"creates session"| node_session
node_session -->|"uses"| node_cookies
node_dashboard -->|"requires user"| node_auth_service
node_dashboard -->|"loads client data"| node_dashboard_data
node_dashboard_data -->|"reads songs"| node_songs_api
node_dashboard_data -->|"reads teams"| node_teams_api
node_song_editor_route -->|"loads and saves"| node_songs_api
node_song_editor_route -->|"renders"| node_song_form
node_song_form -->|"edits lyrics"| node_lyrics_editor
node_song_form -->|"configures layout"| node_typesetting
node_song_form -->|"generates preview"| node_slides_preview
node_live_route -->|"loads live data"| node_live_api
node_live_route -->|"renders slides"| node_slides_preview
node_pdf_route -->|"loads live data"| node_live_api
node_pdf_route -->|"renders PDF"| node_pdf_presentation
node_pdf_presentation -->|"uses viewer assets"| node_cast_assets
node_ci -->|"builds image"| node_container

click node_client "https://github.com/hejmsdz/slides-web/blob/main/app/entry.client.tsx"
click node_server "https://github.com/hejmsdz/slides-web/blob/main/app/entry.server.tsx"
click node_root "https://github.com/hejmsdz/slides-web/blob/main/app/root.tsx"
click node_routes "https://github.com/hejmsdz/slides-web/blob/main/app/routes.ts"
click node_public "https://github.com/hejmsdz/slides-web/blob/main/app/routes/_index.tsx"
click node_auth_service "https://github.com/hejmsdz/slides-web/blob/main/app/auth.server.ts"
click node_session "https://github.com/hejmsdz/slides-web/blob/main/app/session.ts"
click node_cookies "https://github.com/hejmsdz/slides-web/blob/main/app/cookies.server.ts"
click node_google_auth "https://github.com/hejmsdz/slides-web/blob/main/app/routes/auth.google.ts"
click node_google_callback "https://github.com/hejmsdz/slides-web/blob/main/app/routes/auth.google.callback.ts"
click node_dashboard "https://github.com/hejmsdz/slides-web/blob/main/app/routes/dashboard.tsx"
click node_song_editor_route "https://github.com/hejmsdz/slides-web/blob/main/app/routes/dashboard.songs.%24id.tsx"
click node_song_form "https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/song-form.tsx"
click node_lyrics_editor "https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/lyrics-editor.tsx"
click node_typesetting "https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/typesetting.tsx"
click node_dashboard_data "https://github.com/hejmsdz/slides-web/blob/main/app/hooks/use-dashboard-data.ts"
click node_songs_api "https://github.com/hejmsdz/slides-web/blob/main/app/api/songs.ts"
click node_teams_api "https://github.com/hejmsdz/slides-web/blob/main/app/api/teams.ts"
click node_live_route "https://github.com/hejmsdz/slides-web/blob/main/app/routes/%24live.tsx"
click node_slides_preview "https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/slides-preview.tsx"
click node_pdf_route "https://github.com/hejmsdz/slides-web/blob/main/app/routes/%24live.pdf.tsx"
click node_pdf_presentation "https://github.com/hejmsdz/slides-web/blob/main/app/components/pdf/pdf-presentation.tsx"
click node_live_api "https://github.com/hejmsdz/slides-web/blob/main/app/api/live.ts"
click node_cast_assets "https://github.com/hejmsdz/slides-web/blob/main/public/cast/index.html"
click node_container "https://github.com/hejmsdz/slides-web/blob/main/Dockerfile"
click node_ci "https://github.com/hejmsdz/slides-web/blob/main/.github/workflows/docker-image.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_client,node_server,node_root,node_routes,node_public toneBlue
class node_auth_service,node_session,node_cookies,node_google_auth,node_google_callback toneAmber
class node_dashboard,node_song_editor_route,node_song_form,node_lyrics_editor,node_typesetting,node_dashboard_data,node_songs_api,node_teams_api toneMint
class node_live_route,node_slides_preview,node_pdf_route,node_pdf_presentation,node_live_api toneRose
class node_cast_assets,node_container,node_ci toneIndigo
```

## Components

### App Runtime

- [Client entry](https://github.com/hejmsdz/slides-web/blob/main/app/entry.client.tsx): React bootstrap · `app/entry.client.tsx`
- [Server entry](https://github.com/hejmsdz/slides-web/blob/main/app/entry.server.tsx): SSR runtime · `app/entry.server.tsx`
- [Root shell](https://github.com/hejmsdz/slides-web/blob/main/app/root.tsx): React shell · `app/root.tsx`
- [Route registry](https://github.com/hejmsdz/slides-web/blob/main/app/routes.ts): route map · `app/routes.ts`
- [Public landing](https://github.com/hejmsdz/slides-web/blob/main/app/routes/_index.tsx): public route · `app/routes/_index.tsx`

### Identity

- [Auth service](https://github.com/hejmsdz/slides-web/blob/main/app/auth.server.ts): server auth · Owns authentication and authorization checks. · `app/auth.server.ts`
- [Session layer](https://github.com/hejmsdz/slides-web/blob/main/app/session.ts): session storage · `app/session.ts`
- [Cookie handling](https://github.com/hejmsdz/slides-web/blob/main/app/cookies.server.ts): server cookies · `app/cookies.server.ts`
- [Google auth routes](https://github.com/hejmsdz/slides-web/blob/main/app/routes/auth.google.ts): auth routes · `app/routes/auth.google.ts`
- [Google callback](https://github.com/hejmsdz/slides-web/blob/main/app/routes/auth.google.callback.ts): auth route · `app/routes/auth.google.callback.ts`

### Dashboard

- [Dashboard shell](https://github.com/hejmsdz/slides-web/blob/main/app/routes/dashboard.tsx): authenticated route · `app/routes/dashboard.tsx`
- [Song editor route](https://github.com/hejmsdz/slides-web/blob/main/app/routes/dashboard.songs.%24id.tsx): song CRUD route · `app/routes/dashboard.songs.$id.tsx`
- [Song authoring](https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/song-form.tsx): editor UI · `app/components/songs/song-form.tsx`
- [Lyrics editor](https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/lyrics-editor.tsx): authoring component · `app/components/songs/lyrics-editor.tsx`
- [Typesetting](https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/typesetting.tsx): authoring component · `app/components/songs/typesetting.tsx`
- [Dashboard data hook](https://github.com/hejmsdz/slides-web/blob/main/app/hooks/use-dashboard-data.ts): client data hook · `app/hooks/use-dashboard-data.ts`
- [Songs API](https://github.com/hejmsdz/slides-web/blob/main/app/api/songs.ts): server domain API · `app/api/songs.ts`
- [Teams API](https://github.com/hejmsdz/slides-web/blob/main/app/api/teams.ts): server domain API · `app/api/teams.ts`

### Presentation

- [Live presentation](https://github.com/hejmsdz/slides-web/blob/main/app/routes/%24live.tsx): public live route · `app/routes/$live.tsx`
- [Slide preview](https://github.com/hejmsdz/slides-web/blob/main/app/components/songs/slides-preview.tsx): presentation component · `app/components/songs/slides-preview.tsx`
- [PDF presentation](https://github.com/hejmsdz/slides-web/blob/main/app/routes/%24live.pdf.tsx): PDF route · `app/routes/$live.pdf.tsx`
- [PDF renderer](https://github.com/hejmsdz/slides-web/blob/main/app/components/pdf/pdf-presentation.tsx): PDF component · `app/components/pdf/pdf-presentation.tsx`
- [Live API](https://github.com/hejmsdz/slides-web/blob/main/app/api/live.ts): presentation API · `app/api/live.ts`

### Delivery

- [Cast PDF assets](https://github.com/hejmsdz/slides-web/blob/main/public/cast/index.html): static viewer assets · Includes PDF.js and its worker. · `public/cast/index.html`
- [Docker image](https://github.com/hejmsdz/slides-web/blob/main/Dockerfile): deployment artifact · `Dockerfile`
- [Image build workflow](https://github.com/hejmsdz/slides-web/blob/main/.github/workflows/docker-image.yml): CI workflow · `.github/workflows/docker-image.yml`

## Connections

- Client entry → Root shell: hydrates
- Server entry → Root shell: renders
- Route registry → Public landing: registers
- Route registry → Dashboard shell: registers
- Route registry → Google auth routes: registers
- Route registry → Google callback: registers
- Route registry → Live presentation: registers
- Route registry → PDF presentation: registers
- Google auth routes → Auth service: starts login
- Google callback → Auth service: completes login
- Auth service → Session layer: creates session
- Session layer → Cookie handling: uses
- Dashboard shell → Auth service: requires user
- Dashboard shell → Dashboard data hook: loads client data
- Dashboard data hook → Songs API: reads songs
- Dashboard data hook → Teams API: reads teams
- Song editor route → Songs API: loads and saves
- Song editor route → Song authoring: renders
- Song authoring → Lyrics editor: edits lyrics
- Song authoring → Typesetting: configures layout
- Song authoring → Slide preview: generates preview
- Live presentation → Live API: loads live data
- Live presentation → Slide preview: renders slides
- PDF presentation → Live API: loads live data
- PDF presentation → PDF renderer: renders PDF
- PDF renderer → Cast PDF assets: uses viewer assets
- Image build workflow → Docker image: builds image
