# Technical Design Document: Random Slides
## 1. Overview
"Random Slides" is a lightweight, browser-based slideshow application that allows users to create, edit, and play text-based slides using Markdown. The application operates entirely in the browser (Single Page Application) with no backend and requires no build steps. Data is persisted using the browser's `localStorage`.
## 2. Technical Constraints & Requirements
- **No Build Step**: Must use native ES Modules (ESM) and libraries available via CDN (UMD/ESM).
- **Pure Frontend**: No server-side logic.
- **Persistence**: `localStorage`.
- **Framework**: Preact (via `htm` for JSX-like syntax without transpilation).
- **Format**: Markdown for slide content.
## 3. Architecture
### 3.1 Tech Stack
- **Core Library**: `Preact` (imported via `esm.sh` or `unpkg`).
- **Templating**: `htm` (Hyperscript Tagged Markup) to write component layouts similar to JSX.
- **Markdown Renderer**: `marked` (via CDN).
- **Styling**: Standard CSS3.
- **State Management**: Preact standard `useState`, `useEffect`.
### 3.2 File Structure
Since there is no bundler, we will use standard ES modules.
```
/
├── index.html # Entry point, loads styles and scripts
├── style.css # Global styles
└── src/
├── main.js # App entry and mount
├── App.js # Main container and state manager
├── components/
│ ├── Editor.js # Edit mode view
│ └── Player.js # Play mode view
└── utils/
├── storage.js # LocalStorage wrapper
├── array.js # Shuffle logic
└── presets.js # Pre-defined slideshow generators
```
## 4. Data Model
### 4.1 Slide Object
```javascript
{
id: string, // Unique UUID/ID for React keys and drag-drop tracking
content: string // Markdown text content
}
```
### 4.2 Application State
The `App` component will hold the central state:
- `slides`: `Array<SlideObject>` - The source of truth for all slides.
- `fontSize`: `number` - Base font size in pixels (default: 256).
- `mode`: `'edit' | 'play'` - Current application mode.
- `playDeck`: `Array<SlideObject>` - The subset/ordered list of slides currently being played (handling normal vs. shuffled).
- `currentIndex`: `number` - Current slide index in the `playDeck`.
## 5. Component Design
### 5.1 `App.js` (Container)
- **Responsibilities**:
- Initialize state from `localStorage` (slides and settings).
- Persist changes to `slides` and `settings` to `localStorage`.
- Handle transitions between 'edit' and 'play' modes.
- Handle "Play" vs "Shuffle Play" logic (generating the `playDeck`).
- Manage `fontSize` state.
### 5.2 `Editor.js`
- **Props**:
- `slides`: Array of slides.
- `fontSize`: Current font size setting.
- `onUpdate`: Function to update the slides array.
- `onUpdateFontSize`: Function to update the font size.
- `onPlay`: Function to start normal playback.
- `onShufflePlay`: Function to start shuffled playback.
- **Features**:
- **Toolbar**: Organized into two rows.
- Row 1: Title, Clear All button, Play buttons.
- Row 2: Font Size input, Presets dropdown (A-Z, 1-20).
- **Presets**: Load pre-defined slide decks (replacing current slides).
- **Clear All**: Reset slideshow to a single empty slide.
- **Slide List**: Renders a list of textareas.
- **Drag and Drop**: Implemented using HTML5 Drag and Drop API.
- **Actions**: Add Slide, Delete Slide.
### 5.3 `Player.js`
- **Props**:
- `deck`: Array of slides to play.
- `fontSize`: Base font size to apply.
- `onExit`: Function to return to edit mode.
- **State**:
- `index`: Internal tracking of current slide (initialized to 0).
- **Features**:
- Renders current slide using `marked`.
- **Style**:
- Apply `fontSize` (px).
- Content centered horizontally (text-align) and vertically (flexbox).
- **Event Listeners**:
- `click` / `keydown` (any key except ESC): Advance slide.
- `keydown` (ESC): Trigger `onExit`.
- **Rendering**:
- Centered, large text.
- HTML rendered from Markdown (unsanitized as per requirements).
## 6. Key Workflows
### 6.1 Initialization
1. App loads.
2. `storage.js` reads key `random_slides_data`.
3. If null, return default `[{ id: uuid(), content: '' }]`.
4. App mounts in `mode: 'edit'`.
### 6.2 Editing
1. User types in textarea.
2. `onChange` triggers update to specific slide in `slides` array.
3. `useEffect` in `App` observes `slides` and saves to `localStorage`.
### 6.3 Drag and Drop Reordering
1. User drags a slide handle.
2. `dragstart`: Capture index.
3. `drop`: Calculate new index, splice array, update state.
### 6.4 Play Mode
1. User clicks "Play".
- `playDeck` = `slides`.
- `mode` = `'play'`.
2. User clicks "Shuffle".
- `playDeck` = `shuffle(slides)`.
- `mode` = `'play'`.
### 6.5 Navigation (Play Mode)
1. Render `playDeck[currentIndex]`.
2. Input event (Click/Key):
- `currentIndex++`.
- If `currentIndex >= playDeck.length`, show "End of Slideshow" or loop? (Default: Loop or Stop. Prd implies "advance", will implement loop or stop at last slide. Design decision: **Loop** for continuous flow, or **Stop** at end. Let's **Stop** at the end to avoid confusion).
3. ESC Key:
- Call `onExit()`.
- Reset `mode` to `'edit'`.
## 7. UI/UX Plan
- **Edit Mode**:
- Clean vertical list of cards.
- Each card has a handle (for dragging), textarea, and delete button.
- Floating or sticky header/footer for "Add Slide", "Play", "Shuffle".
- **Play Mode**:
- Full screen overlay or full viewport.
- Minimalist.
- Content vertically and horizontally centered.
- High contrast text.
## 8. Third-Party Libraries (CDN)
- **Preact**: `https://esm.sh/preact`
- **Preact Hooks**: `https://esm.sh/preact/hooks`
- **htm**: `https://esm.sh/htm`
- **marked**: `https://esm.sh/marked`
- **uuid**: `https://esm.sh/uuid` (for reliable ID generation).