# casualoffice/slides architecture

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

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

## Overview

Casual Slides is a self-hostable browser presentation editor built on Univer, with PowerPoint-style editing and `.pptx` round-trip. The main workflow is opening or creating a deck, editing slides through the shell and Univer command bridge, then exporting or retaining an autosave. README-described features include slide management, themes, notes, slideshow, recent files, and optional raw-WebSocket co-editing. Source excerpts show the app-to-command, app-to-file-client, worker, and autosave relationships; unsampled UI wiring and the server’s collaboration protocol are not inferred.

Main entry points: [`apps/web/src/App.tsx`](https://github.com/casualoffice/slides/blob/main/apps/web/src/App.tsx) (Editor shell), [`apps/web/src/univer/commands.ts`](https://github.com/casualoffice/slides/blob/main/apps/web/src/univer/commands.ts) (Slide commands), [`apps/web/src/pptx/worker.ts`](https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/worker.ts) (PPTX worker), [`apps/web/src/shell/FormatPane.tsx`](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/FormatPane.tsx) (Format pane)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_editor["Presentation editor"]
  node_app["Editor shell<br/>[App.tsx]"]
  node_engine["Univer canvas<br/>[UniverSlide.tsx]"]
  node_commands["Slide commands<br/>[commands.ts]"]
  node_toolbar["Ribbon tools<br/>[Toolbar.tsx]"]
  node_format["Format pane<br/>[FormatPane.tsx]"]
  node_selection["Selection bridge<br/>[selection.ts]"]
  node_slides["Slide rail<br/>[SlideRail.tsx]"]
  node_slide_menu["Slide actions"]
  node_element_menu["Element actions"]
  node_find["Find and replace"]
  node_themes["Themes and layouts<br/>[ThemePicker.tsx]"]
  node_notes["Speaker notes<br/>[NotesPanel.tsx]"]
  node_show["Slideshow presenter<br/>[SlideShow.tsx]"]
end

subgraph group_files["PowerPoint file I/O"]
  node_pptx_client["PPTX client<br/>[client.ts]"]
  node_worker["PPTX worker<br/>[worker.ts]"]
  node_importer["PresentationML import<br/>[pptx-import.ts]"]
  node_exporter["PPTX export<br/>[pptx-export.ts]"]
  node_download["PDF and PNG output<br/>[download-slide.ts]"]
end

subgraph group_state["Local persistence"]
  node_autosave[("Autosave snapshot<br/>[autosave.ts]")]
  node_recent[("Recent files<br/>[recent-files.ts]")]
end

subgraph group_collab["Co-editing relay"]
  node_collab_ui["Collaboration provider<br/>[CollabProvider.tsx]"]
  node_bridge["Mutation bridge<br/>[bridge.ts]"]
  node_server["WebSocket relay<br/>[index.ts]"]
end

node_author(("Presenter"))
node_browser(("Browser user"))
node_storage_browser[("Browser storage")]
node_peer(("Other editor"))

node_author -->|"uses editor"| node_app
node_app -->|"hosts canvas"| node_engine
node_app -->|"dispatches"| node_commands
node_toolbar -->|"dispatches"| node_commands
node_slide_menu -->|"dispatches"| node_commands
node_element_menu -->|"dispatches"| node_commands
node_format -->|"reads selection"| node_selection
node_format -->|"dispatches"| node_commands
node_toolbar -->|"reads selection"| node_selection
node_commands -->|"reads selection"| node_selection
node_app -->|"imports and exports"| node_pptx_client
node_pptx_client -->|"sends requests"| node_worker
node_worker -->|"imports deck"| node_importer
node_worker -->|"exports deck"| node_exporter
node_app -->|"saves snapshot"| node_autosave
node_app -.->|"uses recent files"| node_recent
node_commands -->|"prints deck"| node_download
node_browser -->|"opens editor"| node_app
node_app -->|"mounts rail"| node_slides
node_app -->|"mounts find UI"| node_find
node_app -->|"mounts format UI"| node_format
node_app -->|"mounts menu"| node_element_menu
node_app -.->|"opens slideshow"| node_show
node_app -.->|"offers themes"| node_themes
node_app -.->|"offers notes"| node_notes
node_app -.->|"enables optionally"| node_collab_ui
node_collab_ui -->|"uses bridge"| node_bridge
node_bridge -.->|"broadcasts mutations"| node_server
node_peer -.->|"joins room"| node_server
node_server -.->|"keeps rooms in memory"| node_storage_browser

click node_app "https://github.com/casualoffice/slides/blob/main/apps/web/src/App.tsx"
click node_engine "https://github.com/casualoffice/slides/blob/main/apps/web/src/UniverSlide.tsx"
click node_commands "https://github.com/casualoffice/slides/blob/main/apps/web/src/univer/commands.ts"
click node_toolbar "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/Toolbar.tsx"
click node_format "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/FormatPane.tsx"
click node_selection "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/selection.ts"
click node_slides "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/SlideRail.tsx"
click node_slide_menu "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/SlideContextMenu.tsx"
click node_element_menu "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/ElementContextMenu.tsx"
click node_find "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/FindReplaceDialog.tsx"
click node_themes "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/ThemePicker.tsx"
click node_notes "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/NotesPanel.tsx"
click node_show "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/SlideShow.tsx"
click node_pptx_client "https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/client.ts"
click node_worker "https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/worker.ts"
click node_importer "https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/pptx-import.ts"
click node_exporter "https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/pptx-export.ts"
click node_download "https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/download-slide.ts"
click node_autosave "https://github.com/casualoffice/slides/blob/main/apps/web/src/storage/autosave.ts"
click node_recent "https://github.com/casualoffice/slides/blob/main/apps/web/src/storage/recent-files.ts"
click node_collab_ui "https://github.com/casualoffice/slides/blob/main/apps/web/src/collab/CollabProvider.tsx"
click node_bridge "https://github.com/casualoffice/slides/blob/main/apps/web/src/collab/bridge.ts"
click node_server "https://github.com/casualoffice/slides/blob/main/apps/server/src/index.ts"

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_app,node_engine,node_commands,node_toolbar,node_format,node_selection,node_slides,node_slide_menu,node_element_menu,node_find,node_themes,node_notes,node_show,node_browser toneBlue
class node_pptx_client,node_worker,node_importer,node_exporter,node_download,node_storage_browser toneAmber
class node_autosave,node_recent toneMint
class node_collab_ui,node_bridge,node_server toneRose
class node_author,node_peer toneIndigo
```

## Components

### Presentation editor

- [Editor shell](https://github.com/casualoffice/slides/blob/main/apps/web/src/App.tsx): `apps/web/src/App.tsx`
- [Univer canvas](https://github.com/casualoffice/slides/blob/main/apps/web/src/UniverSlide.tsx): `apps/web/src/UniverSlide.tsx`
- [Slide commands](https://github.com/casualoffice/slides/blob/main/apps/web/src/univer/commands.ts): `apps/web/src/univer/commands.ts`
- [Ribbon tools](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/Toolbar.tsx): `apps/web/src/shell/Toolbar.tsx`
- [Format pane](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/FormatPane.tsx): `apps/web/src/shell/FormatPane.tsx`
- [Selection bridge](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/selection.ts): `apps/web/src/shell/selection.ts`
- [Slide rail](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/SlideRail.tsx): `apps/web/src/shell/SlideRail.tsx`
- [Slide actions](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/SlideContextMenu.tsx): `apps/web/src/shell/SlideContextMenu.tsx`
- [Element actions](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/ElementContextMenu.tsx): `apps/web/src/shell/ElementContextMenu.tsx`
- [Find and replace](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/FindReplaceDialog.tsx): `apps/web/src/shell/FindReplaceDialog.tsx`
- [Themes and layouts](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/ThemePicker.tsx): `apps/web/src/shell/ThemePicker.tsx`
- [Speaker notes](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/NotesPanel.tsx): `apps/web/src/shell/NotesPanel.tsx`
- [Slideshow presenter](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/SlideShow.tsx): `apps/web/src/shell/SlideShow.tsx`

### PowerPoint file I/O

- [PPTX client](https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/client.ts): `apps/web/src/pptx/client.ts`
- [PPTX worker](https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/worker.ts): `apps/web/src/pptx/worker.ts`
- [PresentationML import](https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/pptx-import.ts): `apps/web/src/pptx/pptx-import.ts`
- [PPTX export](https://github.com/casualoffice/slides/blob/main/apps/web/src/pptx/pptx-export.ts): `apps/web/src/pptx/pptx-export.ts`
- [PDF and PNG output](https://github.com/casualoffice/slides/blob/main/apps/web/src/shell/download-slide.ts): `apps/web/src/shell/download-slide.ts`

### Local persistence

- [Autosave snapshot](https://github.com/casualoffice/slides/blob/main/apps/web/src/storage/autosave.ts): `apps/web/src/storage/autosave.ts`
- [Recent files](https://github.com/casualoffice/slides/blob/main/apps/web/src/storage/recent-files.ts): `apps/web/src/storage/recent-files.ts`

### Co-editing relay

- [Collaboration provider](https://github.com/casualoffice/slides/blob/main/apps/web/src/collab/CollabProvider.tsx): `apps/web/src/collab/CollabProvider.tsx`
- [Mutation bridge](https://github.com/casualoffice/slides/blob/main/apps/web/src/collab/bridge.ts): `apps/web/src/collab/bridge.ts`
- [WebSocket relay](https://github.com/casualoffice/slides/blob/main/apps/server/src/index.ts): `apps/server/src/index.ts`

### Other components

- **Presenter**
- **Browser user**
- **Browser storage**
- **Other editor**

## Connections

- Presenter → Editor shell: uses editor (evidence: `README.md`)
- Editor shell → Univer canvas: hosts canvas (evidence: `apps/web/src/App.tsx`)
- Editor shell → Slide commands: dispatches (evidence: `apps/web/src/App.tsx`)
- Ribbon tools → Slide commands: dispatches (evidence: `apps/web/src/shell/Toolbar.tsx`)
- Slide actions → Slide commands: dispatches (evidence: `apps/web/src/shell/SlideContextMenu.tsx`)
- Element actions → Slide commands: dispatches (evidence: `apps/web/src/shell/ElementContextMenu.tsx`)
- Format pane → Selection bridge: reads selection (evidence: `apps/web/src/shell/FormatPane.tsx`)
- Format pane → Slide commands: dispatches (evidence: `apps/web/src/shell/FormatPane.tsx`)
- Ribbon tools → Selection bridge: reads selection (evidence: `apps/web/src/shell/Toolbar.tsx`)
- Slide commands → Selection bridge: reads selection (evidence: `apps/web/src/univer/commands.ts`)
- Editor shell → PPTX client: imports and exports (evidence: `apps/web/src/App.tsx`)
- PPTX client → PPTX worker: sends requests (evidence: `apps/web/src/pptx/client.ts`)
- PPTX worker → PresentationML import: imports deck (evidence: `apps/web/src/pptx/worker.ts`)
- PPTX worker → PPTX export: exports deck (evidence: `apps/web/src/pptx/worker.ts`)
- Editor shell → Autosave snapshot: saves snapshot (evidence: `apps/web/src/App.tsx`)
- Editor shell → Recent files: uses recent files (evidence: `README.md`)
- Slide commands → PDF and PNG output: prints deck (evidence: `apps/web/src/univer/commands.ts`)
- Browser user → Editor shell: opens editor
- Editor shell → Slide rail: mounts rail (evidence: `apps/web/src/main.tsx`)
- Editor shell → Find and replace: mounts find UI (evidence: `apps/web/src/main.tsx`)
- Editor shell → Format pane: mounts format UI (evidence: `apps/web/src/main.tsx`)
- Editor shell → Element actions: mounts menu (evidence: `apps/web/src/main.tsx`)
- Editor shell → Slideshow presenter: opens slideshow (evidence: `README.md`)
- Editor shell → Themes and layouts: offers themes (evidence: `README.md`)
- Editor shell → Speaker notes: offers notes (evidence: `README.md`)
- Editor shell → Collaboration provider: enables optionally (evidence: `README.md`)
- Collaboration provider → Mutation bridge: uses bridge (evidence: `apps/web/src/collab/CollabProvider.tsx`)
- Mutation bridge → WebSocket relay: broadcasts mutations (evidence: `README.md`)
- Other editor → WebSocket relay: joins room (evidence: `README.md`)
- WebSocket relay → Browser storage: keeps rooms in memory (evidence: `README.md`)
