Skip to content
ishan-pariharPublic

About

Browserless carousel factory — 46 slide types, embedded Blitz renderer (no Chromium), MCP server, WCAG-AA validation. 185 tests.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

242 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

verified 716dbdb
covers src/**

Deckmill Rust

  • Page index — every active doc and the question it owns.
  • Architecture — the pipeline end to end, and why there is no browser in it.

High-performance slide carousel generator — CLI + MCP server for creating professional Instagram/LinkedIn/TikTok carousels as HTML → PNG.

Rust CI License MCP Tests


Features

  • 38 active slide types (46 registry keys; 8 are removed tombstones kept only for redirect notes) grouped by layout family: image, conversion, data, content, process, educational, story, strategy, hero, feature
  • MCP server — integrate with Claude, Cursor, or any MCP client for AI-driven slide generation
  • CLI — scriptable, CI-friendly commands for batch generation
  • Design system — tokens, themes, archetypes, Google Fonts, CSS variables
  • Export pipeline — HTML → PNG via the embedded Blitz renderer (stylo + vello-cpu, no browser needed; 1080×1350, 1080×1080, 1080×1920, 1200×627, 1200×675, etc.)
  • Validation — pre-flight param checks, layout overflow detection, contrast auditing
  • Session persistence — configure_design tokens survive MCP restarts (~/.deckmill/session_state.json)

How it compares

Capability Deckmill Rust Canva / Figma Python-pptx / PPTX libs Headless Chrome screenshot scripts
Agent-native generation ✅ MCP server + CLI, AI-driven ❌ GUI ⚠️ scripted ⚠️
Render without a browser ✅ embedded Blitz (stylo + vello-cpu) n/a n/a ❌ needs Chrome
Validation ✅ overflow detection + contrast (WCAG-AA) auditing ⚠️ manual ❌ ❌
Slide-type library ✅ 38 active types, design tokens + themes ✅ templates ⚠️ ⚠️
Deterministic output ✅ same HTML → same PNG ⚠️ ✅ ⚠️
Session design memory ✅ tokens persist across restarts ✅ ❌ ❌
Self-hosted binary ✅ single Rust binary, 192 tests ❌ SaaS ✅ ✅

Canva is a design studio for humans; Deckmill is a deterministic slide factory for agents — the same tokens, themes, and validation every run.


Showcase

Every slide below is a real export rendered by the embedded Blitz engine (stylo layout + vello-cpu raster) — no browser, no screenshots, no doctored images.

Hero slide in dark editorial style with a gradient accent
hero — dark editorial, gradient accent
Donut chart slide on a light card over a dark background
chart — donut with legend
Metric grid slide with a 2x2 grid of KPI cards
metric_grid — KPI cards
Funnel chart slide with a purple-to-cyan gradient
funnel_chart — conversion funnel
Image headline slide with a city skyline photo and frosted-glass overlay
image_headline — full-bleed photo
Call-to-action slide inviting comments
comment_cta — conversion close

Browse the full interactive decks: all_types_carousel.html · typology_viewer.html · random_styles_viewer.html · stress_test_master.html


Quick Start

Install (pre-built binary)

# Static musl binary (runs on any Linux, no dependencies) — grab from Releases:
curl -fsSL https://github.com/ishan-parihar/deckmill/releases/download/v0.4.0/deckmill-x86_64-unknown-linux-musl \
  -o ~/.local/bin/deckmill && chmod +x ~/.local/bin/deckmill

# Or build from source:
cargo install --git https://github.com/ishan-parihar/deckmill

CLI Usage

# Generate a single slide
deckmill generate-slide hero \
  --primary-color '#4F46E5' \
  --params '{"headline":"Ship slides in minutes","subheadline":"AI-powered carousels"}' \
  --override accent='#00FF88'

# Export carousel to PNGs
deckmill export ./carousel.html \
  --output-dir ./exports \
  --slides 4 \
  --preset instagram_portrait

# List all slide types
deckmill list-slides

# Get schema for a slide type
deckmill slide-info hero

MCP Server

# Start MCP server (stdio transport)
deckmill mcp

Configure in your MCP client (Claude Desktop, Cursor, etc.):

{
  "mcpServers": {
    "deckmill": {
      "command": "deckmill",
      "args": ["mcp"]
    }
  }
}

MCP Tools:

  • configure_design — set brand color, theme, archetype, platform (persists to disk)
  • generate_slide — create one slide (validates required params, blocks on missing)
  • render_carousel — assemble slides into full HTML carousel
  • export_carousel_slides — render carousel to PNG directory
  • preview_slide — quick single-slide PNG preview
  • get_slide_type_info — discover required/optional params + example payload
  • validate_layout / validate_design — audit HTML for overflow, contrast, clipping

Slide Types (38 active)

The registry holds 46 keys; 8 are removed tombstones kept only so old payloads get a redirect note instead of a hard error. deckmill list-slides prints all 46 with their status; the 38 below are the ones the CLI's own active filter (get_slide_type_info + layout_family) keeps.

Layout family Types
hero hero
image image_caption, image_headline, image_quote, image_callout, image_gallery, image_collage, image_comparison
conversion big_statement, comment_cta, pricing_plan, qr_destination
data chart, comparison*, stat_row*
content text_block, faq
educational definition, myth_fact
process process_map, timeline
story before_after_story, problem_solution, case_study_result, checklist_action_plan, logo_cloud, quote, split_features, testimonial_avatar
metrics metric_grid, gauge, comparison_bars, progress_rings, funnel_chart, radar_chart, scatter_plot, table, column_chart

* deprecated aliases: comparison routes to before_after_story; stat_row routes to metric_grid. They still render but are not the canonical names.

Removed tombstones (not listed above): feature, list, cta, callout, grid_cards, text_columns, image_stat, section_divider.

Each type exposes required_params, optional_params, variants, and an example payload via get_slide_type_info.


Configuration

Design Tokens (via configure_design)

{
  "primary_color": "#4F46E5",
  "visual_theme": "bold",        // editorial, bold, minimal, dark, vibrant, natural
  "preset": "vibrant",           // tonal_spot, vibrant, neutral, monochrome, expressive, fidelity, rainbow, fruit_salad, content
  "archetype": "startup_pitch",  // educator, thought_leader, startup_pitch, brand_storyteller, data_analyst, creator
  "platform": "instagram_portrait",
  "brand_name": "Acme Inc",
  "brand_handle": "@acme"
}

Tokens persist to ~/.deckmill/session_state.json and survive MCP restarts.

Token Override (CLI only)

deckmill generate-slide hero \
  --primary-color '#FF5500' \
  --params '{"headline":"Override test"}' \
  --override accent='#00FF88' \
  --override secondary='#222244'

Unknown keys warn with typo suggestions (typo → Did you mean 'accent'?).


Export Pipeline

generate-slide(s) → render-carousel → export
Preset Aspect Dimensions Use Case
instagram_portrait 4:5 1080×1350 Feed carousels
instagram_square 1:1 1080×1080 Feed posts
instagram_story 9:16 1080×1920 Stories/Reels
tiktok_vertical 9:16 1080×1920 TikTok
linkedin_landscape 1.91:1 1200×627 LinkedIn docs
twitter_card 16:9 1200×675 Twitter/X
facebook_post 1.9:1 1200×630 Facebook feed
presentation_16_9 16:9 1920×1080 Slides
presentation_4_3 4:3 1024×768 Slides

PNG geometry fix (v0.2.0+): All presets now render at exact target dimensions (no more 143px height deficit).

Preset dimensions are the export target (G-07). Each preset's own width × height is what deckmill export --preset <name> produces with no --aspect-ratio. An explicit --aspect-ratio re-derives dimensions from the ratio table (1:1 → 1080×1080, 4:5 → 1080×1350, …), so:

deckmill export ./carousel.html --output-dir ./exports --preset linkedin_landscape
#  → 1200×627 PNGs

deckmill export ./carousel.html --output-dir ./exports --preset linkedin_landscape --aspect-ratio 1:1
#  → 1080×1080 PNGs

test_every_preset_exports_its_native_canvas_by_default in src/platforms.rs pins this per preset, so a new preset cannot silently inherit the wrong canvas.


Validation

# Validate slide params before rendering
deckmill validate-layout --slide-type hero --params '{"headline":"Test"}'

# Audit rendered HTML for design issues
deckmill validate-design ./carousel.html

Checks: overflow, contrast, descender clipping, squished components, distorted images, progress ring thickness, text column width.


Memory Profile

The Blitz rendering engine (stylo layout + vello-cpu raster) is embedded in the binary — no Chromium subprocess, no browser download, no persistent browser pool. Measured against the legacy headless-Chrome build on the same 8-slide export workload:

Metric Blitz (v0.4.0, measured 2026-08-07) Legacy Chrome Delta
Peak RSS 132 MB 599 MB 4.5× less
Wall time 13.3 s 15.4 s 1.2× faster
Component RSS (idle)
MCP server ~8.5 MB
CLI (generate-slide) ~4 MB

Build from Source

# Standard (glibc)
cargo build --release

# Musl static (for Alpine/scratch containers)
cargo build --release --target x86_64-unknown-linux-musl

Requires: Rust 1.75+, clang/lld for the musl target (aws-lc-sys).

The build uses rustls-only TLS — a vendored blitz-net ([patch.crates-io]) swaps its hardcoded native-tls for rustls so no libssl/libcrypto is ever linked. The musl artifact is a fully static ~21 MB binary (verified statically linked via ldd).


License

MIT — see LICENSE.

Agent Integration (AXI §7)

Deckmill ships an installable AI agent skill that provides ambient context at session start — showing slide types, design tokens, and contextual help hints.

Install the Skill

# Via npx (recommended)
npx skills add ishan-parihar/deckmill --skill deckmill

# Or download manually
curl -fsSL https://raw.githubusercontent.com/ishan-parihar/deckmill/master/SKILL.md \
  -o ~/.agents/skills/deckmill/SKILL.md

Session Hook (Claude Code)

Add to ~/.claude/settings.json or project .claude/settings.json:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "deckmill"
          }
        ]
      }
    ]
  }
}

At session start, Deckmill prints a compact dashboard:

bin: ~/.local/bin/deckmill
description: Instagram/LinkedIn/TikTok carousel generator — 38 active slide types, 9 platform presets

slides[38]{type,description}:
  hero,Opening hook with headline and subheadline
  ...

design_tokens:
  primary_color: #4F46E5
  theme: bold
  archetype: startup_pitch

help[4]:
  Run `deckmill list-slides` to see all 38 active slide types
  Run `deckmill generate-slide hero --params '{...}'` to create a slide
  Run `deckmill render-carousel slides.json --tokens-file tokens.json` to render
  Run `deckmill export carousel.html --output-dir ./exports` to export PNGs

Session Hook (Codex)

Add to ~/.codex/hooks.json or project .codex/hooks.json:

{
  "SessionStart": "deckmill"
}

Session Hook (OpenCode)

Create ~/.config/opencode/plugins/deckmill.ts:

export default {
  name: "deckmill",
  onSessionStart: async () => {
    const { execSync } = require("child_process");
    return execSync("deckmill").toString();
  },
};

☕ Support & Sponsorship

If you find this project useful, consider supporting ongoing development:

Sponsor Donate

Your support funds new features, releases, and infrastructure for the whole ecosystem.

About

Browserless carousel factory — 46 slide types, embedded Blitz renderer (no Chromium), MCP server, WCAG-AA validation. 185 tests.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages