Skip to content
FromArkZooPublic

About

React + TypeScript slide/presentation builder with canvas editing and dynamic backgrounds

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

BeanNote

A canvas-based slide / presentation builder in React + TypeScript — Fabric.js editing, animated dynamic backgrounds, rich text via TipTap, PDF export. No backend.

BeanNote editor

This is a from-scratch attempt at a Keynote-style editor that runs entirely in the browser. The point is to learn what a polished slide tool actually requires once you stop hand-waving — selection state, undo / redo across heterogeneous object types, animated backgrounds that don't murder the framerate, sortable thumbnails, presenter mode, and a PDF exporter that doesn't lose fonts.

What works

  • Canvas editing — Fabric.js-backed slide canvas with text, shapes, images, charts, tables; drag, resize, rotate, snap, multi-select
  • Rich text — TipTap editor with font family, colour, alignment, underline, lists, KaTeX math
  • Dynamic backgrounds — 7-mode background system (crossed waves, bold ribbon, ridge layers, faceted, smooth wash, …) with 18 presets and per-slide configuration
  • Animation — per-object enter / exit animations driven by Framer Motion + GSAP, sequenced via the Animate inspector
  • Slide management — sortable thumbnails (DnD Kit), templates, layout chooser, theme chooser
  • Presenter mode — full-screen playback with notes view, rehearsal timer
  • PDF export — jsPDF with embedded fonts, one slide per page
  • Document state — Immer-based store with undo / redo across all object mutations

What's missing

  • No persistence layer — everything lives in memory; reload loses the deck (intentional during exploration; would slot a localStorage or file-handle backend in cleanly)
  • No collaboration / real-time sync
  • No image-cropping UI; images are placed at native size
  • Animation timing is per-slide, not synced across the deck

Architecture

src/
├── shell/                  # Top-level UI shell
│   ├── AppShell.tsx              # Layout: toolbar / sidebar / canvas / inspector
│   ├── Toolbar/                  # Top toolbar (Add Slide, Play, Insert, Share)
│   ├── Sidebar/                  # Slide thumbnails + drag-to-reorder
│   ├── Inspector/                # Format / Animate / Layers / Document tabs
│   ├── ThemeChooser/             # Palette + font picker
│   ├── LayoutChooser/            # Per-slide layout templates
│   └── TemplateBuilder/          # Multi-slide template export
├── canvas/                 # Slide editing surface
│   ├── CanvasManager.ts          # Fabric.js wrapper, object lifecycle
│   ├── SlideCanvas.tsx           # React mount point with zoom + pan
│   ├── interactions/             # Selection, drag, resize, snap
│   ├── objects/                  # TextBox, Image, Shape, Chart, Table object classes
│   ├── shapes/                   # Shape library (rounded rect, arrow, callout, …)
│   └── text/                     # TipTap integration on canvas
├── animations/             # Object + background animation
│   └── backgrounds/              # Background renderer + 5 named modes + presets
├── slides/                 # Slide-level features
│   ├── content/                  # Slide content rendering
│   ├── management/               # CRUD, duplicate, reorder
│   ├── presenter/                # Full-screen playback
│   └── rehearsal/                # Rehearsal timer + speaker notes
├── store/                  # Immer-backed document state, undo / redo
├── themes/                 # Theme tokens + palette presets
└── types/

Key decisions

  • Fabric.js for the canvas, not raw <canvas>. Hit-testing, selection handles, and object hierarchy are the unsexy work of any editor; reaching for Fabric let me focus on what's interesting (animation, backgrounds, document model) instead of reimplementing transform handles for the third time.
  • Immer + a single store, no Redux. Slide-deck state is a tree, not a flat list. Immer's draft mutation lets reducers read like ordinary code while still giving structural sharing for cheap undo / redo. A handful of produce(...) calls beat a Redux ecosystem.
  • Background renderer is its own subsystem. Each background mode is a small (ctx, t, params) => void renderer driving a requestAnimationFrame loop on an offscreen canvas, composited under the slide. Adding a new mode is one file in new-renderers/. Presets are pure data.
  • TipTap on Fabric. Text objects host a TipTap editor inside a positioned <div> overlay synced to the Fabric object. Rich editing without giving up canvas-based layout.

Running it

npm install
npm run dev

Open the printed local URL. The first slide is editable on load.

Tech stack

React 18 · TypeScript · Vite · Fabric.js · TipTap · Framer Motion · GSAP · DnD Kit · Immer · jsPDF · KaTeX

About

React + TypeScript slide/presentation builder with canvas editing and dynamic backgrounds

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages