---
name: "Presenton"
client: Open-source (presenton.ai)
status: active
tech: [Python 3.11, FastAPI, Next.js 14, SQLModel, python-pptx, OpenAI/Google/Anthropic LLMs, Docker]
local_path: /Users/ai_leed/Documents/Projects/Oliver/presenton
deploy: docker compose up production
url: http://localhost:5000
tags: [oliver, presentation, ai, open-source]
created: 2026-04-14
server: local
port: 5000
db: SQLite
---

## Overview

Presenton is an open-source, self-hosted AI presentation generator that transforms prompts, documents, or existing PPTX files into fully designed presentations (PPTX/PDF format). It supports multiple LLM providers (OpenAI, Google, Anthropic, Ollama, custom endpoints) and image providers (DALL-E, Gemini, Pexels, ComfyUI), includes a built-in MCP server for AI agent integration, and exposes a REST API for programmatic access. The project is production-ready, actively maintained, and Apache 2.0 licensed.

## Tech Stack

- **Frontend:** Next.js 14 (App Router), React, Redux Toolkit, TypeScript
- **Backend:** FastAPI (Python 3.11), SQLModel (ORM), uvicorn
- **Database:** SQLite (default, can override with PostgreSQL/MySQL via `DATABASE_URL`)
- **Infrastructure:** Docker (single container), nginx reverse proxy, LibreOffice (PDF export), Puppeteer/Chromium
- **AI/ML:** OpenAI (GPT-4, DALL-E, GPT-Image-1.5), Google Gemini, Anthropic Claude, Ollama (local models), custom OpenAI-compatible endpoints
- **Key libraries:** python-pptx (PPTX generation), docling/pdfplumber (document extraction), fastmcp (MCP server), Pillow (image processing)

## Architecture

Presenton runs as a single Docker container with four coordinated processes spawned by `start.js`:
- **nginx** (port 80) — reverse proxy and static file server
- **FastAPI** (port 8000) — backend REST API and core logic
- **Next.js** (port 3000) — frontend SSR
- **MCP Server** (port 8001) — AI agent integration via Claude Desktop
- **Ollama** (port 11434) — optional local LLM serving

All processes are internally networked; external access is exclusively through nginx on port 80 (mapped to host port 5000).

### Presentation Generation Pipeline

```
User Input (prompt/files/PPTX)
    ↓
[Outline Generation] — LLM streams slide outlines (SSE)
    ↓
[Structure Assignment] — LLM assigns layout index per slide
    ↓
[Slide Content] — Batch of 10 slides: content generation
    ↓
[Asset Fetching] — Images fetched/generated concurrently per slide
    ↓
[Export] — python-pptx builds PPTX; LibreOffice converts to PDF
    ↓
[Webhook] — presentation.generation.completed event fired
```

### Data Model

- **PresentationModel** — metadata (title, template, status, content type)
- **SlideModel[]** — per-slide content (outline, title, bullet points, speaker notes, layout index)
- **ImageAsset[]** — images per slide (URL, provider, generation prompt, alt text)

All persisted in SQLite at `/app_data/fastapi.db`.

## Dev Commands

### FastAPI Backend
```bash
cd servers/fastapi

# Install uv package manager
pip install uv

# Install dependencies
uv sync

# Run development server (requires APP_DATA_DIRECTORY env var)
APP_DATA_DIRECTORY=./app_data uv run python server.py --port 8000

# Run tests
uv run pytest

# Lint/format
uv run ruff check .
```

### Next.js Frontend
```bash
cd servers/nextjs

# Install dependencies
npm install

# Dev mode with HMR (connects to FastAPI at localhost:8000)
npm run dev

# Production build
npm run build
npm run start

# Lint
npm run lint

# E2E tests (Cypress)
npx cypress open      # interactive
npx cypress run       # headless
```

### Full Stack (Docker)
```bash
# Development with hot-reload
docker compose up development

# Production
docker compose up production

# GPU-accelerated (NVIDIA)
docker compose up production-gpu

# View logs
docker compose logs -f production

# Stop and clean up
docker compose down
```

## Deployment

- **Server:** Local (self-hosted)
- **Deploy:** `docker compose up production` or `docker run -it --name presenton -p 5000:80 [env vars] ghcr.io/presenton/presenton:latest`
- **URL:** `http://localhost:5000`
- **Port:** 5000 (host) → 80 (container)
- **Service:** None (container-based)
- **Local path:** `/Users/ai_leed/Documents/Projects/Oliver/presenton`
- **Image:** `ghcr.io/presenton/presenton:latest`
- **Base:** `python:3.11-slim-bookworm`
- **Persistent volume:** `./app_data → /app_data`

### Quick Start
```bash
git clone https://github.com/presenton/presenton.git
cd presenton

docker run -it --name presenton -p 5000:80 \
  -e LLM="openai" \
  -e OPENAI_API_KEY="sk-..." \
  -e IMAGE_PROVIDER="dall-e-3" \
  -v "./app_data:/app_data" \
  ghcr.io/presenton/presenton:latest

# Open http://localhost:5000
```

## Environment Variables

**LLM Configuration:**
- `LLM` — Provider: `openai`, `google`, `anthropic`, `ollama`, `custom`
- `OPENAI_API_KEY` — OpenAI API key (required for OpenAI LLM or DALL-E/GPT-Image)
- `OPENAI_MODEL` — Model ID (default: `gpt-4-1`)
- `GOOGLE_API_KEY` — Google API key (Gemini LLM or image generation)
- `GOOGLE_MODEL` — Gemini model ID (default: `models/gemini-2.0-flash`)
- `ANTHROPIC_API_KEY` — Claude API key
- `ANTHROPIC_MODEL` — Claude model ID (default: `claude-3-5-sonnet-20241022`)
- `OLLAMA_URL` — Ollama server (default: `http://localhost:11434`)
- `OLLAMA_MODEL` — Model to use (e.g., `llama3.2:3b`)
- `CUSTOM_LLM_URL` — OpenAI-compatible endpoint URL
- `CUSTOM_LLM_API_KEY` — API key for custom endpoint
- `CUSTOM_MODEL` — Model ID for custom endpoint
- `TOOL_CALLS` — Use tool calls for structured output (default: `false`)
- `DISABLE_THINKING` — Disable chain-of-thought (default: `false`)
- `EXTENDED_REASONING` — Enable extended reasoning (default: empty)
- `WEB_GROUNDING` — Enable LLM web search (default: `false`)

**Image Provider Configuration:**
- `IMAGE_PROVIDER` — Provider: `dall-e-3`, `gpt-image-1.5`, `gemini`, `pexels`, `pixabay`, `comfyui`
- `PEXELS_API_KEY` — Pexels API key
- `PIXABAY_API_KEY` — Pixabay API key
- `COMFYUI_URL` — ComfyUI server URL (for local image generation)
- `COMFYUI_WORKFLOW` — ComfyUI workflow JSON path

**Data & Infrastructure:**
- `APP_DATA_DIRECTORY` — Root for persistent data (default: `/app_data`)
- `TEMP_DIRECTORY` — Temp file staging (default: `/tmp/presenton`)
- `DATABASE_URL` — Override SQLite; use `postgresql://` or `mysql://` for other DBs
- `PUPPETEER_EXECUTABLE_PATH` — Chromium path (default: `/usr/bin/chromium`)
- `CAN_CHANGE_KEYS` — Allow UI to modify API keys (default: `true`)

## API / Endpoints

**REST API Base:** `http://localhost:5000/api/v1/`

**Key Endpoints:**
- `POST /ppt/presentation/generate` — Generate presentation (sync, returns PPTX/PDF path)
- `POST /ppt/presentation/create` — Save new presentation (returns ID)
- `GET /ppt/outlines/stream/{id}` — Stream outline JSON (SSE)
- `POST /ppt/presentation/prepare` — Assign layouts and structure
- `GET /ppt/presentation/stream/{id}` — Stream slide content (SSE)
- `POST /ppt/presentation/export` — Export to PPTX or PDF
- `POST /ppt/pptx-slides/process` — Analyze uploaded PPTX (extract slides, fonts, XML)
- `POST /ppt/slide-to-html/` — Convert PPTX slide to HTML

**MCP Server:**
- `http://localhost:5000/mcp` — FastMCP HTTP endpoint for Claude Desktop integration

**Swagger UI:** `http://localhost:5000/docs`

## Known Issues

- None explicitly documented in provided files. Refer to GitHub issues at https://github.com/presenton/presenton/issues

## Git

- **Remote:** `https://github.com/presenton/presenton.git`
- **Latest commits:** Recent work includes new templates refactor, MCP OpenAI spec fixes, Ukrainian language support, GPT-Image-1.5 integration, local ComfyUI image provider support, and NanoBanana integration
- **License:** Apache 2.0

---

## Additional Resources

- **Architecture & Design:** See `docs/project/architecture.md` for detailed data flows and component interactions
-

## Sessions
### 2026-04-14 – Project catalogued
**Done:** Added to Obsidian second brain.

---
## Change Log
| Date | Requested | Changed | Files |
|------|-----------|---------|-------|
| 2026-04-14 | Initial setup | Note created | — |

## Related
- [[ppt-tool/PPT Tool DeckForge]]