Back to Presentation Editor (Codex)

README

Web PowerPoint-Style Editor & Viewer Spec

1. Overview

  • Browser-based editor and viewer built with React, TailwindCSS, and shadcn/ui.
  • Desktop-only MVP focused on smooth drag/resize interactions (60fps target) and instant loading for up to 50 slides.
  • Rendering is DOM-based: slide canvas is a positioned container with absolutely positioned elements.
  • Light/dark mode supported through Tailwind theme tokens.

2. Internal JSON Format (authoritative data model)

json
{
  "slides": [
    {
      "id": "uuid-1",
      "background": { "color": "#ffffff" },
      "elements": [
        {
          "id": "uuid-2",
          "type": "text",
          "x": 100,
          "y": 150,
          "width": 300,
          "height": 80,
          "rotation": 0,
          "text": "Hello world",
          "style": {
            "fontSize": 24,
            "color": "#000000",
            "fontWeight": "normal",
            "textAlign": "left"
          }
        }
      ]
    }
  ]
}

  • Schema applies to every persisted/exported deck. Images store base64 payloads in an element-specific src field; rectangles store fill/outline colors; circles optional but use same schema with type: "shape" + shape: "circle".
  • All dimensions are numbers in canvas pixels; rotation in degrees. Slide background currently limited to solid colors for MVP but property is extensible.

3. Architecture

State management
  • Zustand store with Immer-backed reducers for predictability and TDD friendliness.
  • Store slices: slides, currentSlideIndex, selectedElementId, history (undo/redo stacks), and ui (viewer/editor mode).
  • Pure reducer helpers (slideReducer, elementReducer, historyReducer) exported for unit testing; UI dispatches serialized actions.
  • Undo/redo captured by pushing snapshots of JSON to stacks; mutations always run through reducers so history stays in sync.
Persistence
  • LocalStorage autosave keyed by powerpoint-codex-deck. Debounced save (500ms) after reducer commits.
  • Export button triggers JSON download of current deck. Import loads JSON and validates structure before replacing store.
Rendering layer
  • SlideCanvas renders active slide. Elements map to components:
- TextElement → content editable div with Tailwind styling. - ImageElementimg tag with max width enforced (1920px) before encoding to base64. - ShapeElementdiv styled with background/border; optional border-radius for circles.
  • react-rnd (or lightweight wrapper) handles drag and resize with transform handles; on interaction end dispatches move/resize actions. Selected element shows blue outline and handles.
Viewer Mode
  • Read-only rendering of the same JSON structure.
  • Keyboard navigation (ArrowLeft/ArrowRight) changes slide index; F toggles full-screen via Fullscreen API.
  • Toolbar button switches between editor and viewer mode but shares store to ensure fidelity.

4. UI Structure

  • Top Bar: Undo, Redo, Add Text, Add Image, Add Rectangle/Circle, Save/Export, Viewer toggle.
  • Left Sidebar: Slide thumbnails rendered from JSON; clicking selects slide. Drag-and-drop (react-beautiful-dnd) supports reorder. Add-slide button at bottom.
  • Main Canvas: 16:9 artboard showing current slide with selection halo. Dragging updates element position; handles adjust width/height.
  • Right Panel: Contextual controls.
- Text: font size, color, weight, alignment. - Shape/Image: fill color, stroke color/width. - Slide: background color picker. - Optional numeric inputs for x/y/width/height for precise control (Phase 1 nice-to-have).

5. Supported Actions (Phase 1)

  • Add/delete/reorder slides.
  • Add text/image/rectangle (circle optional) elements.
  • Select one element at a time.
  • Drag to move; resize via handles; rotate reserved for Phase 2.
  • Edit text inline; formatting controls update style.
  • Slide background color picker.
  • Undo/redo across slide & element operations.

6. Image Handling

  • Local uploads only; convert to base64 (data:image/...) and store in JSON src.
  • Validate and cap dimensions to 1920px width (height scaled) before encoding.
  • Reject files over 5 MB to keep deck lightweight.

7. Testing Strategy (TDD focus)

  • Reducer unit tests (Vitest) covering:
- Slide operations: add, delete, reorder, background color changes. - Element operations: create, move, resize, update text/style. - Undo/redo stack behavior (push/pop, compound operations).
  • Persistence tests: serialize to JSON, load from JSON, validation errors for malformed decks.
  • Component tests (React Testing Library):
- Viewer mode renders slide elements from JSON and responds to keyboard navigation. - Thumbnail list renders slides and reflects active slide state. - Drag behavior smoke tests mocking react-rnd callbacks to ensure position dispatch occurs (no deep DOM drag tests required).

8. Non-Functional Requirements

  • Optimistic UI with requestAnimationFrame-driven drag/resize updates to maintain 60fps.
  • Debounced store persistence to avoid blocking interactions.
  • Tailwind dark-mode classes ensure legibility in both themes.
  • Designed for desktop breakpoints; mobile editing deferred.

9. Roadmap

  • Phase 1 (MVP): JSON model, slide CRUD, text/image/rectangle elements, drag/resize, undo/redo, viewer mode, local save/export.
  • Phase 2: Snap-to-grid guides, element grouping, theme presets, templates, circle shapes if deferred from MVP.

© 2026 Jonathan Leahy · v1.0.9