No description
  • TypeScript 96.7%
  • CSS 1.6%
  • JavaScript 1.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Morten Olsen 7d47c3d76e
All checks were successful
ci/woodpecker/pr/compliance Pipeline was successful
ci/woodpecker/pr/quality Pipeline was successful
ci/woodpecker/push/compliance Pipeline was successful
ci/woodpecker/push/quality Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
the slide viewport: one composition everywhere, the lamp pulls back
ADR 0002 implemented (draft -> accepted). Every slide is composed
against one fixed logical sheet (1024x800, one tunable constant) and
uniformly projected into whatever shows it — transparency physics: the
wobble scales with the ink, and rough strokes now regenerate only
against the stable logical size, never on window resize. Stage,
presenter tab, and replay render the identical sheet.

When content outgrows the sheet the lamp pulls back: a discrete ~0.85
ladder grows the logical page until the content fits. Overflow is
measured on the content box plus data-slide-overflow probes (the
canvas's centered block column clips its own spill — the first
screenshot pass showed clipped bullets and no pull-back), and a
subtree observer remeasures on changes that land without a parent
render — the async elk layout, found when the presenter tab measured
pre-layout and stuck at zoom 1.

The presenter tab also surfaced a real bug: a cloned stylesheet <link>
never fetches in the about:blank tab under production builds (dev only
worked because Vite injects inline styles) — the window now mirrors
styles by serializing the opener's parsed CSSOM, verified against the
prod build (ink-resolved strokes, Shantell in the popup).
2026-09-10 11:46:23 +02:00
.codex update 2026-09-02 21:33:05 +02:00
.impeccable add CLI 2026-09-03 12:19:06 +02:00
.woodpecker add CLI 2026-09-03 12:19:06 +02:00
apps the slide viewport: one composition everywhere, the lamp pulls back 2026-09-10 11:46:23 +02:00
docs the slide viewport: one composition everywhere, the lamp pulls back 2026-09-10 11:46:23 +02:00
packages the prompter: a second loop feeding the presenter their next line 2026-09-10 00:43:08 +02:00
skills/lazysketch add CLI 2026-09-03 12:19:06 +02:00
.gitignore prompter voice hardening: every token must be sayable into the mic 2026-09-10 09:54:32 +02:00
.prettierignore add CLI 2026-09-03 12:19:06 +02:00
.prettierrc init 2026-09-02 19:34:46 +02:00
CLAUDE.md the prompter: a second loop feeding the presenter their next line 2026-09-10 00:43:08 +02:00
DESIGN.md the slide viewport: one composition everywhere, the lamp pulls back 2026-09-10 11:46:23 +02:00
eslint.config.mjs add CLI 2026-09-03 12:19:06 +02:00
mise.toml init 2026-09-02 19:34:46 +02:00
package.json add CLI 2026-09-03 12:19:06 +02:00
pnpm-lock.yaml playwright e2e harness: tests own the browser over the real bridge 2026-09-10 00:27:50 +02:00
pnpm-workspace.yaml add CLI 2026-09-03 12:19:06 +02:00
PRODUCT.md update 2026-09-02 21:33:05 +02:00
README.md replay renders the prompter console; readme leads with the lost moment 2026-09-10 09:02:08 +02:00
renovate.json update 2026-09-02 21:33:05 +02:00
Taskfile.yml prompter eval harness; first live tuning pass lands 8/8 on Haiku 2026-09-10 07:42:57 +02:00
tsconfig.json playwright e2e harness: tests own the browser over the real bridge 2026-09-10 00:27:50 +02:00
vitest.config.ts add CLI 2026-09-03 12:19:06 +02:00

lazysketch

Slides sketched live off your voice. You talk; a small, fast LLM listens to your live transcript and draws the deck while you speak — hand-sketched diagrams, bullets, code blocks, the occasional rubber-duck stamp — on lamp-lit paper, like an overhead projector that grew an opinion.

Try it: https://lazysketch.mortenolsen.pro

A slide titled "This slide is drawing itself": a hand-sketched pipeline diagram (Presenter → Mic → Whisper → Artist (LLM) → This Slide, with a dashed "planned" Audience), a big highlighted "~3 seconds" stat, and a rubber duck stamp

The agent drew this one itself, live, off a scripted run of exactly the talk you'd expect — duck requested by voice.

Fair warning: this is a quirky side project built for the wow effect of a deck drawing itself mid-talk. If you want AI to help you make actual presentations, there is real software for that. If you want to say "watch this" and then just… talk — welcome.

What you need

  • A Chromium-ish browser (Chrome/Edge/Firefox). Speech models (Whisper for ears, Kokoro for a voice) run on-device in workers — a laptop with WebGPU makes them happy.
  • An OpenAI-compatible endpoint of your own (OpenAI, Groq, Ollama, a LiteLLM proxy, …). Nothing is baked in; your key never leaves the browser except to the endpoint you name. A Haiku-class model is the sweet spot — small and fast beats big and slow here.

Everything is client-side: no backend, no account, your presentations live in your browser (IndexedDB), with export/import if you want to move them.

Quick start

  1. Open the app → Settings → set base URL + model (+ key), hit Save & preload models.
  2. Start a fresh sheet, paste in a talk outline as a cue file — it helps the model far more than you'd expect.
  3. Go live, open the mic, and start talking. The deck follows. When you stop, the session is recorded — replay it, scrub it, or resume for Q&A.

No mic handy? Rehearse from a script feeds prepared text through the exact same pipeline, at reading pace or as fast as the agent can draw.

On stage for real

Everyone who presents knows the moment: you're tired, under-rehearsed, you've delivered your points out of order, and the script in front of you has stopped being true. Reading it back doesn't help — what you need is someone who heard what you actually said and can tell you where to go from here. That's the prompter.

  • Present opens the slides alone in a clean tab — move it to the projector, double-click for fullscreen. Your original tab keeps the tray, transcript, and gauges: that's your console now.
  • Write the talk in the Script section on the desk — full prose or just your talking points — then flip on the Prompter next to Go live. A second loop listens along and keeps the next thing to say written large on your console, streaming in as you speak. On script, it's your own words. Off script, it's a live rewrite from where you actually are: points you've already made are dropped, the ones you haven't are lined up in an order that repairs the talk.
  • So when you're lost: take a breath. The line is already there. Say it, and you're back.
  • Audience question? It proposes a short answer. Wandered into a story? It holds the bridge home. Timing notes in the script are read, not parsed — it reasons about your pace against the clock.
  • The prompter can run on a cheaper, faster model than the artist (Settings), Rehearse runs with it on so you can audition it before trusting it with a real room — and Replay shows its console alongside the talk afterwards, so you can judge every line it offered.

The CLI (optional, unpublished)

There's a lazysketch CLI so a coding agent (or you) can prime presentations from the terminal: author the sheet and cue files as plain files, sync them into the browser, run a scripted test session there — using the browser's LLM settings, credentials never touch the CLI — and get an eval report of what the agent drew.

It isn't on a registry yet, so it's clone-and-link:

git clone https://code.olsen.cloud/incubator/lazysketch.git && cd lazysketch
mise install     # Node 24 + task (or bring your own)
task install && task build
cd apps/cli && pnpm link --global
lazysketch --help

Then in the app: Settings → CLI access → Enable, run the pairing command it shows you once, and you're connected (lazysketch status). The loop is init/pull → edit files → push → run --script talk.txt → report → open --replay. Agents can learn it from the skill in skills/lazysketch. (Safari blocks the localhost bridge; use Chrome or Firefox for this part.)

Honest small print

  • Latency is the whole game: with a good endpoint the deck trails you by a few seconds (there's a lag gauge — grease pencil, of course). With a slow model it trails you by an awkward silence.
  • The agent sometimes draws the wrong thing, rewrites a block five times, or celebrates prematurely with confetti. This is considered part of the charm.
  • The prompter follows meaning, not words — in testing it rode out a cat-on-the-keyboard digression without flinching — but it proposes, you decide. It's a prompter, not a co-author. Occasionally it re-offers the line you're mid-way through saying; it catches up on your next breath.
  • Curious how it works? docs/design.md covers the transcript pipeline, the event-sourced deck, and the CLI bridge; DESIGN.md is the paper-world design system.