Vibecode Prezi
track this build4 phases, 12 steps, beginner friendly0%The visible zooming presentations loop is buildable, but a credible replacement needs more than the first screen. Prezi earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope.
You are building a lean indie version of Prezi. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Prezi · indie build A zooming canvas presentation tool where the interesting engineering is a smooth camera path across a large canvas and the governing constraint is that the motion must be optional without the presentation becoming incoherent. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A single large scene with content placed spatially | the spatial arrangement is the structure, not decoration | | Camera | Named viewpoints with an ordered path between them | a path of viewpoints is editable in a way a recorded motion is not | | Motion | Interpolation with capped rate and rotation, honouring reduced motion | the cap is what makes the format tolerable | | Rendering | Vector where possible so zooming stays sharp | zooming into a raster image is the format's most visible failure | | Runtime | TypeScript with local documents | a presentation is a document and must work without a network | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the editor and the presenter. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Your motion caps, decided before authoring** · free - Why: They are constants in the transition path, and deciding them after building a presentation means fitting them to the presentation rather than to the audience. - Get it: Set a maximum zoom rate and rotation, erring conservative, and write down the reasoning. - Verify: Both are written down and appear as constants in the motion module - [ ] **A second display and a different aspect ratio** · free if you have one - Why: Presenter view and aspect ratio cropping are both only testable with a real second screen, and cropping is discovered in front of an audience otherwise. - Get it: Any second display, ideally one whose aspect ratio differs from your authoring machine. - Verify: The presentation runs across two displays and previews correctly at another aspect ratio - [ ] **Someone to watch it who will tell you honestly** · free - Why: Motion tolerance varies enormously and the author is the worst judge, since they know where the camera is going next. - Get it: Show a full run to two or three people and ask specifically about discomfort rather than about the content. - Verify: At least three people have watched a full run and been asked directly - [ ] **A real presentation with a real argument** · free - Why: The reduced-motion and static export checks are about whether the argument survives, and a demonstration deck of shapes has no argument to lose. - Get it: Use a talk you have actually given or will give. - Verify: A presentation exists with at least fifteen viewpoints and a conclusion ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. - presentation and enterprise controls - production codecs, rendering speed, and media templates - multiplayer cursors and comments - large template libraries - high-fidelity import and export If one of those is essential to you, that is the reason to keep paying for Prezi, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Prezi The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a zooming canvas presentation that does not make the audience feel ill to replace Prezi. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero The distinguishing feature of this format is also its main risk. Continuous zooming and rotating motion triggers nausea and dizziness in a meaningful share of any audience, and the people affected cannot leave a meeting to escape it. Vestibular disorders make this considerably worse, and a presentation is not something a person opts into the way a website is. So the build treats motion as an accessibility question rather than a style one. It honours the reduced-motion preference by replacing zooming transitions with cuts, caps rotation and zoom rate as constants rather than settings, and makes the reduced-motion version a first class output that is checked rather than a degraded fallback. It also means the content has to work without the motion. If the argument only makes sense because of the zoom path, it does not survive the export, the reduced-motion viewer or someone reading the slides afterwards, which is most of a presentation's life. ### Stack (fixed, do not substitute) - Canvas: A single large scene with content placed spatially · the spatial arrangement is the structure, not decoration - Camera: Named viewpoints with an ordered path between them · a path of viewpoints is editable in a way a recorded motion is not - Motion: Interpolation with capped rate and rotation, honouring reduced motion · the cap is what makes the format tolerable - Rendering: Vector where possible so zooming stays sharp · zooming into a raster image is the format's most visible failure - Runtime: TypeScript with local documents · a presentation is a document and must work without a network ### Data model (create this before Phase 1) - presentations(id, title, canvas_width, canvas_height, reduced_motion_checked) - elements(id, presentation_id, kind, x, y, width, height, rotation, z, content_json, is_vector) - viewpoints(id, presentation_id, ordinal, x, y, width, height, rotation, dwell_note) - transitions(from_viewpoint_id, to_viewpoint_id, duration_ms, easing, computed_rate, exceeds_cap) - speaker_notes(viewpoint_id, body) - exports(id, presentation_id, kind, path, motion_mode, at) · kind is document, video or static deck - A transition stores its computed motion rate, so a path that would exceed the cap is detectable at authoring time rather than during a presentation. ### Phase 1 · A canvas and a path across it Build: A large canvas with elements placed spatially, and an ordered list of named viewpoints. Navigate forward and backward. Keep the path editable as a list rather than as recorded camera motion. Trap: Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. Done when: Viewpoints are stored as a reorderable list and the path is derived from them. Reordering does not require redoing any motion. Backward navigation works and returns exactly to the previous framing. A viewpoint can be updated to the current view without affecting the others. Do not build yet: No motion caps, reduced motion or export. ### Phase 2 · Motion with a ceiling Build: Interpolate between viewpoints with capped zoom rate and rotation. Compute each transition's rate at authoring time and flag any that would exceed the cap. Make the caps constants rather than settings. Trap: Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. Done when: Transitions cannot exceed the capped zoom rate or rotation, verified by attempting to author one. A transition that would exceed the cap is flagged at authoring with the reason. The caps are constants and are not adjustable at runtime. A long transition across the canvas remains smooth rather than accelerating to compensate. Do not build yet: No reduced motion or export yet. ### Phase 3 · A version with no motion at all Build: Honour the reduced-motion preference by replacing transitions with cuts. Make the reduced-motion version a checked output rather than a fallback. Detect content that only reads correctly during a transition. Trap: Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. Done when: The reduced-motion preference replaces transitions with cuts throughout. The reduced-motion version is reviewed as a distinct output and its review is recorded. Content whose meaning depends on the transition is flagged. Every element visible in a viewpoint is legible without the approach to it. Do not build yet: No presenting or export yet. ### Phase 4 · Presenting without surprises Build: A presenter view with notes and the next viewpoint, working across two displays. Run entirely offline. Handle a display resolution and aspect ratio different from the authoring machine. Trap: A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. Done when: The presentation runs fully offline including fonts and media. A different aspect ratio is previewable at authoring time and does not crop content out of viewpoints. The presenter view shows notes and the next viewpoint across two displays. Recovery from a display disconnection mid-presentation returns to the current viewpoint. Do not build yet: No export yet. ### Phase 5 · Exports that still make the argument Build: Export a static deck of viewpoints and a document including speaker notes. Keep text as text. Verify the exported sequence makes sense without any motion at all. Trap: An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion. Done when: A static export produces one frame per viewpoint with text remaining as text. A document export includes speaker notes alongside each frame. The exported sequence is reviewed for coherence without motion and the review is recorded. Vector elements stay sharp at export resolution. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaborative editing, which is a synchronisation problem rather than a presentation one. - Template and asset libraries, which is most of what the hosted products provide. - Video recording with a presenter overlay, which is a different product for a different purpose. - Analytics on who watched what, which requires hosting the presentation rather than presenting it. ### README must contain - That zooming motion causes nausea for a meaningful share of any audience, who cannot leave the room - That zoom rate and rotation are capped as constants rather than settings - That the reduced-motion version is a checked first-class output rather than a fallback - That content depending on the transition to make sense is flagged, since it does not survive export either - That a static export keeps text as text and is reviewed for coherence without motion ===== AGENTS.md ===== # Agent instructions · Prezi indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A single large scene with content placed spatially, Named viewpoints with an ordered path between them, Interpolation with capped rate and rotation, honouring reduced motion, Vector where possible so zooming stays sharp, TypeScript with local documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. ===== BUILD_PLAN.md ===== # Build plan · Prezi A zooming canvas presentation tool where the interesting engineering is a smooth camera path across a large canvas and the governing constraint is that the motion must be optional without the presentation becoming incoherent. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · A canvas and a path across it Content sits in space and a sequence of viewpoints moves through it. ### Steps 1. Store viewpoints, derive motion Recorded motion cannot be reordered, and reordering is constant. Files: `src/viewpoints.ts` 2. Make the path a reorderable list Restructuring a presentation is the normal case. Files: `src/path.ts` 3. Support exact backward navigation Going back should return to the same framing, not an approximation. Files: `src/navigate.ts` ### Done when - [ ] Viewpoints are a reorderable list - [ ] Reordering requires no motion rework - [ ] Backward navigation returns exactly - [ ] A viewpoint updates without affecting others ### Watch out - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. ## Phase 2 · Motion with a ceiling No transition can move fast enough to make people ill. ### Steps 1. Cap zoom rate and rotation as constants Not settings. The person affected is not the one adjusting them. Files: `src/motion.ts`, `src/motion.test.ts` 2. Compute rates at authoring time So a bad path is a flag rather than a surprise during a talk. Files: `src/transitions.ts` 3. Keep long transitions smooth Rather than accelerating to cover distance in the same time. Files: `src/motion.ts` ### Done when - [ ] Transitions cannot exceed the caps - [ ] Over-cap paths are flagged at authoring - [ ] Caps are not runtime adjustable - [ ] Long transitions stay smooth ### Watch out - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. ## Phase 3 · A version with no motion at all The presentation works as cuts and still makes sense. ### Steps 1. Replace transitions with cuts Not shorter transitions. Cuts. Files: `src/reduced.ts` 2. Make the reduced version reviewable A checked output, with the check recorded. Files: `src/review.ts` 3. Flag motion-dependent content If it only reads during the zoom, it does not survive the export either. Files: `src/analysis.ts` ### Done when - [ ] Reduced motion replaces transitions with cuts - [ ] The reduced version is reviewed and recorded - [ ] Motion-dependent content is flagged - [ ] Every viewpoint is legible on its own ### Watch out - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. ## Phase 4 · Presenting without surprises The presentation runs on the machine and screen it will actually be given on. ### Steps 1. Run offline including fonts A missing font on the day changes every layout. Files: `src/present.ts` 2. Preview target aspect ratios Cropping is discovered in front of the audience otherwise. Files: `src/aspect.ts` 3. Survive a display disconnection It happens, and it should not lose your place. Files: `src/present.ts` ### Done when - [ ] The presentation runs fully offline - [ ] Other aspect ratios preview without cropping - [ ] Presenter view works across two displays - [ ] A display disconnection does not lose position ### Watch out - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. ## Not in this build - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. ## After v1, if you want it - An outline view that edits the path as a list, which is how most restructuring happens - Automatic viewpoint framing from element selection, which removes most of the fiddling - A rehearsal timer against dwell notes, once the path is stable ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Presentation files. A presentation is a document. DOCUMENTS_DIR=~/Documents/presentations # Required. A constant in the transition path. Not adjustable at runtime. MAX_ZOOM_RATE=2.0 # Required. Rotation is the worst offender for nausea. Keep it small. MAX_ROTATION_DEGREES=15 # Required. Present as a constant. The person affected cannot leave the room. RESPECT_REDUCED_MOTION=always # Required. Previewed at authoring, because cropping is found in front of an audience. TARGET_ASPECT_RATIOS=16:9,16:10,4:3 # Required. Present as a constant. A presentation must not depend on the room's network. OFFLINE_ONLY=always
You are building a lean indie version of Prezi. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Prezi · indie build A zooming canvas presentation tool where the interesting engineering is a smooth camera path across a large canvas and the governing constraint is that the motion must be optional without the presentation becoming incoherent. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A single large scene with content placed spatially | the spatial arrangement is the structure, not decoration | | Camera | Named viewpoints with an ordered path between them | a path of viewpoints is editable in a way a recorded motion is not | | Motion | Interpolation with capped rate and rotation, honouring reduced motion | the cap is what makes the format tolerable | | Rendering | Vector where possible so zooming stays sharp | zooming into a raster image is the format's most visible failure | | Runtime | TypeScript with local documents | a presentation is a document and must work without a network | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the editor and the presenter. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Your motion caps, decided before authoring** · free - Why: They are constants in the transition path, and deciding them after building a presentation means fitting them to the presentation rather than to the audience. - Get it: Set a maximum zoom rate and rotation, erring conservative, and write down the reasoning. - Verify: Both are written down and appear as constants in the motion module - [ ] **A second display and a different aspect ratio** · free if you have one - Why: Presenter view and aspect ratio cropping are both only testable with a real second screen, and cropping is discovered in front of an audience otherwise. - Get it: Any second display, ideally one whose aspect ratio differs from your authoring machine. - Verify: The presentation runs across two displays and previews correctly at another aspect ratio - [ ] **Someone to watch it who will tell you honestly** · free - Why: Motion tolerance varies enormously and the author is the worst judge, since they know where the camera is going next. - Get it: Show a full run to two or three people and ask specifically about discomfort rather than about the content. - Verify: At least three people have watched a full run and been asked directly - [ ] **A real presentation with a real argument** · free - Why: The reduced-motion and static export checks are about whether the argument survives, and a demonstration deck of shapes has no argument to lose. - Get it: Use a talk you have actually given or will give. - Verify: A presentation exists with at least fifteen viewpoints and a conclusion ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. - presentation and enterprise controls - production codecs, rendering speed, and media templates - multiplayer cursors and comments - large template libraries - high-fidelity import and export If one of those is essential to you, that is the reason to keep paying for Prezi, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Prezi The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a zooming canvas presentation that does not make the audience feel ill to replace Prezi. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero The distinguishing feature of this format is also its main risk. Continuous zooming and rotating motion triggers nausea and dizziness in a meaningful share of any audience, and the people affected cannot leave a meeting to escape it. Vestibular disorders make this considerably worse, and a presentation is not something a person opts into the way a website is. So the build treats motion as an accessibility question rather than a style one. It honours the reduced-motion preference by replacing zooming transitions with cuts, caps rotation and zoom rate as constants rather than settings, and makes the reduced-motion version a first class output that is checked rather than a degraded fallback. It also means the content has to work without the motion. If the argument only makes sense because of the zoom path, it does not survive the export, the reduced-motion viewer or someone reading the slides afterwards, which is most of a presentation's life. ### Stack (fixed, do not substitute) - Canvas: A single large scene with content placed spatially · the spatial arrangement is the structure, not decoration - Camera: Named viewpoints with an ordered path between them · a path of viewpoints is editable in a way a recorded motion is not - Motion: Interpolation with capped rate and rotation, honouring reduced motion · the cap is what makes the format tolerable - Rendering: Vector where possible so zooming stays sharp · zooming into a raster image is the format's most visible failure - Runtime: TypeScript with local documents · a presentation is a document and must work without a network ### Data model (create this before Phase 1) - presentations(id, title, canvas_width, canvas_height, reduced_motion_checked) - elements(id, presentation_id, kind, x, y, width, height, rotation, z, content_json, is_vector) - viewpoints(id, presentation_id, ordinal, x, y, width, height, rotation, dwell_note) - transitions(from_viewpoint_id, to_viewpoint_id, duration_ms, easing, computed_rate, exceeds_cap) - speaker_notes(viewpoint_id, body) - exports(id, presentation_id, kind, path, motion_mode, at) · kind is document, video or static deck - A transition stores its computed motion rate, so a path that would exceed the cap is detectable at authoring time rather than during a presentation. ### Phase 1 · A canvas and a path across it Build: A large canvas with elements placed spatially, and an ordered list of named viewpoints. Navigate forward and backward. Keep the path editable as a list rather than as recorded camera motion. Trap: Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. Done when: Viewpoints are stored as a reorderable list and the path is derived from them. Reordering does not require redoing any motion. Backward navigation works and returns exactly to the previous framing. A viewpoint can be updated to the current view without affecting the others. Do not build yet: No motion caps, reduced motion or export. ### Phase 2 · Motion with a ceiling Build: Interpolate between viewpoints with capped zoom rate and rotation. Compute each transition's rate at authoring time and flag any that would exceed the cap. Make the caps constants rather than settings. Trap: Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. Done when: Transitions cannot exceed the capped zoom rate or rotation, verified by attempting to author one. A transition that would exceed the cap is flagged at authoring with the reason. The caps are constants and are not adjustable at runtime. A long transition across the canvas remains smooth rather than accelerating to compensate. Do not build yet: No reduced motion or export yet. ### Phase 3 · A version with no motion at all Build: Honour the reduced-motion preference by replacing transitions with cuts. Make the reduced-motion version a checked output rather than a fallback. Detect content that only reads correctly during a transition. Trap: Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. Done when: The reduced-motion preference replaces transitions with cuts throughout. The reduced-motion version is reviewed as a distinct output and its review is recorded. Content whose meaning depends on the transition is flagged. Every element visible in a viewpoint is legible without the approach to it. Do not build yet: No presenting or export yet. ### Phase 4 · Presenting without surprises Build: A presenter view with notes and the next viewpoint, working across two displays. Run entirely offline. Handle a display resolution and aspect ratio different from the authoring machine. Trap: A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. Done when: The presentation runs fully offline including fonts and media. A different aspect ratio is previewable at authoring time and does not crop content out of viewpoints. The presenter view shows notes and the next viewpoint across two displays. Recovery from a display disconnection mid-presentation returns to the current viewpoint. Do not build yet: No export yet. ### Phase 5 · Exports that still make the argument Build: Export a static deck of viewpoints and a document including speaker notes. Keep text as text. Verify the exported sequence makes sense without any motion at all. Trap: An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion. Done when: A static export produces one frame per viewpoint with text remaining as text. A document export includes speaker notes alongside each frame. The exported sequence is reviewed for coherence without motion and the review is recorded. Vector elements stay sharp at export resolution. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaborative editing, which is a synchronisation problem rather than a presentation one. - Template and asset libraries, which is most of what the hosted products provide. - Video recording with a presenter overlay, which is a different product for a different purpose. - Analytics on who watched what, which requires hosting the presentation rather than presenting it. ### README must contain - That zooming motion causes nausea for a meaningful share of any audience, who cannot leave the room - That zoom rate and rotation are capped as constants rather than settings - That the reduced-motion version is a checked first-class output rather than a fallback - That content depending on the transition to make sense is flagged, since it does not survive export either - That a static export keeps text as text and is reviewed for coherence without motion ===== AGENTS.md ===== # Agent instructions · Prezi indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A single large scene with content placed spatially, Named viewpoints with an ordered path between them, Interpolation with capped rate and rotation, honouring reduced motion, Vector where possible so zooming stays sharp, TypeScript with local documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. ===== BUILD_PLAN.md ===== # Build plan · Prezi A zooming canvas presentation tool where the interesting engineering is a smooth camera path across a large canvas and the governing constraint is that the motion must be optional without the presentation becoming incoherent. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · A canvas and a path across it Content sits in space and a sequence of viewpoints moves through it. ### Steps 1. Store viewpoints, derive motion Recorded motion cannot be reordered, and reordering is constant. Files: `src/viewpoints.ts` 2. Make the path a reorderable list Restructuring a presentation is the normal case. Files: `src/path.ts` 3. Support exact backward navigation Going back should return to the same framing, not an approximation. Files: `src/navigate.ts` ### Done when - [ ] Viewpoints are a reorderable list - [ ] Reordering requires no motion rework - [ ] Backward navigation returns exactly - [ ] A viewpoint updates without affecting others ### Watch out - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. ## Phase 2 · Motion with a ceiling No transition can move fast enough to make people ill. ### Steps 1. Cap zoom rate and rotation as constants Not settings. The person affected is not the one adjusting them. Files: `src/motion.ts`, `src/motion.test.ts` 2. Compute rates at authoring time So a bad path is a flag rather than a surprise during a talk. Files: `src/transitions.ts` 3. Keep long transitions smooth Rather than accelerating to cover distance in the same time. Files: `src/motion.ts` ### Done when - [ ] Transitions cannot exceed the caps - [ ] Over-cap paths are flagged at authoring - [ ] Caps are not runtime adjustable - [ ] Long transitions stay smooth ### Watch out - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. ## Phase 3 · A version with no motion at all The presentation works as cuts and still makes sense. ### Steps 1. Replace transitions with cuts Not shorter transitions. Cuts. Files: `src/reduced.ts` 2. Make the reduced version reviewable A checked output, with the check recorded. Files: `src/review.ts` 3. Flag motion-dependent content If it only reads during the zoom, it does not survive the export either. Files: `src/analysis.ts` ### Done when - [ ] Reduced motion replaces transitions with cuts - [ ] The reduced version is reviewed and recorded - [ ] Motion-dependent content is flagged - [ ] Every viewpoint is legible on its own ### Watch out - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. ## Phase 4 · Presenting without surprises The presentation runs on the machine and screen it will actually be given on. ### Steps 1. Run offline including fonts A missing font on the day changes every layout. Files: `src/present.ts` 2. Preview target aspect ratios Cropping is discovered in front of the audience otherwise. Files: `src/aspect.ts` 3. Survive a display disconnection It happens, and it should not lose your place. Files: `src/present.ts` ### Done when - [ ] The presentation runs fully offline - [ ] Other aspect ratios preview without cropping - [ ] Presenter view works across two displays - [ ] A display disconnection does not lose position ### Watch out - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. ## Not in this build - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. ## After v1, if you want it - An outline view that edits the path as a list, which is how most restructuring happens - Automatic viewpoint framing from element selection, which removes most of the fiddling - A rehearsal timer against dwell notes, once the path is stable ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Presentation files. A presentation is a document. DOCUMENTS_DIR=~/Documents/presentations # Required. A constant in the transition path. Not adjustable at runtime. MAX_ZOOM_RATE=2.0 # Required. Rotation is the worst offender for nausea. Keep it small. MAX_ROTATION_DEGREES=15 # Required. Present as a constant. The person affected cannot leave the room. RESPECT_REDUCED_MOTION=always # Required. Previewed at authoring, because cropping is found in front of an audience. TARGET_ASPECT_RATIOS=16:9,16:10,4:3 # Required. Present as a constant. A presentation must not depend on the room's network. OFFLINE_ONLY=always
You are building a production product version of Prezi. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # Prezi · product brief ## Problem The visible zooming presentations loop is buildable, but a credible replacement needs more than the first screen. Prezi earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A zooming presentation that stays within motion limits nobody can raise, works as cuts for anyone who needs that, and still makes its argument when read as a static document. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. - presentation and enterprise controls - production codecs, rendering speed, and media templates - multiplayer cursors and comments - large template libraries - high-fidelity import and export ## Success criteria - Transitions are confirmed unable to exceed the motion caps - Caps are confirmed not runtime adjustable - The reduced-motion version is confirmed reviewed and coherent - The presentation is confirmed to run fully offline - A static export is confirmed to keep text as text ===== BRIEF.md ===== # Build brief · Prezi The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a zooming canvas presentation that does not make the audience feel ill to replace Prezi. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero The distinguishing feature of this format is also its main risk. Continuous zooming and rotating motion triggers nausea and dizziness in a meaningful share of any audience, and the people affected cannot leave a meeting to escape it. Vestibular disorders make this considerably worse, and a presentation is not something a person opts into the way a website is. So the build treats motion as an accessibility question rather than a style one. It honours the reduced-motion preference by replacing zooming transitions with cuts, caps rotation and zoom rate as constants rather than settings, and makes the reduced-motion version a first class output that is checked rather than a degraded fallback. It also means the content has to work without the motion. If the argument only makes sense because of the zoom path, it does not survive the export, the reduced-motion viewer or someone reading the slides afterwards, which is most of a presentation's life. ### Stack (fixed, do not substitute) - Canvas: A single large scene with content placed spatially · the spatial arrangement is the structure, not decoration - Camera: Named viewpoints with an ordered path between them · a path of viewpoints is editable in a way a recorded motion is not - Motion: Interpolation with capped rate and rotation, honouring reduced motion · the cap is what makes the format tolerable - Rendering: Vector where possible so zooming stays sharp · zooming into a raster image is the format's most visible failure - Runtime: TypeScript with local documents · a presentation is a document and must work without a network ### Data model (create this before Phase 1) - presentations(id, title, canvas_width, canvas_height, reduced_motion_checked) - elements(id, presentation_id, kind, x, y, width, height, rotation, z, content_json, is_vector) - viewpoints(id, presentation_id, ordinal, x, y, width, height, rotation, dwell_note) - transitions(from_viewpoint_id, to_viewpoint_id, duration_ms, easing, computed_rate, exceeds_cap) - speaker_notes(viewpoint_id, body) - exports(id, presentation_id, kind, path, motion_mode, at) · kind is document, video or static deck - A transition stores its computed motion rate, so a path that would exceed the cap is detectable at authoring time rather than during a presentation. ### Phase 1 · A canvas and a path across it Build: A large canvas with elements placed spatially, and an ordered list of named viewpoints. Navigate forward and backward. Keep the path editable as a list rather than as recorded camera motion. Trap: Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. Done when: Viewpoints are stored as a reorderable list and the path is derived from them. Reordering does not require redoing any motion. Backward navigation works and returns exactly to the previous framing. A viewpoint can be updated to the current view without affecting the others. Do not build yet: No motion caps, reduced motion or export. ### Phase 2 · Motion with a ceiling Build: Interpolate between viewpoints with capped zoom rate and rotation. Compute each transition's rate at authoring time and flag any that would exceed the cap. Make the caps constants rather than settings. Trap: Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. Done when: Transitions cannot exceed the capped zoom rate or rotation, verified by attempting to author one. A transition that would exceed the cap is flagged at authoring with the reason. The caps are constants and are not adjustable at runtime. A long transition across the canvas remains smooth rather than accelerating to compensate. Do not build yet: No reduced motion or export yet. ### Phase 3 · A version with no motion at all Build: Honour the reduced-motion preference by replacing transitions with cuts. Make the reduced-motion version a checked output rather than a fallback. Detect content that only reads correctly during a transition. Trap: Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. Done when: The reduced-motion preference replaces transitions with cuts throughout. The reduced-motion version is reviewed as a distinct output and its review is recorded. Content whose meaning depends on the transition is flagged. Every element visible in a viewpoint is legible without the approach to it. Do not build yet: No presenting or export yet. ### Phase 4 · Presenting without surprises Build: A presenter view with notes and the next viewpoint, working across two displays. Run entirely offline. Handle a display resolution and aspect ratio different from the authoring machine. Trap: A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. Done when: The presentation runs fully offline including fonts and media. A different aspect ratio is previewable at authoring time and does not crop content out of viewpoints. The presenter view shows notes and the next viewpoint across two displays. Recovery from a display disconnection mid-presentation returns to the current viewpoint. Do not build yet: No export yet. ### Phase 5 · Exports that still make the argument Build: Export a static deck of viewpoints and a document including speaker notes. Keep text as text. Verify the exported sequence makes sense without any motion at all. Trap: An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion. Done when: A static export produces one frame per viewpoint with text remaining as text. A document export includes speaker notes alongside each frame. The exported sequence is reviewed for coherence without motion and the review is recorded. Vector elements stay sharp at export resolution. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaborative editing, which is a synchronisation problem rather than a presentation one. - Template and asset libraries, which is most of what the hosted products provide. - Video recording with a presenter overlay, which is a different product for a different purpose. - Analytics on who watched what, which requires hosting the presentation rather than presenting it. ### README must contain - That zooming motion causes nausea for a meaningful share of any audience, who cannot leave the room - That zoom rate and rotation are capped as constants rather than settings - That the reduced-motion version is a checked first-class output rather than a fallback - That content depending on the transition to make sense is flagged, since it does not survive export either - That a static export keeps text as text and is reviewed for coherence without motion ===== ARCHITECTURE.md ===== # Architecture · Prezi ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A single large scene with content placed spatially | the spatial arrangement is the structure, not decoration | | Camera | Named viewpoints with an ordered path between them | a path of viewpoints is editable in a way a recorded motion is not | | Motion | Interpolation with capped rate and rotation, honouring reduced motion | the cap is what makes the format tolerable | | Rendering | Vector where possible so zooming stays sharp | zooming into a raster image is the format's most visible failure | | Runtime | TypeScript with local documents | a presentation is a document and must work without a network | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Canvas | Spatial content and viewpoints. | Any implementation, provided the path is a reorderable list rather than recorded motion. | | Motion | Capped interpolation. | Any easing, provided the caps are constants evaluated after it. | | Reduced motion | A checked cut-based output. | Not swappable for an untested fallback, which is worse than the motion. | | Presenting | Offline running and aspect handling. | Any implementation, provided it works without a network. | | Export | Static sequences with text preserved. | Any format, provided the argument is reviewed without motion. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DOCUMENTS_DIR` · required · Presentation files. A presentation is a document. - `MAX_ZOOM_RATE` · required · A constant in the transition path. Not adjustable at runtime. - `MAX_ROTATION_DEGREES` · required · Rotation is the worst offender for nausea. Keep it small. - `RESPECT_REDUCED_MOTION` · required · Present as a constant. The person affected cannot leave the room. - `TARGET_ASPECT_RATIOS` · required · Previewed at authoring, because cropping is found in front of an audience. - `OFFLINE_ONLY` · required · Present as a constant. A presentation must not depend on the room's network. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · Prezi product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A single large scene with content placed spatially, Named viewpoints with an ordered path between them, Interpolation with capped rate and rotation, honouring reduced motion, Vector where possible so zooming stays sharp, TypeScript with local documents. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. - An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion. ===== MILESTONES.md ===== # Delivery milestones · Prezi Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · A canvas and a path across it Content sits in space and a sequence of viewpoints moves through it. ### Steps 1. Store viewpoints, derive motion Recorded motion cannot be reordered, and reordering is constant. Files: `src/viewpoints.ts` 2. Make the path a reorderable list Restructuring a presentation is the normal case. Files: `src/path.ts` 3. Support exact backward navigation Going back should return to the same framing, not an approximation. Files: `src/navigate.ts` ### Done when - [ ] Viewpoints are a reorderable list - [ ] Reordering requires no motion rework - [ ] Backward navigation returns exactly - [ ] A viewpoint updates without affecting others ### Watch out - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. ## M2 · Motion with a ceiling No transition can move fast enough to make people ill. ### Steps 1. Cap zoom rate and rotation as constants Not settings. The person affected is not the one adjusting them. Files: `src/motion.ts`, `src/motion.test.ts` 2. Compute rates at authoring time So a bad path is a flag rather than a surprise during a talk. Files: `src/transitions.ts` 3. Keep long transitions smooth Rather than accelerating to cover distance in the same time. Files: `src/motion.ts` ### Done when - [ ] Transitions cannot exceed the caps - [ ] Over-cap paths are flagged at authoring - [ ] Caps are not runtime adjustable - [ ] Long transitions stay smooth ### Watch out - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. ## M3 · A version with no motion at all The presentation works as cuts and still makes sense. ### Steps 1. Replace transitions with cuts Not shorter transitions. Cuts. Files: `src/reduced.ts` 2. Make the reduced version reviewable A checked output, with the check recorded. Files: `src/review.ts` 3. Flag motion-dependent content If it only reads during the zoom, it does not survive the export either. Files: `src/analysis.ts` ### Done when - [ ] Reduced motion replaces transitions with cuts - [ ] The reduced version is reviewed and recorded - [ ] Motion-dependent content is flagged - [ ] Every viewpoint is legible on its own ### Watch out - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. ## M4 · Presenting without surprises The presentation runs on the machine and screen it will actually be given on. ### Steps 1. Run offline including fonts A missing font on the day changes every layout. Files: `src/present.ts` 2. Preview target aspect ratios Cropping is discovered in front of the audience otherwise. Files: `src/aspect.ts` 3. Survive a display disconnection It happens, and it should not lose your place. Files: `src/present.ts` ### Done when - [ ] The presentation runs fully offline - [ ] Other aspect ratios preview without cropping - [ ] Presenter view works across two displays - [ ] A display disconnection does not lose position ### Watch out - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. ## M5 · Exports that still make the argument (production only) The presentation survives being read rather than watched. ### Steps 1. Export viewpoints as a readable sequence Most of a presentation's life is being read, not watched. Files: `src/export.ts` 2. Keep text as text So it is searchable, selectable and readable by assistive tools. Files: `src/export.ts` 3. Review coherence without motion If the argument needed the zoom, it needed rewriting. Files: `src/review.ts` ### Done when - [ ] Static export gives one frame per viewpoint - [ ] Text remains text in exports - [ ] Coherence without motion is reviewed - [ ] Vector elements stay sharp ### Watch out - An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion. ===== OPERATIONS.md ===== # Operations · Prezi ## Backup Presentations are documents and belong with your ordinary document backups. Embedded media should be inside the document rather than referenced, since a missing asset on presentation day is the failure that matters. ## Restore Restore and confirm fonts and media are embedded rather than referenced, since a restored presentation that reflows because a font is missing changes every viewpoint's framing. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For an authoring tool the check is at authoring time: transitions exceeding the caps and viewpoints flagged as motion-dependent are both caught before anyone presents, which is the only useful moment. ## Incident checklist An audience member made ill is the failure this build exists to prevent, and it means the caps were too generous rather than that the software broke. Reviewing the caps is the response, not adjusting them upward. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Transitions are confirmed unable to exceed the motion caps - [ ] Caps are confirmed not runtime adjustable - [ ] The reduced-motion version is confirmed reviewed and coherent - [ ] The presentation is confirmed to run fully offline - [ ] A static export is confirmed to keep text as text ## Launch constraint Do not market omitted Prezi capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Presentation files. A presentation is a document. DOCUMENTS_DIR=~/Documents/presentations # Required. A constant in the transition path. Not adjustable at runtime. MAX_ZOOM_RATE=2.0 # Required. Rotation is the worst offender for nausea. Keep it small. MAX_ROTATION_DEGREES=15 # Required. Present as a constant. The person affected cannot leave the room. RESPECT_REDUCED_MOTION=always # Required. Previewed at authoring, because cropping is found in front of an audience. TARGET_ASPECT_RATIOS=16:9,16:10,4:3 # Required. Present as a constant. A presentation must not depend on the room's network. OFFLINE_ONLY=always
# Prezi · indie build A zooming canvas presentation tool where the interesting engineering is a smooth camera path across a large canvas and the governing constraint is that the motion must be optional without the presentation becoming incoherent. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A single large scene with content placed spatially | the spatial arrangement is the structure, not decoration | | Camera | Named viewpoints with an ordered path between them | a path of viewpoints is editable in a way a recorded motion is not | | Motion | Interpolation with capped rate and rotation, honouring reduced motion | the cap is what makes the format tolerable | | Rendering | Vector where possible so zooming stays sharp | zooming into a raster image is the format's most visible failure | | Runtime | TypeScript with local documents | a presentation is a document and must work without a network | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the editor and the presenter. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Your motion caps, decided before authoring** · free - Why: They are constants in the transition path, and deciding them after building a presentation means fitting them to the presentation rather than to the audience. - Get it: Set a maximum zoom rate and rotation, erring conservative, and write down the reasoning. - Verify: Both are written down and appear as constants in the motion module - [ ] **A second display and a different aspect ratio** · free if you have one - Why: Presenter view and aspect ratio cropping are both only testable with a real second screen, and cropping is discovered in front of an audience otherwise. - Get it: Any second display, ideally one whose aspect ratio differs from your authoring machine. - Verify: The presentation runs across two displays and previews correctly at another aspect ratio - [ ] **Someone to watch it who will tell you honestly** · free - Why: Motion tolerance varies enormously and the author is the worst judge, since they know where the camera is going next. - Get it: Show a full run to two or three people and ask specifically about discomfort rather than about the content. - Verify: At least three people have watched a full run and been asked directly - [ ] **A real presentation with a real argument** · free - Why: The reduced-motion and static export checks are about whether the argument survives, and a demonstration deck of shapes has no argument to lose. - Get it: Use a talk you have actually given or will give. - Verify: A presentation exists with at least fifteen viewpoints and a conclusion ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. - presentation and enterprise controls - production codecs, rendering speed, and media templates - multiplayer cursors and comments - large template libraries - high-fidelity import and export If one of those is essential to you, that is the reason to keep paying for Prezi, and the README should say so rather than pretend.
# Build brief · Prezi The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a zooming canvas presentation that does not make the audience feel ill to replace Prezi. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero The distinguishing feature of this format is also its main risk. Continuous zooming and rotating motion triggers nausea and dizziness in a meaningful share of any audience, and the people affected cannot leave a meeting to escape it. Vestibular disorders make this considerably worse, and a presentation is not something a person opts into the way a website is. So the build treats motion as an accessibility question rather than a style one. It honours the reduced-motion preference by replacing zooming transitions with cuts, caps rotation and zoom rate as constants rather than settings, and makes the reduced-motion version a first class output that is checked rather than a degraded fallback. It also means the content has to work without the motion. If the argument only makes sense because of the zoom path, it does not survive the export, the reduced-motion viewer or someone reading the slides afterwards, which is most of a presentation's life. ### Stack (fixed, do not substitute) - Canvas: A single large scene with content placed spatially · the spatial arrangement is the structure, not decoration - Camera: Named viewpoints with an ordered path between them · a path of viewpoints is editable in a way a recorded motion is not - Motion: Interpolation with capped rate and rotation, honouring reduced motion · the cap is what makes the format tolerable - Rendering: Vector where possible so zooming stays sharp · zooming into a raster image is the format's most visible failure - Runtime: TypeScript with local documents · a presentation is a document and must work without a network ### Data model (create this before Phase 1) - presentations(id, title, canvas_width, canvas_height, reduced_motion_checked) - elements(id, presentation_id, kind, x, y, width, height, rotation, z, content_json, is_vector) - viewpoints(id, presentation_id, ordinal, x, y, width, height, rotation, dwell_note) - transitions(from_viewpoint_id, to_viewpoint_id, duration_ms, easing, computed_rate, exceeds_cap) - speaker_notes(viewpoint_id, body) - exports(id, presentation_id, kind, path, motion_mode, at) · kind is document, video or static deck - A transition stores its computed motion rate, so a path that would exceed the cap is detectable at authoring time rather than during a presentation. ### Phase 1 · A canvas and a path across it Build: A large canvas with elements placed spatially, and an ordered list of named viewpoints. Navigate forward and backward. Keep the path editable as a list rather than as recorded camera motion. Trap: Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. Done when: Viewpoints are stored as a reorderable list and the path is derived from them. Reordering does not require redoing any motion. Backward navigation works and returns exactly to the previous framing. A viewpoint can be updated to the current view without affecting the others. Do not build yet: No motion caps, reduced motion or export. ### Phase 2 · Motion with a ceiling Build: Interpolate between viewpoints with capped zoom rate and rotation. Compute each transition's rate at authoring time and flag any that would exceed the cap. Make the caps constants rather than settings. Trap: Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. Done when: Transitions cannot exceed the capped zoom rate or rotation, verified by attempting to author one. A transition that would exceed the cap is flagged at authoring with the reason. The caps are constants and are not adjustable at runtime. A long transition across the canvas remains smooth rather than accelerating to compensate. Do not build yet: No reduced motion or export yet. ### Phase 3 · A version with no motion at all Build: Honour the reduced-motion preference by replacing transitions with cuts. Make the reduced-motion version a checked output rather than a fallback. Detect content that only reads correctly during a transition. Trap: Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. Done when: The reduced-motion preference replaces transitions with cuts throughout. The reduced-motion version is reviewed as a distinct output and its review is recorded. Content whose meaning depends on the transition is flagged. Every element visible in a viewpoint is legible without the approach to it. Do not build yet: No presenting or export yet. ### Phase 4 · Presenting without surprises Build: A presenter view with notes and the next viewpoint, working across two displays. Run entirely offline. Handle a display resolution and aspect ratio different from the authoring machine. Trap: A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. Done when: The presentation runs fully offline including fonts and media. A different aspect ratio is previewable at authoring time and does not crop content out of viewpoints. The presenter view shows notes and the next viewpoint across two displays. Recovery from a display disconnection mid-presentation returns to the current viewpoint. Do not build yet: No export yet. ### Phase 5 · Exports that still make the argument Build: Export a static deck of viewpoints and a document including speaker notes. Keep text as text. Verify the exported sequence makes sense without any motion at all. Trap: An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion. Done when: A static export produces one frame per viewpoint with text remaining as text. A document export includes speaker notes alongside each frame. The exported sequence is reviewed for coherence without motion and the review is recorded. Vector elements stay sharp at export resolution. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaborative editing, which is a synchronisation problem rather than a presentation one. - Template and asset libraries, which is most of what the hosted products provide. - Video recording with a presenter overlay, which is a different product for a different purpose. - Analytics on who watched what, which requires hosting the presentation rather than presenting it. ### README must contain - That zooming motion causes nausea for a meaningful share of any audience, who cannot leave the room - That zoom rate and rotation are capped as constants rather than settings - That the reduced-motion version is a checked first-class output rather than a fallback - That content depending on the transition to make sense is flagged, since it does not survive export either - That a static export keeps text as text and is reviewed for coherence without motion
# Agent instructions · Prezi indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A single large scene with content placed spatially, Named viewpoints with an ordered path between them, Interpolation with capped rate and rotation, honouring reduced motion, Vector where possible so zooming stays sharp, TypeScript with local documents. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day.
# Build plan · Prezi A zooming canvas presentation tool where the interesting engineering is a smooth camera path across a large canvas and the governing constraint is that the motion must be optional without the presentation becoming incoherent. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · A canvas and a path across it Content sits in space and a sequence of viewpoints moves through it. ### Steps 1. Store viewpoints, derive motion Recorded motion cannot be reordered, and reordering is constant. Files: `src/viewpoints.ts` 2. Make the path a reorderable list Restructuring a presentation is the normal case. Files: `src/path.ts` 3. Support exact backward navigation Going back should return to the same framing, not an approximation. Files: `src/navigate.ts` ### Done when - [ ] Viewpoints are a reorderable list - [ ] Reordering requires no motion rework - [ ] Backward navigation returns exactly - [ ] A viewpoint updates without affecting others ### Watch out - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. ## Phase 2 · Motion with a ceiling No transition can move fast enough to make people ill. ### Steps 1. Cap zoom rate and rotation as constants Not settings. The person affected is not the one adjusting them. Files: `src/motion.ts`, `src/motion.test.ts` 2. Compute rates at authoring time So a bad path is a flag rather than a surprise during a talk. Files: `src/transitions.ts` 3. Keep long transitions smooth Rather than accelerating to cover distance in the same time. Files: `src/motion.ts` ### Done when - [ ] Transitions cannot exceed the caps - [ ] Over-cap paths are flagged at authoring - [ ] Caps are not runtime adjustable - [ ] Long transitions stay smooth ### Watch out - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. ## Phase 3 · A version with no motion at all The presentation works as cuts and still makes sense. ### Steps 1. Replace transitions with cuts Not shorter transitions. Cuts. Files: `src/reduced.ts` 2. Make the reduced version reviewable A checked output, with the check recorded. Files: `src/review.ts` 3. Flag motion-dependent content If it only reads during the zoom, it does not survive the export either. Files: `src/analysis.ts` ### Done when - [ ] Reduced motion replaces transitions with cuts - [ ] The reduced version is reviewed and recorded - [ ] Motion-dependent content is flagged - [ ] Every viewpoint is legible on its own ### Watch out - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. ## Phase 4 · Presenting without surprises The presentation runs on the machine and screen it will actually be given on. ### Steps 1. Run offline including fonts A missing font on the day changes every layout. Files: `src/present.ts` 2. Preview target aspect ratios Cropping is discovered in front of the audience otherwise. Files: `src/aspect.ts` 3. Survive a display disconnection It happens, and it should not lose your place. Files: `src/present.ts` ### Done when - [ ] The presentation runs fully offline - [ ] Other aspect ratios preview without cropping - [ ] Presenter view works across two displays - [ ] A display disconnection does not lose position ### Watch out - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. ## Not in this build - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. ## After v1, if you want it - An outline view that edits the path as a list, which is how most restructuring happens - Automatic viewpoint framing from element selection, which removes most of the fiddling - A rehearsal timer against dwell notes, once the path is stable
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Presentation files. A presentation is a document. DOCUMENTS_DIR=~/Documents/presentations # Required. A constant in the transition path. Not adjustable at runtime. MAX_ZOOM_RATE=2.0 # Required. Rotation is the worst offender for nausea. Keep it small. MAX_ROTATION_DEGREES=15 # Required. Present as a constant. The person affected cannot leave the room. RESPECT_REDUCED_MOTION=always # Required. Previewed at authoring, because cropping is found in front of an audience. TARGET_ASPECT_RATIOS=16:9,16:10,4:3 # Required. Present as a constant. A presentation must not depend on the room's network. OFFLINE_ONLY=always
# Prezi · product brief ## Problem The visible zooming presentations loop is buildable, but a credible replacement needs more than the first screen. Prezi earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A zooming presentation that stays within motion limits nobody can raise, works as cuts for anyone who needs that, and still makes its argument when read as a static document. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Real-time collaborative editing. - Template and asset libraries. - Video recording with presenter overlay. - Viewing analytics. - presentation and enterprise controls - production codecs, rendering speed, and media templates - multiplayer cursors and comments - large template libraries - high-fidelity import and export ## Success criteria - Transitions are confirmed unable to exceed the motion caps - Caps are confirmed not runtime adjustable - The reduced-motion version is confirmed reviewed and coherent - The presentation is confirmed to run fully offline - A static export is confirmed to keep text as text
# Build brief · Prezi The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a zooming canvas presentation that does not make the audience feel ill to replace Prezi. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero The distinguishing feature of this format is also its main risk. Continuous zooming and rotating motion triggers nausea and dizziness in a meaningful share of any audience, and the people affected cannot leave a meeting to escape it. Vestibular disorders make this considerably worse, and a presentation is not something a person opts into the way a website is. So the build treats motion as an accessibility question rather than a style one. It honours the reduced-motion preference by replacing zooming transitions with cuts, caps rotation and zoom rate as constants rather than settings, and makes the reduced-motion version a first class output that is checked rather than a degraded fallback. It also means the content has to work without the motion. If the argument only makes sense because of the zoom path, it does not survive the export, the reduced-motion viewer or someone reading the slides afterwards, which is most of a presentation's life. ### Stack (fixed, do not substitute) - Canvas: A single large scene with content placed spatially · the spatial arrangement is the structure, not decoration - Camera: Named viewpoints with an ordered path between them · a path of viewpoints is editable in a way a recorded motion is not - Motion: Interpolation with capped rate and rotation, honouring reduced motion · the cap is what makes the format tolerable - Rendering: Vector where possible so zooming stays sharp · zooming into a raster image is the format's most visible failure - Runtime: TypeScript with local documents · a presentation is a document and must work without a network ### Data model (create this before Phase 1) - presentations(id, title, canvas_width, canvas_height, reduced_motion_checked) - elements(id, presentation_id, kind, x, y, width, height, rotation, z, content_json, is_vector) - viewpoints(id, presentation_id, ordinal, x, y, width, height, rotation, dwell_note) - transitions(from_viewpoint_id, to_viewpoint_id, duration_ms, easing, computed_rate, exceeds_cap) - speaker_notes(viewpoint_id, body) - exports(id, presentation_id, kind, path, motion_mode, at) · kind is document, video or static deck - A transition stores its computed motion rate, so a path that would exceed the cap is detectable at authoring time rather than during a presentation. ### Phase 1 · A canvas and a path across it Build: A large canvas with elements placed spatially, and an ordered list of named viewpoints. Navigate forward and backward. Keep the path editable as a list rather than as recorded camera motion. Trap: Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. Done when: Viewpoints are stored as a reorderable list and the path is derived from them. Reordering does not require redoing any motion. Backward navigation works and returns exactly to the previous framing. A viewpoint can be updated to the current view without affecting the others. Do not build yet: No motion caps, reduced motion or export. ### Phase 2 · Motion with a ceiling Build: Interpolate between viewpoints with capped zoom rate and rotation. Compute each transition's rate at authoring time and flag any that would exceed the cap. Make the caps constants rather than settings. Trap: Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. Done when: Transitions cannot exceed the capped zoom rate or rotation, verified by attempting to author one. A transition that would exceed the cap is flagged at authoring with the reason. The caps are constants and are not adjustable at runtime. A long transition across the canvas remains smooth rather than accelerating to compensate. Do not build yet: No reduced motion or export yet. ### Phase 3 · A version with no motion at all Build: Honour the reduced-motion preference by replacing transitions with cuts. Make the reduced-motion version a checked output rather than a fallback. Detect content that only reads correctly during a transition. Trap: Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. Done when: The reduced-motion preference replaces transitions with cuts throughout. The reduced-motion version is reviewed as a distinct output and its review is recorded. Content whose meaning depends on the transition is flagged. Every element visible in a viewpoint is legible without the approach to it. Do not build yet: No presenting or export yet. ### Phase 4 · Presenting without surprises Build: A presenter view with notes and the next viewpoint, working across two displays. Run entirely offline. Handle a display resolution and aspect ratio different from the authoring machine. Trap: A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. Done when: The presentation runs fully offline including fonts and media. A different aspect ratio is previewable at authoring time and does not crop content out of viewpoints. The presenter view shows notes and the next viewpoint across two displays. Recovery from a display disconnection mid-presentation returns to the current viewpoint. Do not build yet: No export yet. ### Phase 5 · Exports that still make the argument Build: Export a static deck of viewpoints and a document including speaker notes. Keep text as text. Verify the exported sequence makes sense without any motion at all. Trap: An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion. Done when: A static export produces one frame per viewpoint with text remaining as text. A document export includes speaker notes alongside each frame. The exported sequence is reviewed for coherence without motion and the review is recorded. Vector elements stay sharp at export resolution. Do not build yet: Nothing after this. ### Out of scope (and why) - Real-time collaborative editing, which is a synchronisation problem rather than a presentation one. - Template and asset libraries, which is most of what the hosted products provide. - Video recording with a presenter overlay, which is a different product for a different purpose. - Analytics on who watched what, which requires hosting the presentation rather than presenting it. ### README must contain - That zooming motion causes nausea for a meaningful share of any audience, who cannot leave the room - That zoom rate and rotation are capped as constants rather than settings - That the reduced-motion version is a checked first-class output rather than a fallback - That content depending on the transition to make sense is flagged, since it does not survive export either - That a static export keeps text as text and is reviewed for coherence without motion
# Architecture · Prezi ## Stack | Part | Choice | Why | | --- | --- | --- | | Canvas | A single large scene with content placed spatially | the spatial arrangement is the structure, not decoration | | Camera | Named viewpoints with an ordered path between them | a path of viewpoints is editable in a way a recorded motion is not | | Motion | Interpolation with capped rate and rotation, honouring reduced motion | the cap is what makes the format tolerable | | Rendering | Vector where possible so zooming stays sharp | zooming into a raster image is the format's most visible failure | | Runtime | TypeScript with local documents | a presentation is a document and must work without a network | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Canvas | Spatial content and viewpoints. | Any implementation, provided the path is a reorderable list rather than recorded motion. | | Motion | Capped interpolation. | Any easing, provided the caps are constants evaluated after it. | | Reduced motion | A checked cut-based output. | Not swappable for an untested fallback, which is worse than the motion. | | Presenting | Offline running and aspect handling. | Any implementation, provided it works without a network. | | Export | Static sequences with text preserved. | Any format, provided the argument is reviewed without motion. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DOCUMENTS_DIR` · required · Presentation files. A presentation is a document. - `MAX_ZOOM_RATE` · required · A constant in the transition path. Not adjustable at runtime. - `MAX_ROTATION_DEGREES` · required · Rotation is the worst offender for nausea. Keep it small. - `RESPECT_REDUCED_MOTION` · required · Present as a constant. The person affected cannot leave the room. - `TARGET_ASPECT_RATIOS` · required · Previewed at authoring, because cropping is found in front of an audience. - `OFFLINE_ONLY` · required · Present as a constant. A presentation must not depend on the room's network. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · Prezi product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A single large scene with content placed spatially, Named viewpoints with an ordered path between them, Interpolation with capped rate and rotation, honouring reduced motion, Vector where possible so zooming stays sharp, TypeScript with local documents. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. - An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion.
# Delivery milestones · Prezi Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · A canvas and a path across it Content sits in space and a sequence of viewpoints moves through it. ### Steps 1. Store viewpoints, derive motion Recorded motion cannot be reordered, and reordering is constant. Files: `src/viewpoints.ts` 2. Make the path a reorderable list Restructuring a presentation is the normal case. Files: `src/path.ts` 3. Support exact backward navigation Going back should return to the same framing, not an approximation. Files: `src/navigate.ts` ### Done when - [ ] Viewpoints are a reorderable list - [ ] Reordering requires no motion rework - [ ] Backward navigation returns exactly - [ ] A viewpoint updates without affecting others ### Watch out - Recording camera movement as the author drags produces a path that cannot be reordered or adjusted without redoing everything, and presentations get restructured constantly. Store named viewpoints and derive the motion, so reordering is moving a list item. ## M2 · Motion with a ceiling No transition can move fast enough to make people ill. ### Steps 1. Cap zoom rate and rotation as constants Not settings. The person affected is not the one adjusting them. Files: `src/motion.ts`, `src/motion.test.ts` 2. Compute rates at authoring time So a bad path is a flag rather than a surprise during a talk. Files: `src/transitions.ts` 3. Keep long transitions smooth Rather than accelerating to cover distance in the same time. Files: `src/motion.ts` ### Done when - [ ] Transitions cannot exceed the caps - [ ] Over-cap paths are flagged at authoring - [ ] Caps are not runtime adjustable - [ ] Long transitions stay smooth ### Watch out - Leaving motion intensity as a setting means it gets increased for effect, and the person who suffers is in the audience rather than at the keyboard. Cap the rate and rotation as constants, and flag an authored transition that would exceed them so the author fixes the path rather than the limit. ## M3 · A version with no motion at all The presentation works as cuts and still makes sense. ### Steps 1. Replace transitions with cuts Not shorter transitions. Cuts. Files: `src/reduced.ts` 2. Make the reduced version reviewable A checked output, with the check recorded. Files: `src/review.ts` 3. Flag motion-dependent content If it only reads during the zoom, it does not survive the export either. Files: `src/analysis.ts` ### Done when - [ ] Reduced motion replaces transitions with cuts - [ ] The reduced version is reviewed and recorded - [ ] Motion-dependent content is flagged - [ ] Every viewpoint is legible on its own ### Watch out - Treating reduced motion as a degraded mode nobody tests produces a version where three points revealed by a zoom all appear at once and contradict each other, which is worse than the motion for the person who needed it off. Check the reduced-motion version explicitly and flag viewpoints whose content depends on the movement. ## M4 · Presenting without surprises The presentation runs on the machine and screen it will actually be given on. ### Steps 1. Run offline including fonts A missing font on the day changes every layout. Files: `src/present.ts` 2. Preview target aspect ratios Cropping is discovered in front of the audience otherwise. Files: `src/aspect.ts` 3. Survive a display disconnection It happens, and it should not lose your place. Files: `src/present.ts` ### Done when - [ ] The presentation runs fully offline - [ ] Other aspect ratios preview without cropping - [ ] Presenter view works across two displays - [ ] A display disconnection does not lose position ### Watch out - A presentation that reflows or reframes for a different aspect ratio will crop content out of a viewpoint on the room's projector, and it is discovered in front of the audience. Compute framing for the target aspect ratio and let the author preview it before the day. ## M5 · Exports that still make the argument (production only) The presentation survives being read rather than watched. ### Steps 1. Export viewpoints as a readable sequence Most of a presentation's life is being read, not watched. Files: `src/export.ts` 2. Keep text as text So it is searchable, selectable and readable by assistive tools. Files: `src/export.ts` 3. Review coherence without motion If the argument needed the zoom, it needed rewriting. Files: `src/review.ts` ### Done when - [ ] Static export gives one frame per viewpoint - [ ] Text remains text in exports - [ ] Coherence without motion is reviewed - [ ] Vector elements stay sharp ### Watch out - An export that only produces a video preserves the motion and loses everything else, and most of a presentation's life is spent being read afterwards by people who were not there. Export viewpoints as a readable sequence with the notes, and check that the argument survives the loss of the motion.
# Operations · Prezi ## Backup Presentations are documents and belong with your ordinary document backups. Embedded media should be inside the document rather than referenced, since a missing asset on presentation day is the failure that matters. ## Restore Restore and confirm fonts and media are embedded rather than referenced, since a restored presentation that reflows because a font is missing changes every viewpoint's framing. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring For an authoring tool the check is at authoring time: transitions exceeding the caps and viewpoints flagged as motion-dependent are both caught before anyone presents, which is the only useful moment. ## Incident checklist An audience member made ill is the failure this build exists to prevent, and it means the caps were too generous rather than that the software broke. Reviewing the caps is the response, not adjusting them upward. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Transitions are confirmed unable to exceed the motion caps - [ ] Caps are confirmed not runtime adjustable - [ ] The reduced-motion version is confirmed reviewed and coherent - [ ] The presentation is confirmed to run fully offline - [ ] A static export is confirmed to keep text as text ## Launch constraint Do not market omitted Prezi capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Presentation files. A presentation is a document. DOCUMENTS_DIR=~/Documents/presentations # Required. A constant in the transition path. Not adjustable at runtime. MAX_ZOOM_RATE=2.0 # Required. Rotation is the worst offender for nausea. Keep it small. MAX_ROTATION_DEGREES=15 # Required. Present as a constant. The person affected cannot leave the room. RESPECT_REDUCED_MOTION=always # Required. Previewed at authoring, because cropping is found in front of an audience. TARGET_ASPECT_RATIOS=16:9,16:10,4:3 # Required. Present as a constant. A presentation must not depend on the room's network. OFFLINE_ONLY=always
$ choose a build depth, inspect the files, then open the complete pack in your agent
Prezi: The shapes are easy; customers pay for low-friction editing, reliable exports, collaboration, and a canvas that never fights them.
xpresentation and enterprise controls
xproduction codecs, rendering speed, and media templates
xmultiplayer cursors and comments
xlarge template libraries
xhigh-fidelity import and export
Don't feel like building it? These folks already made it free.
no votes, no pay-to-list · just what's real
Prezi pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| basic | $0/user | $0/user | Up to 5 editable presentations; 500 AI credits; up to 10 talking points per AI presentation. |
| standard | — | $7/user | 500 AI credits; up to 10 talking points; privacy controls. |
| plus | — | $19/user | Unlimited AI presentation generation; desktop/offline app; PDF export and personal branding. |
| premium | — | $29/user | Unlimited AI presentation generation; Plus features; analytics and phone support. |
| edu plus | custom | — | Unlimited AI presentation generation; certified education email required. |
| edu pro | custom | — | Edu Plus plus analytics, exclusive support and advanced import integrations. |
| business | custom | — | Premium features plus centralized billing; teams with 10+ licences receive custom templates and branded designs. |
| edu teams | custom | — | Edu Plus features plus analytics and enhanced collaboration. |
free tier5 editable presentations; 500 AI credits; up to 10 talking points; content loses paid privacy controls
billingannual billing for published Standard, Plus and Premium rates; 14-day trial; education and team pricing is quote/check-out based
hidden costspaid plans auto-renew; after expiry content remains stored but cannot be edited or newly created until renewal or downgrade; team customization starts at 10 licences
verified 2026-08-13 · source ↗
Vibecode Prezi
Kinda. The core of Prezi is buildable in a weekend with the prompt on this page, but there are real gaps: presentation and enterprise controls, production codecs, rendering speed, and media templates. Read the honest list above before committing.
How much does Prezi cost?
Prezi's pricing is usage-based or varies by plan · The official pricing URL is recorded, but a stable current amount was not safely recoverable in this pass. Do not publish a number until rechecked..
What do I lose by replacing Prezi?
Honestly: presentation and enterprise controls; production codecs, rendering speed, and media templates; multiplayer cursors and comments; large template libraries; high-fidelity import and export. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Prezi?
Yes: Sozi (A real zooming presentation editor built around SVG canvases and camera paths; less collaborative, less glossy, and blessedly free of a monthly bill.) The prompt is for when you want it exactly your way.