JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 77
  • Score
    100M100P100Q67286F
  • License MIT

CLI to create beautiful slide cards (9:16, 16:9, 1:1) from JSON + HTML templates

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (slide-cli) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    slide-cli

    npm version npm downloads CI license bun ko-fi

    A TypeScript CLI to create beautiful slide cards from JSON data + HTML templates. Supports 9:16 (Stories/Reels), 16:9 (presentations/YouTube), and 1:1 (feed) aspect ratios.

    slide create        --data data.json --template minimal --out ./output
    slide list          [--verbose]
    slide add-template  <path>  [--force]

    Installation

    From npm (end users)

    npm install -g slide-cli
    slide --help

    Requires: Node.js ≥ 18 · Chrome/Chromium (bundled via Puppeteer)

    From source (contributors)

    git clone https://github.com/doum1004/slide-cli.git
    cd slide-cli
    bun install       # Bun is required for building and running tests
    bun run build     # outputs to dist/
    npm link          # exposes the `slide` command globally
    slide --help

    Requires: Bun ≥ 1.0 (build + test only) · Node.js ≥ 18 (runtime)

    Why both Bun and Node?

    The published dist/ runs on Node — so any end user with Node can install and use slide via npm without touching Bun. Bun is only needed locally to build (bun build) and run tests (bun test). This avoids the Windows issue where npm link detected Bun and generated a .ps1 wrapper that caused Puppeteer to hang silently.


    Quick start (from source)

    bun install
    bun run build
    slide list --verbose
    slide create --data samples/sample-quotes.json --template quote-card

    Commands

    slide create

    slide create --data my-deck.json --template minimal --out ./output
    Flag Default Description
    -d, --data <file> (required) Path to data JSON
    -t, --template <id> (required) Template id or name
    -o, --out <dir> ./output Output directory
    -f, --format <png|jpg> jpg Screenshot format
    --no-images off Skip screenshots (HTML only)

    Output:

    output/
    ├── slide-1.html   slide-1.jpg
    ├── slide-2.html   slide-2.jpg
    │   …
    ├── index.html     ← presentation viewer
    └── data.json      ← copy of your input

    slide list

    slide list
    slide list --verbose    # full slot schema

    slide add-template

    slide add-template ./my-template/
    slide add-template ./my-template/ --force

    Data JSON format

    {
      "title": "My Presentation",
      "slides": [
        {
          "layout": "minimal",
          "heading": "Less is more",
          "body": "Simplicity is the ultimate sophistication.",
          "label": "Chapter 01",
          "accent": "#c8b89a",
          "bg": "#0f0e0c"
        }
      ]
    }

    Built-in templates

    id Ratio Required slots Style
    minimal 9:16 heading Dark typographic, Fraunces serif
    bold-title 9:16 title Gradient editorial, Bebas Neue
    quote-card 9:16 quote Light serif pull-quote card
    minimal-wide 16:9 heading Dark typographic, two-column layout
    bold-title-wide 16:9 title Gradient editorial, title left / subtitle right
    quote-card-wide 16:9 quote Light serif pull-quote, quote left / attribution right

    Creating a custom template

    my-template/
    ├── template.json    ← manifest + slot definitions
    └── template.html    ← Handlebars HTML at your chosen dimensions

    template.json

    Set aspectRatio, width, and height to match your target format:

    aspectRatio width height Use case
    "9:16" 1080 1920 Instagram Stories, TikTok, Reels
    "16:9" 1920 1080 YouTube thumbnails, presentations
    "1:1" 1080 1080 Instagram feed, Twitter/X
    {
      "name": "My Template",
      "id": "my-template",
      "version": "1.0.0",
      "description": "Short description",
      "aspectRatio": "16:9",
      "width": 1920,
      "height": 1080,
      "slots": [
        { "id": "headline", "type": "text",  "label": "Headline",   "required": true },
        { "id": "bg",       "type": "color", "label": "Background", "required": false, "default": "#fff" }
      ]
    }

    Slot types: text · color · image · number · url

    template.html

    Match width and height in CSS to the values in your manifest:

    <!DOCTYPE html><html>
    <head><style>
      html, body { width: 1920px; height: 1080px; background: {{bg}}; }
    </style></head>
    <body>
      <h1>{{headline}}</h1>
      {{#if subtitle}}<p>{{subtitle}}</p>{{/if}}
      <footer>{{slideIndex}} / {{totalSlides}}</footer>
    </body></html>

    Always available: {{slideIndex}} · {{totalSlides}} · {{title}}
    Helpers: {{#if}} · {{upper val}} · {{lower val}} · {{default val "fallback"}}


    Presentation viewer

    The generated index.html has:

    • ← → keys or buttons · Space = autoplay · F = fullscreen
    • Home/End · touch/swipe support
    • Speed selector · progress bar · dot nav

    Template storage

    Path Purpose
    ~/.slide-cli/templates/ User templates (via add-template)
    <project>/templates/ Built-in templates

    User templates take priority over built-ins on id collision.