Skip to main content
Glama
███████╗██╗     ██╗██████╗ ███████╗
██╔════╝██║     ██║██╔══██╗██╔════╝
███████╗██║     ██║██║  ██║█████╗
╚════██║██║     ██║██║  ██║██╔══╝
███████║███████╗██║██████╔╝███████╗
╚══════╝╚══════╝╚═╝╚═════╝ ╚══════╝

slide

Slide decks in the browser: draw, point at a shape, and let your agent edit it over MCP.

slides · mcp · docker · pptx

CI  Image  License: MIT

Many people draw their slides by hand in PowerPoint: rounded rectangles, connectors glued to them, text boxes placed wherever they fit. Asking an AI to change one box means first describing where that box is. slide keeps those drawing tools in the browser, lets you select a shape and tell your agent what to change, and still exports a normal .pptx when someone needs one.

> "Make the hi on slide 1 say Results, 24 pt bold"
  ⚡ get_deck { deck_id: "dk_a9q86y45ax" }
  ⚡ update_shapes { deck_id: "dk_a9q86y45ax", slide: 1, updates: [{ id: "sh_hdq4vujt", set: { text: { paragraphs: [{ runs: [{ text: "Results", size: 48, bold: true }], align: "center" }] } } }] }
✓ { status: "applied", entry: "42", changed: ["sh_hdq4vujt"] }: done; the editor shows it, and the history can revert it

What it does

  • Draws rectangles, rounded rectangles, ellipses, text boxes, pictures, and connectors that stay glued when shapes move, with undo, copy and paste

  • Types in place, Chinese input methods included, wrapping lines exactly where PowerPoint does

  • Hands your agent what you selected over MCP: the shapes as JSON, the words you marked, and a picture of that part of the slide

  • Lets your agent edit directly: its changes apply at once, like yours, and every one is recorded in the history, where any edit can be reverted on its own unless a later one changed the same place

  • Imports and exports .pptx, keeping shapes native, connectors glued and text editable

  • Presents full screen, or split across screens: the projector shows only the slides while your screen shows the slide, the next one, your speaker notes (written in the editor or by your agent) and a timer

  • Publishes a deck to a read-only link anyone can open and download

  • Checks a deck for your agent (check_deck): text sizes, overflow, overlaps, contrast, and the master's palette

Related MCP server: deck

Deploy

With Docker Compose, on any machine with Docker:

curl -fsSLO https://raw.githubusercontent.com/zyx1121/slide/main/compose.yaml
curl -fsSL -o .env https://raw.githubusercontent.com/zyx1121/slide/main/.env.example
# set POSTGRES_PASSWORD, APP_URL, OIDC_*, ALLOWED_EMAILS and SESSION_SECRET in .env
docker compose up -d

This starts Postgres, a one-shot migration job and the web app, all from ghcr.io/zyx1121/slide, with the app on 127.0.0.1:3000. Uploaded pictures live on the assets volume; back it up with the database.

IMPORTANT

The app listens on 127.0.0.1 and speaks plain HTTP: put a reverse proxy with TLS in front (it must pass the originalHost), and register APP_URL/auth/callback as a redirect URI of your sign-in client. Let the proxy refuse request bodies a little over 100 MiB, the largest upload (a .pptx import); in Caddy, request_body { max_size 101MiB } (Caddy reads MB as 1,000,000 bytes).

Use

  1. Sign in with an account whose email is in ALLOWED_EMAILS (Google, or any OpenID Connect provider you configure). The home page lists your decks: 新增 starts one on a master you pick, 匯入 turns a .pptx into one on its own master.

  2. Edit on the slide. Double-click a shape or the title to type; the dock at the bottom inserts shapes, text boxes, pictures and connectors, and a menu next to what you select styles it.

  3. Connect your agent. In Claude Code, run claude mcp add --transport http slide https://slide.example.org/mcp, then sign in from /mcp; it signs you in (if you are not already) and asks you to allow the agent.

  4. Select shapes (or words) and leave a comment from the dock's 評論 button, as many as you like; then ask your agent to answer the open comments. Or select shapes and ask your agent to change them directly. Its edits show up at once; the history button in the dock (紀錄) lists every change, yours and your agent's, and reverts any edit.

  5. Download a .pptx from the dock, or publish the deck from the globe button and share its /s/… link.

Configure

Set these in .env; .env.example documents every one.

Key

What it sets

Default

POSTGRES_PASSWORD

the bundled Postgres password

required

APP_URL

the public URL members open; the sign-in provider sends them back there

required

OIDC_ISSUER

the OpenID Connect provider, e.g. https://accounts.google.com

required

OIDC_CLIENT_ID

a confidential web client using the code flow with PKCE S256

required

OIDC_CLIENT_SECRET

that client's secret

required

ALLOWED_EMAILS

comma-separated verified email addresses that may sign in

required

SESSION_SECRET

encrypts the session cookie, 32 characters or more

required

OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS

where traces and error logs go, over OTLP/HTTP JSON

off

OTEL_SERVICE_NAME

the service name on those traces

slide

ASSETS_DIR

where a run from source keeps uploaded pictures (compose uses a volume)

./data/assets

MIGRATIONS_DIR

where the migrate role reads its SQL files

./migrations

SLIDE_VERSION

the image tag compose runs

latest

SLIDE_BIND, SLIDE_PORT

where the web port is published

127.0.0.1, 3000

How it works

flowchart LR
  E[Browser editor] -->|server actions, API routes| A[Next.js app]
  G[Your agent] -->|MCP at /mcp| A
  A --> D[(Postgres)]
  A -->|OIDC sign-in| O[Google or another OIDC provider]

One Next.js app and one Postgres database, run with Docker Compose. Members sign in with an OpenID Connect provider such as Google, and only verified emails in ALLOWED_EMAILS get in; each member sees only their own decks and pictures; a published deck is readable by anyone with its link until it is unpublished. An agent signs in through the app's own OAuth authorization server: the member signs in as on the web, allows the agent on a consent page, and the agent gets a one-hour access token and a rotating refresh token, stored only as hashes; /mcp acts as that member while the grant stands and the member stays on the allowlist. Every edit, from the editor or from an agent, goes through the same validated path and is stored as a revision; an agent's edit applies at once like the member's, and any edit can be reverted on its own. One renderer draws slides in the browser and, through resvg, on the server, with bundled fonts, so lines wrap the same everywhere.

Develop

bun install
sh scripts/fetch-fonts.sh   # Carlito, Noto Sans TC and Noto Emoji, for slide rendering
cp .env.example .env   # set DATABASE_URL to a Postgres you can reach
bun run migrate
bun dev

CI runs bun run typecheck, bun run lint, bun run format:check, and bun run test, then builds the image and smoke-tests the compose stack with scripts/smoke.sh.

Limitations

  • A deck keeps the slide master it is made on: plain, WinLab, or an imported file's own (its layouts' backgrounds, artwork and placeholders). A new slide gets its layout's title and text placeholders to type in, as in PowerPoint. Path gradients are drawn as circles

  • Import turns a table into a rectangle per cell (its text stays editable, but not as one table), and leaves out charts, SmartArt, freeforms drawn with guide formulas, and pictures in EMF, SVG or TIFF, and says so

  • Pictures are PNG, JPEG or GIF, up to 10 MB and 50 million pixels

  • Text is capped at 5,000 characters a shape and 20,000 a slide, so any slide renders in a second or two

  • Decks are private to their owner; sharing with other members is not there yet

  • In Safari and Firefox the projection window cannot place itself on the projector: drag it there, then double-click it to go full screen (Chromium browsers open it on the other screen)

Contributing

Issues and PRs welcome: start with CONTRIBUTING.md.

License

MIT · every connector stays glued

Related MCP Connectors

Related MCP Servers