Skip to content

Latest commit

 

History

988 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Presentation Forge

Presentation Forge logo

A topic goes in. A themed deck and a graded report come out.
Local-first presentation and report generation for academic work.

MIT license Node.js 24 or newer 34 themes 74 slide types Automated test suite Local-first

Glassmorphism — a frosted plate, rendered in Chrome Swiss International — a dense KPI slide
Stats slide in the Glassmorphism theme, on a frosted glass plate KPI dashboard slide in the Swiss International theme

Every image in this README is a real render from the repository, produced by the same code path a generated deck goes through — not a mockup. The left one is a plate: a background Chrome renders as an image because PowerPoint cannot draw frosted glass, with the text still native and editable on top of it.

A real briefing session — topic → choices → optional thesis
Presentation Forge accepting a presentation topic, asking for deck choices, and opening optional thesis and audience questions

Captured from a fresh private Docker install. The session enters a real topic, chooses presentation settings, and opens the actual optional-detail questions. It stops before generation because no model was available; it does not pretend a deck was produced. Download the MP4.

A real local app session — project workspace → slide viewer
Presentation Forge opening the public Green Hydrogen deck, then showing its editable first PowerPoint slide

Captured from the local Docker bundle using the public Green Hydrogen deck in this repository. It shows opening and inspecting existing work, not a fabricated live-generation run. Download the MP4.

Run it locally

Install Docker, then:

git clone https://github.com/Deepnar/presentation-forge.git
cd presentation-forge
docker compose up -d --build --wait

Open http://localhost:8090. The first visit creates one local owner and signs you in; after that, public signup is closed. There is no email verification, Google login or password-reset ceremony in this private-machine mode.

Forge and its private SearXNG research service now run. To generate, choose one of two model paths:

  • Bring your own key: add an OpenAI-compatible provider under Settings → Cloud. Only model requests go to that provider. Forge starts with a 180,000-token rolling 24-hour safety budget, caps each BYOK response at 12,000 tokens, and allows at most one transport retry; the key owner can change the daily guard in Profile. Your provider bills your account directly, so also set a hard spending limit in its dashboard.
  • Keep inference local: install Ollama, run ollama pull qwen3:4b, and leave Forge on Auto. This is a lightweight starting model; use a stronger model or BYOK when output quality matters.
# Optional install check; Node runs inside the container.
docker compose exec forge env FORGE_CHECK_URL=http://localhost:5174 node tools/local-check.mjs

Windows and macOS work through Docker Desktop. Linux may need Ollama exposed to Docker's host gateway when using local inference. LOCAL_SETUP.md has that command, platform notes, data locations and troubleshooting. This private bundle binds only to localhost; use docs/DEPLOY.md for an internet-facing multi-user service.


The rule that makes it work

The model never writes layout. Asking a language model for coordinates and font sizes fails the moment content changes length. So it cannot express them:

Layer Owns Written by
chrome crest, banner, presenter line, slide number locked code in src/chrome.js
theme palette, type, spacing, shape human-authored themes/*.yaml
content what the slides say the model, as schema-validated YAML

The model picks a semantic slide type and writes its content. It cannot supply a coordinate, a hex value, or a font name — those keys do not exist in the schema it is decoding against.

Which is what makes this possible. The same slide, same words, four themes:

One slide, four themes — 6-second loop
The same statistics slide cycling through Swiss International, Neubrutalism, Editorial Magazine, and Sci-Fi HUD themes

This is a real render loop, not a product simulation. Nothing in the content changes between frames; switching theme is one field in deck.yaml, and 34 of them ship. Download the MP4.

The pipeline

brief → research → outline → HUMAN GATE → content → validate → render → preview → critique
         notes.md   plan.yaml              deck.yaml           .pptx     PNGs
                                                               .docx

The gate is deliberate: nothing renders until a person has read the outline and approved it. Everything after it is deterministic or checked.

  • Research from SearXNG, arXiv, Crossref, or your own uploaded documents. Claims are checked back against the saved notes before a deck is finalised.
  • Per-slide retrieval. Each slide is shown the research that slide needs rather than the whole corpus — which is both cheaper and better writing.
  • Rendered, then read back. A written .pptx proves only that the file parsed. Slides are rasterised and the text read off the image, because pres.writeFile() succeeds happily for text running off the canvas.
  • A vision critic looks at the rendered PNGs and fixes what it sees.

The vocabulary

74 slide types: 73 native layouts plus the deliberate freeform exception. The model chooses among them by what the content is — a comparison becomes a comparison layout, not a bulleted list about comparing.

timeline compare chart
Timeline slide Compare slide Chart slide
pyramid matrix flow
Pyramid slide Matrix slide Flow slide
table funnel big-number
Table slide Funnel slide Big number slide

Text stays editable. freeform is the one type rasterised whole — it is the deliberate exception, where the model writes the slide as HTML. A plate theme is not the same thing: Chrome renders only the decorative background to a PNG, and every word on top of it is still native PowerPoint text you can select and retype.


Real output

Decks and reports made with this app, committed so you can open them without running anything:

Presentation Size Files
Recent Trends in Mixed-Mode Programming 21 slides + report PPTX · DOCX
First Impressions & Networking 20 slides + report PDF · PPTX · DOCX
First Impressions & Networking, a second run 20 slides PPTX

Browse published/. Private decks live in decks/<slug>/ and are gitignored.


Reports are the other half

The deck is free and themed; the report is rigid and graded against an institutional template. Your department's .docx is the donor: the renderer strips only its body and keeps everything else byte-identical — the watermark in the header, the footer's page field, the styles, the media.

The section list is read from the donor itself, so a different college's template is an upload, not a code change. Table-of-contents page numbers are real: the render is two-pass, converting once to find where each heading lands.


Run from source (contributors)

Use this only when developing Forge itself rather than using it. It exposes the Vite UI on :5173 and API on :5174, and expects the renderer prerequisites on your host:

npm install
npm run fonts
npm run brand
cp config/identity.example.yaml config/identity.yaml
ollama pull qwen3:4b
npm run dev

LOCAL_SETUP.md covers the source path, platform-specific prerequisites and troubleshooting. docs/DEPLOY.md is the separate hardened production route — hosted mode, Caddy/TLS, mail, persistent secrets, administrator controls and tenant limits.


Everyday commands

npm run dev                                   # API :5174 + UI :5173
npm test                                      # automated test suite

npm run render decks/<slug>/deck.yaml         # content -> .pptx
npm run preview decks/<slug>/out/deck.pptx    # .pptx -> PNGs

npm run themematrix                           # every theme x every type, fit verdicts
npm run textcheck                             # did every word survive onto the page
npm run drawcheck                             # did every field reach the page at all
npm run deckscore <slug>                      # a deck, scored /100
npm run deckscore -- --history                # what previous runs scored

npm run forge -- new "<topic>" --research     # headless: outline
npm run forge -- generate <slug> --critic     # headless: deck

The CLI is not a wrapper around the app — both call the same src/. The API layer holds no presentation logic, because the pipeline has to run headless.


Verification that proves something

A written .pptx proves the file parsed and nothing else. pres.writeFile() succeeds for decks with text off the canvas and invisible-on-invisible colour pairs. So the checks ask four different questions, and each was added because the ones before it were clean on a defect that shipped:

  1. Is the box on the slide? A geometry watcher runs inside every render.
  2. Was the field drawn at all? drawcheck writes a marker into each field and reads back what the layout emitted.
  3. Does the text fit? themematrix across 34 themes × 74 types.
  4. Did it survive the render? textcheck rasterises and reads it back.

None of them replaces looking at the image.


Project map

app/server/       Express transport over the shared core — no logic of its own
app/web/          Vite + React browser application
src/              renderer, pipeline, research, validation, previews, metering
themes/           34 design languages
styles/           reusable token overrides layered over a theme
schema/           the content contracts for decks and reports
templates/        starting content templates
config/           models, identity, accounts, keys
brand/            institutional marks, per operator and per account
app/gallery/      committed theme specimens — the images above
decks/<slug>/     a portable workspace: content, plan, research, output
docker/           image, Compose stack, TLS, SearXNG
docs/             architecture, blockers, economics, roadmap, traps

Data and privacy

No external database service is required. A deck workspace is ordinary files and copies to another installation.

Data Location Committed?
Deck content, outline, research, output decks/<slug>/ definitions yes, output no
Institution identity config/identity.yaml, config/identities/ no
Accounts, sessions, keys, usage config/forge.db no — keys encrypted under FORGE_KEY_PEPPER
Provider keys (install-wide) config/local.yaml no
Brand assets brand/ no — they may carry protected marks

With Ollama, model calls never leave the machine. Research providers and an explicitly chosen hosted provider involve network requests; the deck, the research and the account data stay local.

Retention. Nothing is deleted unless FORGE_SWEEP_DAYS is set, and then the clock is inactivity, not age. GET /api/policy reports what the running install actually enforces, so the notice in the app cannot drift from the scheduler behind it.

Hosted deployment

The internet-facing stack is intentionally separate: TLS, SMTP, secure cookies, operator secrets, tenant limits and retention. It still uses the same image and builds for amd64 and arm64. See docs/DEPLOY.md; the root Compose file is private local software and must not be exposed as a public service.

Further reading

Doc Answers
ARCHITECTURE how it is built, as built
ROADMAP all work — done, planned, and why
BLOCKED what cannot be worked on, and who can unblock it
ECONOMICS what a deck costs to produce and what it can be sold for
PRODUCTION what stands between here and real users
TRAPS failure modes that have already bitten
LOCAL_SETUP prerequisites and troubleshooting

Community

Questions and early ideas belong in GitHub Discussions. Reproducible defects and scoped feature requests use the repository issue templates. Before contributing, read CONTRIBUTING.md and the Code of Conduct. Report vulnerabilities privately through the process in SECURITY.md; never put keys or private deck content in a public issue.

License

MIT. Institutional marks, donor templates and assets you add remain yours and may carry their own restrictions.

About

Self-hosted AI presentation generator: topic or sources in, researched themed editable PPTX and report out. Docker, BYOK or Ollama; 74 slide types, 34 themes.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages