Vibecode MagicSlides
track this build4 phases, 12 steps, beginner friendly0%An LLM that turns a topic or URL into an outline and renders a PPTX/PDF is a weekend build. What MagicSlides actually sells is the template library, the export fidelity, and the distribution: a Google Slides add-on and a browser extension already installed by millions. You can rebuild the core loop; you can't rebuild the polish or the install base overnight.
You are building a lean indie version of MagicSlides. 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 ===== # MagicSlides · indie build A deck generator whose two real problems are that a model asked to summarise will produce confident claims the source never made, and that generating a genuine presentation file means writing a format whose text layout is computed by the renderer rather than by you. 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 | | --- | --- | --- | | Extraction | Source parsing into a numbered block sequence | every generated line must cite the block it came from | | Generation | Structured output with a required citation per bullet | an uncited bullet is an invention and is rejected | | Layout | Templates with measured text fitting | the presentation format does not lay out text for you, it asks the renderer to | | Output | A real editable presentation file, not images | a deck you cannot edit afterwards is a picture of a deck | | Runtime | Python 3.12 | the document and presentation format libraries are here | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Python 3.12 or newer** · free - Why: Runs extraction, generation and file writing. - Get it: python.org or your package manager, then a virtual environment. - Verify: python3 --version prints 3.12 or higher - [ ] **A presentation file library** · free - Why: Writing the format by hand means implementing a specification whose text layout is computed by the renderer, which is the trap this build is about. - Get it: A maintained library for the presentation format, and a real presentation application to open the output in. - Verify: A trivial generated file opens without warnings in a real application - [ ] **A model that follows structured output reliably** · free locally; per-token if hosted - Why: Every bullet must carry a citation, and a model that returns prose instead of structure makes validation impossible. - Get it: Local or hosted, tested for whether it returns valid structured output ten times in a row for this task. - Verify: Ten generations produce parseable structured output with citations - [ ] **Four real source documents** · free - Why: Extraction breaks on the things real documents contain: a heavily structured report, an article with tables, a transcript, and something long enough that later sections get ignored. - Get it: Use documents you would genuinely turn into a deck. - Verify: All four parse into blocks with heading context - [ ] **A template with known box dimensions** · free - Why: Text fitting is measured against specific boxes at specific sizes, and a template whose dimensions you do not know cannot be fitted to. - Get it: Build or take a simple template and record every layout's box dimensions and fonts. - Verify: A written table gives box dimensions and font sizes per layout ## 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: - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. - 70+ polished templates and design presets - one-click Google Slides add-on and browser extension - reliable PPTX/PDF export fidelity - hosted sharing and no-watermark output - team and API tiers If one of those is essential to you, that is the reason to keep paying for MagicSlides, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · MagicSlides 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 slide decks generated from a document, where every bullet came from the document to replace MagicSlides. 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. ### Stack (fixed, do not substitute) - Extraction: Source parsing into a numbered block sequence · every generated line must cite the block it came from - Generation: Structured output with a required citation per bullet · an uncited bullet is an invention and is rejected - Layout: Templates with measured text fitting · the presentation format does not lay out text for you, it asks the renderer to - Output: A real editable presentation file, not images · a deck you cannot edit afterwards is a picture of a deck - Runtime: Python 3.12 · the document and presentation format libraries are here ### Data model (create this before Phase 1) - sources(id, kind, path_or_url, title, extracted_at) · kind is document, article or transcript - blocks(id, source_id, ordinal, text, heading_path) · the numbered sequence citations refer to - decks(id, source_id, template_id, created_at, validated) - slides(id, deck_id, ordinal, layout, title, notes) - bullets(id, slide_id, ordinal, text, cited_block_ids_json, verbatim) - fit_checks(slide_id, element, measured_width, measured_height, overflowed) · because overflow is invisible until someone presents - A bullet with no citation cannot be stored, which is enforced rather than validated afterwards. ### Phase 1 · The source, as numbered blocks Build: Parse documents, articles and transcripts into numbered blocks with their heading context. Preserve order and structure. Handle a source that is mostly tables or mostly dialogue, since both break naive paragraph splitting. Trap: Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. Done when: A document, an article and a transcript all parse into ordered blocks with heading context. A source that is mostly tables produces usable blocks rather than a wall of numbers. Block numbering is stable across re-parses of an unchanged source. A long source parses without losing its later sections. Do not build yet: No generation, layout or output. ### Phase 2 · Bullets that came from the document Build: Generate slides from numbered blocks, requiring a citation per bullet. Validate every citation resolves and reject the whole deck otherwise. Mark bullets that are verbatim distinctly from those that are paraphrased. Trap: A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. Done when: Every bullet cites blocks that resolve to real text. A crafted response citing a nonexistent block causes the deck to be rejected, tested against the validator directly. Verbatim and paraphrased bullets are distinguishable. A source with no content for a requested slide count produces fewer slides rather than invented ones. Do not build yet: No layout, templates or file output yet. ### Phase 3 · Text that fits on the slide Build: Measure text against the template's box dimensions at the template's font and size before committing a slide. Reduce content or split the slide rather than shrinking text indefinitely. Record what was measured. Trap: The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. Done when: No slide overflows when opened in a real presentation application, verified by opening a generated deck. Overflow is resolved by splitting or trimming rather than by shrinking text below a stated minimum. Measurements are recorded per slide. A very long bullet is split across slides rather than truncated. Do not build yet: No file output or images yet. ### Phase 4 · A file people can edit Build: Write a genuine presentation file with real text boxes, speaker notes carrying the citations, and template styling applied through the file's own mechanisms rather than by positioning everything absolutely. Trap: Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. Done when: The generated file opens in a real presentation application with editable text boxes. Speaker notes contain the citations so a reader can check any claim. Template styling survives opening and editing. A deck of forty slides generates in a reasonable time and opens without warnings. Do not build yet: No images or batch yet. ### Phase 5 · Images, and knowing what you are allowed to use Build: Add images from sources with a recorded licence, or generate them with the model and provenance recorded. Refuse to insert an image with no licence record. Keep the deck's full provenance exportable. Trap: Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck. Done when: An image cannot be inserted without a licence record, tested by attempting it. Generated images record the model and prompt as their provenance. The deck's provenance exports as a document listing every source block and every image licence. A deck with no suitable images generates without them rather than inserting arbitrary ones. Do not build yet: Nothing after this. ### Out of scope (and why) - Design quality comparable to a designer, which is what makes a deck persuasive and is not a generation problem. - Charts generated from data in the source, which requires understanding the data rather than the prose. - Live editing and collaboration, which is the presentation application's job. - Video and animated transitions, which the format supports and which almost never improve a deck. ### README must contain - That every bullet must cite a source block and an uncited one rejects the whole deck - That the tool produces fewer slides rather than padding to a requested count - That text is measured against the template box because autofit is an instruction, not a layout - That the output is a real editable file rather than images - That every image carries a licence record or is not inserted ===== AGENTS.md ===== # Agent instructions · MagicSlides indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Source parsing into a numbered block sequence, Structured output with a required citation per bullet, Templates with measured text fitting, A real editable presentation file, not images, Python 3.12. 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 - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. ===== BUILD_PLAN.md ===== # Build plan · MagicSlides A deck generator whose two real problems are that a model asked to summarise will produce confident claims the source never made, and that generating a genuine presentation file means writing a format whose text layout is computed by the renderer rather than by you. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The source, as numbered blocks A document becomes an ordered sequence you can cite into. ### Steps 1. Preserve the heading path per block Structure is what tells a deck what is subordinate to what. Files: `src/extract.py` 2. Handle tables and dialogue Both break paragraph splitting and both are common sources. Files: `src/blocks.py` 3. Make numbering stable Citations refer to numbers. Unstable numbering makes them meaningless. Files: `src/blocks.py`, `tests/test_stability.py` ### Done when - [ ] Three source kinds parse into ordered blocks - [ ] Heading context is preserved per block - [ ] Tables and dialogue produce usable blocks - [ ] Numbering is stable across re-parses ### Watch out - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. ## Phase 2 · Bullets that came from the document Every line on every slide traces to a block in the source. ### Steps 1. Require and validate citations A pure function over the block set, unit tested with a bad citation. Files: `src/generate.py`, `tests/test_citations.py` 2. Reject rather than dropping A deck with one invented slide silently removed is still untrustworthy. Files: `src/generate.py` 3. Refuse to pad to a slide count Fewer slides is the correct answer when the source is short. Files: `src/generate.py` ### Done when - [ ] Every bullet cites a resolvable block - [ ] A crafted bad citation rejects the deck - [ ] Verbatim and paraphrased are distinguishable - [ ] A thin source produces fewer slides, not invented ones ### Watch out - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. ## Phase 3 · Text that fits on the slide No slide overflows its box when someone actually opens it. ### Steps 1. Measure against the template box At the template's font and size. Autofit is an instruction, not a layout. Files: `src/fit.py` 2. Split or trim rather than shrink There is a size below which a slide is not a slide. Files: `src/fit.py` 3. Record the measurement So an overflow found later can be traced to what was measured. Files: `src/fit_checks.py` ### Done when - [ ] No slide overflows in a real application - [ ] Overflow splits or trims rather than shrinking - [ ] Measurements are recorded per slide - [ ] A long bullet splits rather than truncating ### Watch out - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. ## Phase 4 · A file people can edit The output opens as a real, editable deck in the application people use. ### Steps 1. Write real text elements Editable. Images are a picture of a deck, not a deck. Files: `src/write_pptx.py` 2. Put citations in the speaker notes Where they are available to the presenter and out of the audience's way. Files: `src/notes.py` 3. Apply styling through the format's own mechanisms Absolute positioning everything breaks the moment someone edits a slide. Files: `src/template.py` ### Done when - [ ] The file opens with editable text boxes - [ ] Speaker notes carry the citations - [ ] Styling survives editing - [ ] Forty slides generate and open without warnings ### Watch out - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. ## Not in this build - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. ## After v1, if you want it - Speaker notes written for delivery rather than only carrying citations - A revision pass that regenerates one slide without rebuilding the deck - Export to a plain outline, which is often what the user actually wanted ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Documents to turn into decks. Read only. SOURCE_DIR=./sources # Required. Generated presentation files and provenance documents. OUTPUT_DIR=./decks # Required. The template whose box dimensions text is measured against. TEMPLATE_PATH=./templates/standard.pptx # Required. Below this a slide is split rather than shrunk. There is a size that is not a slide. MIN_FONT_SIZE_PT=18 # Required. Zero means as many as the source supports. A requested count is a request to invent. MAX_SLIDES=0 # Required. Present as a constant so the answer is visible in configuration. There is no other value. REQUIRE_IMAGE_LICENCE=always
You are building a lean indie version of MagicSlides. 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 ===== # MagicSlides · indie build A deck generator whose two real problems are that a model asked to summarise will produce confident claims the source never made, and that generating a genuine presentation file means writing a format whose text layout is computed by the renderer rather than by you. 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 | | --- | --- | --- | | Extraction | Source parsing into a numbered block sequence | every generated line must cite the block it came from | | Generation | Structured output with a required citation per bullet | an uncited bullet is an invention and is rejected | | Layout | Templates with measured text fitting | the presentation format does not lay out text for you, it asks the renderer to | | Output | A real editable presentation file, not images | a deck you cannot edit afterwards is a picture of a deck | | Runtime | Python 3.12 | the document and presentation format libraries are here | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Python 3.12 or newer** · free - Why: Runs extraction, generation and file writing. - Get it: python.org or your package manager, then a virtual environment. - Verify: python3 --version prints 3.12 or higher - [ ] **A presentation file library** · free - Why: Writing the format by hand means implementing a specification whose text layout is computed by the renderer, which is the trap this build is about. - Get it: A maintained library for the presentation format, and a real presentation application to open the output in. - Verify: A trivial generated file opens without warnings in a real application - [ ] **A model that follows structured output reliably** · free locally; per-token if hosted - Why: Every bullet must carry a citation, and a model that returns prose instead of structure makes validation impossible. - Get it: Local or hosted, tested for whether it returns valid structured output ten times in a row for this task. - Verify: Ten generations produce parseable structured output with citations - [ ] **Four real source documents** · free - Why: Extraction breaks on the things real documents contain: a heavily structured report, an article with tables, a transcript, and something long enough that later sections get ignored. - Get it: Use documents you would genuinely turn into a deck. - Verify: All four parse into blocks with heading context - [ ] **A template with known box dimensions** · free - Why: Text fitting is measured against specific boxes at specific sizes, and a template whose dimensions you do not know cannot be fitted to. - Get it: Build or take a simple template and record every layout's box dimensions and fonts. - Verify: A written table gives box dimensions and font sizes per layout ## 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: - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. - 70+ polished templates and design presets - one-click Google Slides add-on and browser extension - reliable PPTX/PDF export fidelity - hosted sharing and no-watermark output - team and API tiers If one of those is essential to you, that is the reason to keep paying for MagicSlides, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · MagicSlides 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 slide decks generated from a document, where every bullet came from the document to replace MagicSlides. 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. ### Stack (fixed, do not substitute) - Extraction: Source parsing into a numbered block sequence · every generated line must cite the block it came from - Generation: Structured output with a required citation per bullet · an uncited bullet is an invention and is rejected - Layout: Templates with measured text fitting · the presentation format does not lay out text for you, it asks the renderer to - Output: A real editable presentation file, not images · a deck you cannot edit afterwards is a picture of a deck - Runtime: Python 3.12 · the document and presentation format libraries are here ### Data model (create this before Phase 1) - sources(id, kind, path_or_url, title, extracted_at) · kind is document, article or transcript - blocks(id, source_id, ordinal, text, heading_path) · the numbered sequence citations refer to - decks(id, source_id, template_id, created_at, validated) - slides(id, deck_id, ordinal, layout, title, notes) - bullets(id, slide_id, ordinal, text, cited_block_ids_json, verbatim) - fit_checks(slide_id, element, measured_width, measured_height, overflowed) · because overflow is invisible until someone presents - A bullet with no citation cannot be stored, which is enforced rather than validated afterwards. ### Phase 1 · The source, as numbered blocks Build: Parse documents, articles and transcripts into numbered blocks with their heading context. Preserve order and structure. Handle a source that is mostly tables or mostly dialogue, since both break naive paragraph splitting. Trap: Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. Done when: A document, an article and a transcript all parse into ordered blocks with heading context. A source that is mostly tables produces usable blocks rather than a wall of numbers. Block numbering is stable across re-parses of an unchanged source. A long source parses without losing its later sections. Do not build yet: No generation, layout or output. ### Phase 2 · Bullets that came from the document Build: Generate slides from numbered blocks, requiring a citation per bullet. Validate every citation resolves and reject the whole deck otherwise. Mark bullets that are verbatim distinctly from those that are paraphrased. Trap: A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. Done when: Every bullet cites blocks that resolve to real text. A crafted response citing a nonexistent block causes the deck to be rejected, tested against the validator directly. Verbatim and paraphrased bullets are distinguishable. A source with no content for a requested slide count produces fewer slides rather than invented ones. Do not build yet: No layout, templates or file output yet. ### Phase 3 · Text that fits on the slide Build: Measure text against the template's box dimensions at the template's font and size before committing a slide. Reduce content or split the slide rather than shrinking text indefinitely. Record what was measured. Trap: The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. Done when: No slide overflows when opened in a real presentation application, verified by opening a generated deck. Overflow is resolved by splitting or trimming rather than by shrinking text below a stated minimum. Measurements are recorded per slide. A very long bullet is split across slides rather than truncated. Do not build yet: No file output or images yet. ### Phase 4 · A file people can edit Build: Write a genuine presentation file with real text boxes, speaker notes carrying the citations, and template styling applied through the file's own mechanisms rather than by positioning everything absolutely. Trap: Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. Done when: The generated file opens in a real presentation application with editable text boxes. Speaker notes contain the citations so a reader can check any claim. Template styling survives opening and editing. A deck of forty slides generates in a reasonable time and opens without warnings. Do not build yet: No images or batch yet. ### Phase 5 · Images, and knowing what you are allowed to use Build: Add images from sources with a recorded licence, or generate them with the model and provenance recorded. Refuse to insert an image with no licence record. Keep the deck's full provenance exportable. Trap: Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck. Done when: An image cannot be inserted without a licence record, tested by attempting it. Generated images record the model and prompt as their provenance. The deck's provenance exports as a document listing every source block and every image licence. A deck with no suitable images generates without them rather than inserting arbitrary ones. Do not build yet: Nothing after this. ### Out of scope (and why) - Design quality comparable to a designer, which is what makes a deck persuasive and is not a generation problem. - Charts generated from data in the source, which requires understanding the data rather than the prose. - Live editing and collaboration, which is the presentation application's job. - Video and animated transitions, which the format supports and which almost never improve a deck. ### README must contain - That every bullet must cite a source block and an uncited one rejects the whole deck - That the tool produces fewer slides rather than padding to a requested count - That text is measured against the template box because autofit is an instruction, not a layout - That the output is a real editable file rather than images - That every image carries a licence record or is not inserted ===== AGENTS.md ===== # Agent instructions · MagicSlides indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Source parsing into a numbered block sequence, Structured output with a required citation per bullet, Templates with measured text fitting, A real editable presentation file, not images, Python 3.12. 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 - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. ===== BUILD_PLAN.md ===== # Build plan · MagicSlides A deck generator whose two real problems are that a model asked to summarise will produce confident claims the source never made, and that generating a genuine presentation file means writing a format whose text layout is computed by the renderer rather than by you. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The source, as numbered blocks A document becomes an ordered sequence you can cite into. ### Steps 1. Preserve the heading path per block Structure is what tells a deck what is subordinate to what. Files: `src/extract.py` 2. Handle tables and dialogue Both break paragraph splitting and both are common sources. Files: `src/blocks.py` 3. Make numbering stable Citations refer to numbers. Unstable numbering makes them meaningless. Files: `src/blocks.py`, `tests/test_stability.py` ### Done when - [ ] Three source kinds parse into ordered blocks - [ ] Heading context is preserved per block - [ ] Tables and dialogue produce usable blocks - [ ] Numbering is stable across re-parses ### Watch out - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. ## Phase 2 · Bullets that came from the document Every line on every slide traces to a block in the source. ### Steps 1. Require and validate citations A pure function over the block set, unit tested with a bad citation. Files: `src/generate.py`, `tests/test_citations.py` 2. Reject rather than dropping A deck with one invented slide silently removed is still untrustworthy. Files: `src/generate.py` 3. Refuse to pad to a slide count Fewer slides is the correct answer when the source is short. Files: `src/generate.py` ### Done when - [ ] Every bullet cites a resolvable block - [ ] A crafted bad citation rejects the deck - [ ] Verbatim and paraphrased are distinguishable - [ ] A thin source produces fewer slides, not invented ones ### Watch out - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. ## Phase 3 · Text that fits on the slide No slide overflows its box when someone actually opens it. ### Steps 1. Measure against the template box At the template's font and size. Autofit is an instruction, not a layout. Files: `src/fit.py` 2. Split or trim rather than shrink There is a size below which a slide is not a slide. Files: `src/fit.py` 3. Record the measurement So an overflow found later can be traced to what was measured. Files: `src/fit_checks.py` ### Done when - [ ] No slide overflows in a real application - [ ] Overflow splits or trims rather than shrinking - [ ] Measurements are recorded per slide - [ ] A long bullet splits rather than truncating ### Watch out - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. ## Phase 4 · A file people can edit The output opens as a real, editable deck in the application people use. ### Steps 1. Write real text elements Editable. Images are a picture of a deck, not a deck. Files: `src/write_pptx.py` 2. Put citations in the speaker notes Where they are available to the presenter and out of the audience's way. Files: `src/notes.py` 3. Apply styling through the format's own mechanisms Absolute positioning everything breaks the moment someone edits a slide. Files: `src/template.py` ### Done when - [ ] The file opens with editable text boxes - [ ] Speaker notes carry the citations - [ ] Styling survives editing - [ ] Forty slides generate and open without warnings ### Watch out - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. ## Not in this build - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. ## After v1, if you want it - Speaker notes written for delivery rather than only carrying citations - A revision pass that regenerates one slide without rebuilding the deck - Export to a plain outline, which is often what the user actually wanted ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Documents to turn into decks. Read only. SOURCE_DIR=./sources # Required. Generated presentation files and provenance documents. OUTPUT_DIR=./decks # Required. The template whose box dimensions text is measured against. TEMPLATE_PATH=./templates/standard.pptx # Required. Below this a slide is split rather than shrunk. There is a size that is not a slide. MIN_FONT_SIZE_PT=18 # Required. Zero means as many as the source supports. A requested count is a request to invent. MAX_SLIDES=0 # Required. Present as a constant so the answer is visible in configuration. There is no other value. REQUIRE_IMAGE_LICENCE=always
You are building a production product version of MagicSlides. 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 ===== # MagicSlides · product brief ## Problem An LLM that turns a topic or URL into an outline and renders a PPTX/PDF is a weekend build. What MagicSlides actually sells is the template library, the export fidelity, and the distribution: a Google Slides add-on and a browser extension already installed by millions. You can rebuild the core loop; you can't rebuild the polish or the install base overnight. ## Product outcome A deck generator that never puts a claim on a slide the source did not make, produces a file people can actually edit, and does not silently overflow its own text boxes. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - LLM API key - a slide/PPTX renderer - a template system - optional image API key - optional YouTube transcript fetch ## Explicit non-goals for v1 - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. - 70+ polished templates and design presets - one-click Google Slides add-on and browser extension - reliable PPTX/PDF export fidelity - hosted sharing and no-watermark output - team and API tiers ## Success criteria - A crafted bad citation is confirmed to reject the deck - A thin source is confirmed to produce fewer slides rather than invented ones - No slide is confirmed to overflow in a real application - The output is confirmed editable rather than images - An unlicensed image is confirmed impossible to insert ===== BRIEF.md ===== # Build brief · MagicSlides 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 slide decks generated from a document, where every bullet came from the document to replace MagicSlides. 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. ### Stack (fixed, do not substitute) - Extraction: Source parsing into a numbered block sequence · every generated line must cite the block it came from - Generation: Structured output with a required citation per bullet · an uncited bullet is an invention and is rejected - Layout: Templates with measured text fitting · the presentation format does not lay out text for you, it asks the renderer to - Output: A real editable presentation file, not images · a deck you cannot edit afterwards is a picture of a deck - Runtime: Python 3.12 · the document and presentation format libraries are here ### Data model (create this before Phase 1) - sources(id, kind, path_or_url, title, extracted_at) · kind is document, article or transcript - blocks(id, source_id, ordinal, text, heading_path) · the numbered sequence citations refer to - decks(id, source_id, template_id, created_at, validated) - slides(id, deck_id, ordinal, layout, title, notes) - bullets(id, slide_id, ordinal, text, cited_block_ids_json, verbatim) - fit_checks(slide_id, element, measured_width, measured_height, overflowed) · because overflow is invisible until someone presents - A bullet with no citation cannot be stored, which is enforced rather than validated afterwards. ### Phase 1 · The source, as numbered blocks Build: Parse documents, articles and transcripts into numbered blocks with their heading context. Preserve order and structure. Handle a source that is mostly tables or mostly dialogue, since both break naive paragraph splitting. Trap: Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. Done when: A document, an article and a transcript all parse into ordered blocks with heading context. A source that is mostly tables produces usable blocks rather than a wall of numbers. Block numbering is stable across re-parses of an unchanged source. A long source parses without losing its later sections. Do not build yet: No generation, layout or output. ### Phase 2 · Bullets that came from the document Build: Generate slides from numbered blocks, requiring a citation per bullet. Validate every citation resolves and reject the whole deck otherwise. Mark bullets that are verbatim distinctly from those that are paraphrased. Trap: A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. Done when: Every bullet cites blocks that resolve to real text. A crafted response citing a nonexistent block causes the deck to be rejected, tested against the validator directly. Verbatim and paraphrased bullets are distinguishable. A source with no content for a requested slide count produces fewer slides rather than invented ones. Do not build yet: No layout, templates or file output yet. ### Phase 3 · Text that fits on the slide Build: Measure text against the template's box dimensions at the template's font and size before committing a slide. Reduce content or split the slide rather than shrinking text indefinitely. Record what was measured. Trap: The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. Done when: No slide overflows when opened in a real presentation application, verified by opening a generated deck. Overflow is resolved by splitting or trimming rather than by shrinking text below a stated minimum. Measurements are recorded per slide. A very long bullet is split across slides rather than truncated. Do not build yet: No file output or images yet. ### Phase 4 · A file people can edit Build: Write a genuine presentation file with real text boxes, speaker notes carrying the citations, and template styling applied through the file's own mechanisms rather than by positioning everything absolutely. Trap: Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. Done when: The generated file opens in a real presentation application with editable text boxes. Speaker notes contain the citations so a reader can check any claim. Template styling survives opening and editing. A deck of forty slides generates in a reasonable time and opens without warnings. Do not build yet: No images or batch yet. ### Phase 5 · Images, and knowing what you are allowed to use Build: Add images from sources with a recorded licence, or generate them with the model and provenance recorded. Refuse to insert an image with no licence record. Keep the deck's full provenance exportable. Trap: Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck. Done when: An image cannot be inserted without a licence record, tested by attempting it. Generated images record the model and prompt as their provenance. The deck's provenance exports as a document listing every source block and every image licence. A deck with no suitable images generates without them rather than inserting arbitrary ones. Do not build yet: Nothing after this. ### Out of scope (and why) - Design quality comparable to a designer, which is what makes a deck persuasive and is not a generation problem. - Charts generated from data in the source, which requires understanding the data rather than the prose. - Live editing and collaboration, which is the presentation application's job. - Video and animated transitions, which the format supports and which almost never improve a deck. ### README must contain - That every bullet must cite a source block and an uncited one rejects the whole deck - That the tool produces fewer slides rather than padding to a requested count - That text is measured against the template box because autofit is an instruction, not a layout - That the output is a real editable file rather than images - That every image carries a licence record or is not inserted ===== ARCHITECTURE.md ===== # Architecture · MagicSlides ## Stack | Part | Choice | Why | | --- | --- | --- | | Extraction | Source parsing into a numbered block sequence | every generated line must cite the block it came from | | Generation | Structured output with a required citation per bullet | an uncited bullet is an invention and is rejected | | Layout | Templates with measured text fitting | the presentation format does not lay out text for you, it asks the renderer to | | Output | A real editable presentation file, not images | a deck you cannot edit afterwards is a picture of a deck | | Runtime | Python 3.12 | the document and presentation format libraries are here | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Extraction | Numbered blocks with heading context. | Any parser, provided numbering is stable since citations depend on it. | | Generation | Cited bullets and rejection on failure. | Any model, provided uncited output rejects the deck rather than being trimmed. | | Fitting | Measuring text against template boxes. | Any measurement, provided it does not rely on the format's autofit instruction. | | Writing | Real editable presentation files. | Any library. Rendering to images is the shortcut that makes the output useless. | | Images | Licence records and provenance. | Any source, provided a record exists before insertion. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `SOURCE_DIR` · required · Documents to turn into decks. Read only. - `OUTPUT_DIR` · required · Generated presentation files and provenance documents. - `TEMPLATE_PATH` · required · The template whose box dimensions text is measured against. - `MIN_FONT_SIZE_PT` · required · Below this a slide is split rather than shrunk. There is a size that is not a slide. - `MAX_SLIDES` · required · Zero means as many as the source supports. A requested count is a request to invent. - `REQUIRE_IMAGE_LICENCE` · required · Present as a constant so the answer is visible in configuration. There is no other value. ## 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 · MagicSlides product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: Source parsing into a numbered block sequence, Structured output with a required citation per bullet, Templates with measured text fitting, A real editable presentation file, not images, Python 3.12. - 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 - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. - Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck. ===== MILESTONES.md ===== # Delivery milestones · MagicSlides Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · The source, as numbered blocks A document becomes an ordered sequence you can cite into. ### Steps 1. Preserve the heading path per block Structure is what tells a deck what is subordinate to what. Files: `src/extract.py` 2. Handle tables and dialogue Both break paragraph splitting and both are common sources. Files: `src/blocks.py` 3. Make numbering stable Citations refer to numbers. Unstable numbering makes them meaningless. Files: `src/blocks.py`, `tests/test_stability.py` ### Done when - [ ] Three source kinds parse into ordered blocks - [ ] Heading context is preserved per block - [ ] Tables and dialogue produce usable blocks - [ ] Numbering is stable across re-parses ### Watch out - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. ## M2 · Bullets that came from the document Every line on every slide traces to a block in the source. ### Steps 1. Require and validate citations A pure function over the block set, unit tested with a bad citation. Files: `src/generate.py`, `tests/test_citations.py` 2. Reject rather than dropping A deck with one invented slide silently removed is still untrustworthy. Files: `src/generate.py` 3. Refuse to pad to a slide count Fewer slides is the correct answer when the source is short. Files: `src/generate.py` ### Done when - [ ] Every bullet cites a resolvable block - [ ] A crafted bad citation rejects the deck - [ ] Verbatim and paraphrased are distinguishable - [ ] A thin source produces fewer slides, not invented ones ### Watch out - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. ## M3 · Text that fits on the slide No slide overflows its box when someone actually opens it. ### Steps 1. Measure against the template box At the template's font and size. Autofit is an instruction, not a layout. Files: `src/fit.py` 2. Split or trim rather than shrink There is a size below which a slide is not a slide. Files: `src/fit.py` 3. Record the measurement So an overflow found later can be traced to what was measured. Files: `src/fit_checks.py` ### Done when - [ ] No slide overflows in a real application - [ ] Overflow splits or trims rather than shrinking - [ ] Measurements are recorded per slide - [ ] A long bullet splits rather than truncating ### Watch out - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. ## M4 · A file people can edit The output opens as a real, editable deck in the application people use. ### Steps 1. Write real text elements Editable. Images are a picture of a deck, not a deck. Files: `src/write_pptx.py` 2. Put citations in the speaker notes Where they are available to the presenter and out of the audience's way. Files: `src/notes.py` 3. Apply styling through the format's own mechanisms Absolute positioning everything breaks the moment someone edits a slide. Files: `src/template.py` ### Done when - [ ] The file opens with editable text boxes - [ ] Speaker notes carry the citations - [ ] Styling survives editing - [ ] Forty slides generate and open without warnings ### Watch out - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. ## M5 · Images, and knowing what you are allowed to use (production only) Illustrated slides use images you can account for. ### Steps 1. Require a licence record per image No record, no image. Enforced at insertion. Files: `src/images.py` 2. Record generated image provenance Model and prompt. It is a different licence question, not an absent one. Files: `src/images.py` 3. Export the deck's full provenance Blocks cited and image licences, as one document. Files: `src/provenance.py` ### Done when - [ ] An unlicensed image cannot be inserted - [ ] Generated images record model and prompt - [ ] Provenance exports as a complete document - [ ] A deck without suitable images omits them ### Watch out - Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck. ===== OPERATIONS.md ===== # Operations · MagicSlides ## Backup Source documents are yours already. Decks regenerate from sources plus the template, so back up the provenance records, since those are what let you defend a claim on a slide months later. ## Restore Restore sources and regenerate, comparing against a kept deck. Differences point at model non-determinism rather than at a restore problem, which is worth knowing before you rely on regeneration. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Citation validation failure rate is the metric that matters. A rising rate means the model is drifting toward invention, usually after a model or prompt change. ## Incident checklist A slide making a claim the source did not contain is the failure this exists to prevent, and it means validation passed something it should not have. The block set and the citation are both recorded, so the case is reproducible. 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 - [ ] A crafted bad citation is confirmed to reject the deck - [ ] A thin source is confirmed to produce fewer slides rather than invented ones - [ ] No slide is confirmed to overflow in a real application - [ ] The output is confirmed editable rather than images - [ ] An unlicensed image is confirmed impossible to insert ## Launch constraint Do not market omitted MagicSlides 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. Documents to turn into decks. Read only. SOURCE_DIR=./sources # Required. Generated presentation files and provenance documents. OUTPUT_DIR=./decks # Required. The template whose box dimensions text is measured against. TEMPLATE_PATH=./templates/standard.pptx # Required. Below this a slide is split rather than shrunk. There is a size that is not a slide. MIN_FONT_SIZE_PT=18 # Required. Zero means as many as the source supports. A requested count is a request to invent. MAX_SLIDES=0 # Required. Present as a constant so the answer is visible in configuration. There is no other value. REQUIRE_IMAGE_LICENCE=always
# MagicSlides · indie build A deck generator whose two real problems are that a model asked to summarise will produce confident claims the source never made, and that generating a genuine presentation file means writing a format whose text layout is computed by the renderer rather than by you. 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 | | --- | --- | --- | | Extraction | Source parsing into a numbered block sequence | every generated line must cite the block it came from | | Generation | Structured output with a required citation per bullet | an uncited bullet is an invention and is rejected | | Layout | Templates with measured text fitting | the presentation format does not lay out text for you, it asks the renderer to | | Output | A real editable presentation file, not images | a deck you cannot edit afterwards is a picture of a deck | | Runtime | Python 3.12 | the document and presentation format libraries are here | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Python 3.12 or newer** · free - Why: Runs extraction, generation and file writing. - Get it: python.org or your package manager, then a virtual environment. - Verify: python3 --version prints 3.12 or higher - [ ] **A presentation file library** · free - Why: Writing the format by hand means implementing a specification whose text layout is computed by the renderer, which is the trap this build is about. - Get it: A maintained library for the presentation format, and a real presentation application to open the output in. - Verify: A trivial generated file opens without warnings in a real application - [ ] **A model that follows structured output reliably** · free locally; per-token if hosted - Why: Every bullet must carry a citation, and a model that returns prose instead of structure makes validation impossible. - Get it: Local or hosted, tested for whether it returns valid structured output ten times in a row for this task. - Verify: Ten generations produce parseable structured output with citations - [ ] **Four real source documents** · free - Why: Extraction breaks on the things real documents contain: a heavily structured report, an article with tables, a transcript, and something long enough that later sections get ignored. - Get it: Use documents you would genuinely turn into a deck. - Verify: All four parse into blocks with heading context - [ ] **A template with known box dimensions** · free - Why: Text fitting is measured against specific boxes at specific sizes, and a template whose dimensions you do not know cannot be fitted to. - Get it: Build or take a simple template and record every layout's box dimensions and fonts. - Verify: A written table gives box dimensions and font sizes per layout ## 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: - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. - 70+ polished templates and design presets - one-click Google Slides add-on and browser extension - reliable PPTX/PDF export fidelity - hosted sharing and no-watermark output - team and API tiers If one of those is essential to you, that is the reason to keep paying for MagicSlides, and the README should say so rather than pretend.
# Build brief · MagicSlides 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 slide decks generated from a document, where every bullet came from the document to replace MagicSlides. 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. ### Stack (fixed, do not substitute) - Extraction: Source parsing into a numbered block sequence · every generated line must cite the block it came from - Generation: Structured output with a required citation per bullet · an uncited bullet is an invention and is rejected - Layout: Templates with measured text fitting · the presentation format does not lay out text for you, it asks the renderer to - Output: A real editable presentation file, not images · a deck you cannot edit afterwards is a picture of a deck - Runtime: Python 3.12 · the document and presentation format libraries are here ### Data model (create this before Phase 1) - sources(id, kind, path_or_url, title, extracted_at) · kind is document, article or transcript - blocks(id, source_id, ordinal, text, heading_path) · the numbered sequence citations refer to - decks(id, source_id, template_id, created_at, validated) - slides(id, deck_id, ordinal, layout, title, notes) - bullets(id, slide_id, ordinal, text, cited_block_ids_json, verbatim) - fit_checks(slide_id, element, measured_width, measured_height, overflowed) · because overflow is invisible until someone presents - A bullet with no citation cannot be stored, which is enforced rather than validated afterwards. ### Phase 1 · The source, as numbered blocks Build: Parse documents, articles and transcripts into numbered blocks with their heading context. Preserve order and structure. Handle a source that is mostly tables or mostly dialogue, since both break naive paragraph splitting. Trap: Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. Done when: A document, an article and a transcript all parse into ordered blocks with heading context. A source that is mostly tables produces usable blocks rather than a wall of numbers. Block numbering is stable across re-parses of an unchanged source. A long source parses without losing its later sections. Do not build yet: No generation, layout or output. ### Phase 2 · Bullets that came from the document Build: Generate slides from numbered blocks, requiring a citation per bullet. Validate every citation resolves and reject the whole deck otherwise. Mark bullets that are verbatim distinctly from those that are paraphrased. Trap: A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. Done when: Every bullet cites blocks that resolve to real text. A crafted response citing a nonexistent block causes the deck to be rejected, tested against the validator directly. Verbatim and paraphrased bullets are distinguishable. A source with no content for a requested slide count produces fewer slides rather than invented ones. Do not build yet: No layout, templates or file output yet. ### Phase 3 · Text that fits on the slide Build: Measure text against the template's box dimensions at the template's font and size before committing a slide. Reduce content or split the slide rather than shrinking text indefinitely. Record what was measured. Trap: The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. Done when: No slide overflows when opened in a real presentation application, verified by opening a generated deck. Overflow is resolved by splitting or trimming rather than by shrinking text below a stated minimum. Measurements are recorded per slide. A very long bullet is split across slides rather than truncated. Do not build yet: No file output or images yet. ### Phase 4 · A file people can edit Build: Write a genuine presentation file with real text boxes, speaker notes carrying the citations, and template styling applied through the file's own mechanisms rather than by positioning everything absolutely. Trap: Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. Done when: The generated file opens in a real presentation application with editable text boxes. Speaker notes contain the citations so a reader can check any claim. Template styling survives opening and editing. A deck of forty slides generates in a reasonable time and opens without warnings. Do not build yet: No images or batch yet. ### Phase 5 · Images, and knowing what you are allowed to use Build: Add images from sources with a recorded licence, or generate them with the model and provenance recorded. Refuse to insert an image with no licence record. Keep the deck's full provenance exportable. Trap: Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck. Done when: An image cannot be inserted without a licence record, tested by attempting it. Generated images record the model and prompt as their provenance. The deck's provenance exports as a document listing every source block and every image licence. A deck with no suitable images generates without them rather than inserting arbitrary ones. Do not build yet: Nothing after this. ### Out of scope (and why) - Design quality comparable to a designer, which is what makes a deck persuasive and is not a generation problem. - Charts generated from data in the source, which requires understanding the data rather than the prose. - Live editing and collaboration, which is the presentation application's job. - Video and animated transitions, which the format supports and which almost never improve a deck. ### README must contain - That every bullet must cite a source block and an uncited one rejects the whole deck - That the tool produces fewer slides rather than padding to a requested count - That text is measured against the template box because autofit is an instruction, not a layout - That the output is a real editable file rather than images - That every image carries a licence record or is not inserted
# Agent instructions · MagicSlides indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Source parsing into a numbered block sequence, Structured output with a required citation per bullet, Templates with measured text fitting, A real editable presentation file, not images, Python 3.12. 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 - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications.
# Build plan · MagicSlides A deck generator whose two real problems are that a model asked to summarise will produce confident claims the source never made, and that generating a genuine presentation file means writing a format whose text layout is computed by the renderer rather than by you. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The source, as numbered blocks A document becomes an ordered sequence you can cite into. ### Steps 1. Preserve the heading path per block Structure is what tells a deck what is subordinate to what. Files: `src/extract.py` 2. Handle tables and dialogue Both break paragraph splitting and both are common sources. Files: `src/blocks.py` 3. Make numbering stable Citations refer to numbers. Unstable numbering makes them meaningless. Files: `src/blocks.py`, `tests/test_stability.py` ### Done when - [ ] Three source kinds parse into ordered blocks - [ ] Heading context is preserved per block - [ ] Tables and dialogue produce usable blocks - [ ] Numbering is stable across re-parses ### Watch out - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. ## Phase 2 · Bullets that came from the document Every line on every slide traces to a block in the source. ### Steps 1. Require and validate citations A pure function over the block set, unit tested with a bad citation. Files: `src/generate.py`, `tests/test_citations.py` 2. Reject rather than dropping A deck with one invented slide silently removed is still untrustworthy. Files: `src/generate.py` 3. Refuse to pad to a slide count Fewer slides is the correct answer when the source is short. Files: `src/generate.py` ### Done when - [ ] Every bullet cites a resolvable block - [ ] A crafted bad citation rejects the deck - [ ] Verbatim and paraphrased are distinguishable - [ ] A thin source produces fewer slides, not invented ones ### Watch out - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. ## Phase 3 · Text that fits on the slide No slide overflows its box when someone actually opens it. ### Steps 1. Measure against the template box At the template's font and size. Autofit is an instruction, not a layout. Files: `src/fit.py` 2. Split or trim rather than shrink There is a size below which a slide is not a slide. Files: `src/fit.py` 3. Record the measurement So an overflow found later can be traced to what was measured. Files: `src/fit_checks.py` ### Done when - [ ] No slide overflows in a real application - [ ] Overflow splits or trims rather than shrinking - [ ] Measurements are recorded per slide - [ ] A long bullet splits rather than truncating ### Watch out - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. ## Phase 4 · A file people can edit The output opens as a real, editable deck in the application people use. ### Steps 1. Write real text elements Editable. Images are a picture of a deck, not a deck. Files: `src/write_pptx.py` 2. Put citations in the speaker notes Where they are available to the presenter and out of the audience's way. Files: `src/notes.py` 3. Apply styling through the format's own mechanisms Absolute positioning everything breaks the moment someone edits a slide. Files: `src/template.py` ### Done when - [ ] The file opens with editable text boxes - [ ] Speaker notes carry the citations - [ ] Styling survives editing - [ ] Forty slides generate and open without warnings ### Watch out - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. ## Not in this build - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. ## After v1, if you want it - Speaker notes written for delivery rather than only carrying citations - A revision pass that regenerates one slide without rebuilding the deck - Export to a plain outline, which is often what the user actually wanted
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Documents to turn into decks. Read only. SOURCE_DIR=./sources # Required. Generated presentation files and provenance documents. OUTPUT_DIR=./decks # Required. The template whose box dimensions text is measured against. TEMPLATE_PATH=./templates/standard.pptx # Required. Below this a slide is split rather than shrunk. There is a size that is not a slide. MIN_FONT_SIZE_PT=18 # Required. Zero means as many as the source supports. A requested count is a request to invent. MAX_SLIDES=0 # Required. Present as a constant so the answer is visible in configuration. There is no other value. REQUIRE_IMAGE_LICENCE=always
# MagicSlides · product brief ## Problem An LLM that turns a topic or URL into an outline and renders a PPTX/PDF is a weekend build. What MagicSlides actually sells is the template library, the export fidelity, and the distribution: a Google Slides add-on and a browser extension already installed by millions. You can rebuild the core loop; you can't rebuild the polish or the install base overnight. ## Product outcome A deck generator that never puts a claim on a slide the source did not make, produces a file people can actually edit, and does not silently overflow its own text boxes. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - LLM API key - a slide/PPTX renderer - a template system - optional image API key - optional YouTube transcript fetch ## Explicit non-goals for v1 - Design quality comparable to a designer. - Charts generated from data in the source. - Live editing and collaboration. - Video and animated transitions. - 70+ polished templates and design presets - one-click Google Slides add-on and browser extension - reliable PPTX/PDF export fidelity - hosted sharing and no-watermark output - team and API tiers ## Success criteria - A crafted bad citation is confirmed to reject the deck - A thin source is confirmed to produce fewer slides rather than invented ones - No slide is confirmed to overflow in a real application - The output is confirmed editable rather than images - An unlicensed image is confirmed impossible to insert
# Build brief · MagicSlides 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 slide decks generated from a document, where every bullet came from the document to replace MagicSlides. 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. ### Stack (fixed, do not substitute) - Extraction: Source parsing into a numbered block sequence · every generated line must cite the block it came from - Generation: Structured output with a required citation per bullet · an uncited bullet is an invention and is rejected - Layout: Templates with measured text fitting · the presentation format does not lay out text for you, it asks the renderer to - Output: A real editable presentation file, not images · a deck you cannot edit afterwards is a picture of a deck - Runtime: Python 3.12 · the document and presentation format libraries are here ### Data model (create this before Phase 1) - sources(id, kind, path_or_url, title, extracted_at) · kind is document, article or transcript - blocks(id, source_id, ordinal, text, heading_path) · the numbered sequence citations refer to - decks(id, source_id, template_id, created_at, validated) - slides(id, deck_id, ordinal, layout, title, notes) - bullets(id, slide_id, ordinal, text, cited_block_ids_json, verbatim) - fit_checks(slide_id, element, measured_width, measured_height, overflowed) · because overflow is invisible until someone presents - A bullet with no citation cannot be stored, which is enforced rather than validated afterwards. ### Phase 1 · The source, as numbered blocks Build: Parse documents, articles and transcripts into numbered blocks with their heading context. Preserve order and structure. Handle a source that is mostly tables or mostly dialogue, since both break naive paragraph splitting. Trap: Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. Done when: A document, an article and a transcript all parse into ordered blocks with heading context. A source that is mostly tables produces usable blocks rather than a wall of numbers. Block numbering is stable across re-parses of an unchanged source. A long source parses without losing its later sections. Do not build yet: No generation, layout or output. ### Phase 2 · Bullets that came from the document Build: Generate slides from numbered blocks, requiring a citation per bullet. Validate every citation resolves and reject the whole deck otherwise. Mark bullets that are verbatim distinctly from those that are paraphrased. Trap: A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. Done when: Every bullet cites blocks that resolve to real text. A crafted response citing a nonexistent block causes the deck to be rejected, tested against the validator directly. Verbatim and paraphrased bullets are distinguishable. A source with no content for a requested slide count produces fewer slides rather than invented ones. Do not build yet: No layout, templates or file output yet. ### Phase 3 · Text that fits on the slide Build: Measure text against the template's box dimensions at the template's font and size before committing a slide. Reduce content or split the slide rather than shrinking text indefinitely. Record what was measured. Trap: The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. Done when: No slide overflows when opened in a real presentation application, verified by opening a generated deck. Overflow is resolved by splitting or trimming rather than by shrinking text below a stated minimum. Measurements are recorded per slide. A very long bullet is split across slides rather than truncated. Do not build yet: No file output or images yet. ### Phase 4 · A file people can edit Build: Write a genuine presentation file with real text boxes, speaker notes carrying the citations, and template styling applied through the file's own mechanisms rather than by positioning everything absolutely. Trap: Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. Done when: The generated file opens in a real presentation application with editable text boxes. Speaker notes contain the citations so a reader can check any claim. Template styling survives opening and editing. A deck of forty slides generates in a reasonable time and opens without warnings. Do not build yet: No images or batch yet. ### Phase 5 · Images, and knowing what you are allowed to use Build: Add images from sources with a recorded licence, or generate them with the model and provenance recorded. Refuse to insert an image with no licence record. Keep the deck's full provenance exportable. Trap: Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck. Done when: An image cannot be inserted without a licence record, tested by attempting it. Generated images record the model and prompt as their provenance. The deck's provenance exports as a document listing every source block and every image licence. A deck with no suitable images generates without them rather than inserting arbitrary ones. Do not build yet: Nothing after this. ### Out of scope (and why) - Design quality comparable to a designer, which is what makes a deck persuasive and is not a generation problem. - Charts generated from data in the source, which requires understanding the data rather than the prose. - Live editing and collaboration, which is the presentation application's job. - Video and animated transitions, which the format supports and which almost never improve a deck. ### README must contain - That every bullet must cite a source block and an uncited one rejects the whole deck - That the tool produces fewer slides rather than padding to a requested count - That text is measured against the template box because autofit is an instruction, not a layout - That the output is a real editable file rather than images - That every image carries a licence record or is not inserted
# Architecture · MagicSlides ## Stack | Part | Choice | Why | | --- | --- | --- | | Extraction | Source parsing into a numbered block sequence | every generated line must cite the block it came from | | Generation | Structured output with a required citation per bullet | an uncited bullet is an invention and is rejected | | Layout | Templates with measured text fitting | the presentation format does not lay out text for you, it asks the renderer to | | Output | A real editable presentation file, not images | a deck you cannot edit afterwards is a picture of a deck | | Runtime | Python 3.12 | the document and presentation format libraries are here | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Extraction | Numbered blocks with heading context. | Any parser, provided numbering is stable since citations depend on it. | | Generation | Cited bullets and rejection on failure. | Any model, provided uncited output rejects the deck rather than being trimmed. | | Fitting | Measuring text against template boxes. | Any measurement, provided it does not rely on the format's autofit instruction. | | Writing | Real editable presentation files. | Any library. Rendering to images is the shortcut that makes the output useless. | | Images | Licence records and provenance. | Any source, provided a record exists before insertion. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `SOURCE_DIR` · required · Documents to turn into decks. Read only. - `OUTPUT_DIR` · required · Generated presentation files and provenance documents. - `TEMPLATE_PATH` · required · The template whose box dimensions text is measured against. - `MIN_FONT_SIZE_PT` · required · Below this a slide is split rather than shrunk. There is a size that is not a slide. - `MAX_SLIDES` · required · Zero means as many as the source supports. A requested count is a request to invent. - `REQUIRE_IMAGE_LICENCE` · required · Present as a constant so the answer is visible in configuration. There is no other value. ## 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 · MagicSlides product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: Source parsing into a numbered block sequence, Structured output with a required citation per bullet, Templates with measured text fitting, A real editable presentation file, not images, Python 3.12. - 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 - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. - Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck.
# Delivery milestones · MagicSlides Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · The source, as numbered blocks A document becomes an ordered sequence you can cite into. ### Steps 1. Preserve the heading path per block Structure is what tells a deck what is subordinate to what. Files: `src/extract.py` 2. Handle tables and dialogue Both break paragraph splitting and both are common sources. Files: `src/blocks.py` 3. Make numbering stable Citations refer to numbers. Unstable numbering makes them meaningless. Files: `src/blocks.py`, `tests/test_stability.py` ### Done when - [ ] Three source kinds parse into ordered blocks - [ ] Heading context is preserved per block - [ ] Tables and dialogue produce usable blocks - [ ] Numbering is stable across re-parses ### Watch out - Flattening a document to plain text loses the heading hierarchy, and without it a generated deck has no idea which points were subordinate to which, so it produces a flat list of facts in the order they happened to appear. Keep the heading path with every block. ## M2 · Bullets that came from the document Every line on every slide traces to a block in the source. ### Steps 1. Require and validate citations A pure function over the block set, unit tested with a bad citation. Files: `src/generate.py`, `tests/test_citations.py` 2. Reject rather than dropping A deck with one invented slide silently removed is still untrustworthy. Files: `src/generate.py` 3. Refuse to pad to a slide count Fewer slides is the correct answer when the source is short. Files: `src/generate.py` ### Done when - [ ] Every bullet cites a resolvable block - [ ] A crafted bad citation rejects the deck - [ ] Verbatim and paraphrased are distinguishable - [ ] A thin source produces fewer slides, not invented ones ### Watch out - A model asked to make a document into a presentation will produce the summary slide it thinks a deck needs, including figures and conclusions the document never contained, and those slides are the most confident-looking ones in the deck. Require a citation per bullet, validate it, and reject rather than dropping the offending line, since a partially invented deck is worse than none. ## M3 · Text that fits on the slide No slide overflows its box when someone actually opens it. ### Steps 1. Measure against the template box At the template's font and size. Autofit is an instruction, not a layout. Files: `src/fit.py` 2. Split or trim rather than shrink There is a size below which a slide is not a slide. Files: `src/fit.py` 3. Record the measurement So an overflow found later can be traced to what was measured. Files: `src/fit_checks.py` ### Done when - [ ] No slide overflows in a real application - [ ] Overflow splits or trims rather than shrinking - [ ] Measurements are recorded per slide - [ ] A long bullet splits rather than truncating ### Watch out - The presentation format stores an instruction to autofit rather than the resulting layout, so the file looks correct to your code and overflows or shrinks to an unreadable size when opened in the actual application. Measure the text yourself against the box, and treat overflow as a generation problem rather than a rendering one. ## M4 · A file people can edit The output opens as a real, editable deck in the application people use. ### Steps 1. Write real text elements Editable. Images are a picture of a deck, not a deck. Files: `src/write_pptx.py` 2. Put citations in the speaker notes Where they are available to the presenter and out of the audience's way. Files: `src/notes.py` 3. Apply styling through the format's own mechanisms Absolute positioning everything breaks the moment someone edits a slide. Files: `src/template.py` ### Done when - [ ] The file opens with editable text boxes - [ ] Speaker notes carry the citations - [ ] Styling survives editing - [ ] Forty slides generate and open without warnings ### Watch out - Generating slides as images guarantees they look exactly as intended and makes them completely uneditable, which is the first thing every user needs to do. Write real text elements, and accept that they will render slightly differently in different applications. ## M5 · Images, and knowing what you are allowed to use (production only) Illustrated slides use images you can account for. ### Steps 1. Require a licence record per image No record, no image. Enforced at insertion. Files: `src/images.py` 2. Record generated image provenance Model and prompt. It is a different licence question, not an absent one. Files: `src/images.py` 3. Export the deck's full provenance Blocks cited and image licences, as one document. Files: `src/provenance.py` ### Done when - [ ] An unlicensed image cannot be inserted - [ ] Generated images record model and prompt - [ ] Provenance exports as a complete document - [ ] A deck without suitable images omits them ### Watch out - Pulling an illustrative image from a search result puts an unlicensed photograph into a deck that may be presented to customers or published, and nobody in the room will know where it came from. Every image carries a licence record or it does not go in, and the record travels with the deck.
# Operations · MagicSlides ## Backup Source documents are yours already. Decks regenerate from sources plus the template, so back up the provenance records, since those are what let you defend a claim on a slide months later. ## Restore Restore sources and regenerate, comparing against a kept deck. Differences point at model non-determinism rather than at a restore problem, which is worth knowing before you rely on regeneration. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Citation validation failure rate is the metric that matters. A rising rate means the model is drifting toward invention, usually after a model or prompt change. ## Incident checklist A slide making a claim the source did not contain is the failure this exists to prevent, and it means validation passed something it should not have. The block set and the citation are both recorded, so the case is reproducible. 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 - [ ] A crafted bad citation is confirmed to reject the deck - [ ] A thin source is confirmed to produce fewer slides rather than invented ones - [ ] No slide is confirmed to overflow in a real application - [ ] The output is confirmed editable rather than images - [ ] An unlicensed image is confirmed impossible to insert ## Launch constraint Do not market omitted MagicSlides 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. Documents to turn into decks. Read only. SOURCE_DIR=./sources # Required. Generated presentation files and provenance documents. OUTPUT_DIR=./decks # Required. The template whose box dimensions text is measured against. TEMPLATE_PATH=./templates/standard.pptx # Required. Below this a slide is split rather than shrunk. There is a size that is not a slide. MIN_FONT_SIZE_PT=18 # Required. Zero means as many as the source supports. A requested count is a request to invent. MAX_SLIDES=0 # Required. Present as a constant so the answer is visible in configuration. There is no other value. REQUIRE_IMAGE_LICENCE=always
$ choose a build depth, inspect the files, then open the complete pack in your agent
People pay because it drops into Google Slides and their browser where they already work, and the output looks presentable without opening PowerPoint. The AI is commodity; the template quality and the frictionless install are what they are actually buying.
x70+ polished templates and design presets
xone-click Google Slides add-on and browser extension
xreliable PPTX/PDF export fidelity
xhosted sharing and no-watermark output
xteam and API tiers
MagicSlides pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| premium | $29/user | — | $29 of model credits/month; 70+ templates; 150+ design systems; decks of 50+ slides. |
| premium plus | $34/user | — | $34 of model credits/month; 70+ templates; 150+ design systems; decks of 50+ slides; face-image and HTML Studio features. |
| team & enterprise | custom | — | Invoice billing and centralized purchasing; numeric credit, seat and usage caps are not published. |
| done by us | custom | — | 1 presentation delivered in 48–72 hours. |
free tierno permanent free tier verified
billingmonthly + annual for Premium tiers; annual advertised at 17% off; Done By Us is a one-time purchase
hidden costslicense is tied to one Google account; model-credit consumption can exceed the included monthly amount; API access is a separately priced product
verified 2026-08-13 · source ↗
Vibecode MagicSlides
Kinda. The core of MagicSlides is buildable in a weekend with the prompt on this page, but there are real gaps: 70+ polished templates and design presets, one-click Google Slides add-on and browser extension. Read the honest list above before committing.
How much does MagicSlides cost?
MagicSlides costs about $29/month (Premium, checked 2026-08-13), which is $348 per year.
What do I lose by replacing MagicSlides?
Honestly: 70+ polished templates and design presets; one-click Google Slides add-on and browser extension; reliable PPTX/PDF export fidelity; hosted sharing and no-watermark output; team and API tiers. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to MagicSlides?
Yes: Slidev (Open-source Markdown/HTML slide deck framework, a strong base for a generator), Marp (Markdown-to-slides ecosystem with PPTX/PDF export). Using prior art is also vibecoding; the prompt is for when you want it exactly your way.