Feedback from hands-on testing
After building a deck end-to-end and inspecting the codebase, here are four issues worth addressing — ranging from server lifecycle bugs to fundamental workflow gaps.
1. start_review accumulates servers without closing previous ones
Each start_review call spawns a new Fastify server on an ephemeral port (port 0) but never shuts down the previous one. If the user does not click Done, the old server lingers for 24 hours (shutdown.ts hardCap). Multiple iteration rounds accumulate orphan servers.
Relevant code: mcp/tools/review.ts:34-51, runtime/server/shutdown.ts:12-48
Short-term fix: On start_review, close any existing server in the running Map that shares the same deckDir.
Long-term proposal: Introduce WebSocket to maintain a single persistent port per project. After build_deck, push a reload signal over WS so the browser refreshes automatically — no new URL needed. The annotation session can reset on the same connection. start_review would only start a server on the first call; subsequent iterations reuse the same port.
2. Rendering pipeline is rigid — limited extensibility
The entire pipeline is hardcoded: content.md → marked.parse() → string-template HTML → reveal.js. There is only one engine (reveal.js), the HTML template is string concatenation (not replaceable), and the 5 CSS themes only swap colors/fonts — the structure is identical. No support for marked plugins (Mermaid, KaTeX), no custom CSS or HTML template overrides, no pluggable engine architecture.
Relevant code: runtime/engines/reveal.ts:157-302 (the entire buildDeck function), runtime/engines/themes/*.css
Possible improvements:
- Support marked plugin system (mermaid-js, KaTeX, etc.)
- Allow user-provided custom CSS or HTML template overrides
- Consider a pluggable engine architecture beyond reveal.js
3. Annotation pins drift + accidental popover triggers on slide navigation
Pin drift: pin.ts:45-46 uses absolute pixel positioning (scrollX + rect.left), but reveal.js scales slides via CSS transform: scale(). getBoundingClientRect() returns viewport coordinates that do not match the pin container's coordinate system. Pins drift on resize, zoom, and during transitions. Fix: attach pins inside the corresponding <section> with relative positioning.
Accidental triggers: annotation-mode.ts:33-34 listens for all clicks at the document capture phase without excluding reveal.js navigation controls (arrows, progress bar) or applying any mis-tap protection (debounce, minimum drag distance, etc.). Switching slides in annotation mode frequently opens the popover unintentionally. Worse, popover.ts has no light dismiss — clicking outside the popover does nothing, forcing the user to manually hit Cancel or Esc after every accidental trigger.
Relevant code: runtime/overlay/pin.ts:31-52, runtime/overlay/annotation-mode.ts:19-34, runtime/overlay/popover.ts:11-80
4. First-pass content quality is weak — missing a planning phase
Even with the fun style selected, the agent's first draft tends to produce content with unfocused key points and uneven information density. Some slides are overloaded, others feel empty. The overall narrative reads like fragmented excerpts rather than a coherent presentation.
Root cause: SKILL.md only provides tonal guidance per style ("conversational tone, friendly framing, light commentary") with no structural guidance:
- No requirement to extract core arguments / narrative arc before writing slides
- No constraint on per-slide information density (e.g., one key point per slide)
- No distinction between summarization vs. original storytelling strategies
- Style descriptions affect tone, not logical structure
Proposed improvement — introduce a Planning phase:
The current workflow jumps straight to Draft → Refine. It should be Plan → Draft → Refine:
- Plan — Agent collaborates with the user to align on audience, goals, and core arguments. Together they define the narrative arc (problem → evidence → conclusion) and per-slide key points, producing an outline.
- Draft — Based on the outline, the agent collects/organizes information and generates the initial
content.md.
- Refine — The annotation system kicks in for visual and copy polish iterations.
The annotation system is great for refinement, but it should not bear the burden of aligning the narrative — that belongs in the planning phase. SKILL.md workflow should change from init_deck → write content.md to init_deck → plan storyline with user → write content.md.
Feedback from hands-on testing
After building a deck end-to-end and inspecting the codebase, here are four issues worth addressing — ranging from server lifecycle bugs to fundamental workflow gaps.
1.
start_reviewaccumulates servers without closing previous onesEach
start_reviewcall spawns a new Fastify server on an ephemeral port (port 0) but never shuts down the previous one. If the user does not click Done, the old server lingers for 24 hours (shutdown.tshardCap). Multiple iteration rounds accumulate orphan servers.Relevant code:
mcp/tools/review.ts:34-51,runtime/server/shutdown.ts:12-48Short-term fix: On
start_review, close any existing server in therunningMap that shares the samedeckDir.Long-term proposal: Introduce WebSocket to maintain a single persistent port per project. After
build_deck, push a reload signal over WS so the browser refreshes automatically — no new URL needed. The annotation session can reset on the same connection.start_reviewwould only start a server on the first call; subsequent iterations reuse the same port.2. Rendering pipeline is rigid — limited extensibility
The entire pipeline is hardcoded:
content.md → marked.parse() → string-template HTML → reveal.js. There is only one engine (reveal.js), the HTML template is string concatenation (not replaceable), and the 5 CSS themes only swap colors/fonts — the structure is identical. No support for marked plugins (Mermaid, KaTeX), no custom CSS or HTML template overrides, no pluggable engine architecture.Relevant code:
runtime/engines/reveal.ts:157-302(the entirebuildDeckfunction),runtime/engines/themes/*.cssPossible improvements:
3. Annotation pins drift + accidental popover triggers on slide navigation
Pin drift:
pin.ts:45-46uses absolute pixel positioning (scrollX + rect.left), but reveal.js scales slides via CSStransform: scale().getBoundingClientRect()returns viewport coordinates that do not match the pin container's coordinate system. Pins drift on resize, zoom, and during transitions. Fix: attach pins inside the corresponding<section>with relative positioning.Accidental triggers:
annotation-mode.ts:33-34listens for all clicks at the document capture phase without excluding reveal.js navigation controls (arrows, progress bar) or applying any mis-tap protection (debounce, minimum drag distance, etc.). Switching slides in annotation mode frequently opens the popover unintentionally. Worse,popover.tshas no light dismiss — clicking outside the popover does nothing, forcing the user to manually hit Cancel or Esc after every accidental trigger.Relevant code:
runtime/overlay/pin.ts:31-52,runtime/overlay/annotation-mode.ts:19-34,runtime/overlay/popover.ts:11-804. First-pass content quality is weak — missing a planning phase
Even with the
funstyle selected, the agent's first draft tends to produce content with unfocused key points and uneven information density. Some slides are overloaded, others feel empty. The overall narrative reads like fragmented excerpts rather than a coherent presentation.Root cause: SKILL.md only provides tonal guidance per style ("conversational tone, friendly framing, light commentary") with no structural guidance:
Proposed improvement — introduce a Planning phase:
The current workflow jumps straight to Draft → Refine. It should be Plan → Draft → Refine:
content.md.The annotation system is great for refinement, but it should not bear the burden of aligning the narrative — that belongs in the planning phase. SKILL.md workflow should change from
init_deck → write content.mdtoinit_deck → plan storyline with user → write content.md.