mcpField
S
slidej

slidej

github.com/h4pplnessDocuments2657 installsUpdated 19w ago
Repository

About slidej

slidej generates PowerPoint presentations from JSON and parses PPTX files back into JSON. It is for users building or inspecting slides as structured data, with templates, layout elements, and animation controls.

Key features

  1. 01Generate PPTX from JSON
  2. 02Parse PPTX into JSON
  3. 03Use multiple presentation templates
  4. 04Configure text, shapes, images, and tables
  5. 05Set element animations and trigger order

Use cases

  1. 01Create presentations from structured content
  2. 02Convert an existing PPTX to JSON for inspection
  3. 03Build reports with tables or graphics
  4. 04Sequence animations across slide elements

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/h4pplness/slidej --skill slidej

After installing, type/slidejin Claude Code to confirm it loaded.

Details

From the project README

SlideJ — Agent Guide

Quick Start

# JSON -> PPTX
slidej generate input.json -o output.pptx
slidej gen input.json -o output.pptx          # alias

# PPTX -> JSON
slidej parse input.pptx -o output.json
slidej parse input.pptx                       # stdout
slidej parse input.pptx --no-images -o out.json

# Templates
slidej template list                          # list all
slidej template info <name>                   # show style guide
slidej template use <name> -o deck.json       # export for editing
slidej template save input.json <name> -d "Description" -t "tag1,tag2"
slidej template remove <name>

# Helpers
slidej schema                                 # print JSON schema
slidej example -o example.json                # demo deck
Templates
TemplateStyleBest for
title-slideDark hero, centeredTitle screens, section dividers
pitch-deckProfessional dark-to-lightPitches, proposals
reportClean corporate, tablesReports, dashboards
minimalWhitespace, typographyAcademic, text-heavy
dark-modernDark UI, gradient accentsTech, SaaS demos
sunset-waveWarm gradients, organicCreative, storytelling
candy-popBold pop-art on whiteEvents, campaigns
ocean-auroraDeep cool-tone, glowTech showcases, premium
neon-gardenNeon-on-blackCreative agencies, entertainment

JSON Structure

Root
{
  "width": 13.333,
  "height": 7.5,
  "meta": { "title": "Title", "author": "Author" },
  "theme": {
    "colors": { "accent1": "4472C4", "accent2": "ED7D31" },
    "majorFont": "Calibri Light",
    "minorFont": "Calibri"
  },
  "slides": [...]
}
Slide
{
  "background": "1A1A2E",
  "transition": "fade",
  "elements": [...]
}

Background: hex string "1A1A2E" or gradient object:

{
  "type": "gradient",
  "stops": [
    { "position": 0, "color": "0B0B1F" },
    { "position": 100, "color": "162447" }
  ],
  "angle": 135
}

Transition: "fade" | "push" | "wipe" | "split" | "cover" | "cut" | "dissolve" | "random", or object { "type": "fade", "speed": "med", "advanceAfter": 3000 }.


Elements

All elements must have position: { x, y, w, h } in inches.

Slide size: 13.333" wide x 7.5" tall. Safe margin: 0.5" on each side.

Rules
  • Colors are bare hex without #: use "FF0000" not "#FF0000".
  • Font sizes are in points. Text is not auto-sized — reduce fontSize or enlarge box if text overflows.
  • Image src paths are resolved relative to the JSON file's directory.
  • Use "\n" inside any text string for line breaks.
Text
{
  "type": "text",
  "text": "Hello World",
  "position": { "x": 1, "y": 1, "w": 10, "h": 1.5 },
  "fontSize": 36,
  "bold": true,
  "color": "FFFFFF",
  "fontFamily": "Calibri Light",
  "align": "center",
  "vertAlign": "middle"
}

Multi-paragraph (each item is a separate paragraph):

"text": [
  { "text": "Heading", "fontSize": 28, "bold": true, "color": "FFFFFF" },
  { "text": "Subtitle", "fontSize": 16, "color": "AAAAAA" }
]

Mixed runs in one paragraph:

"text": [
  {
    "align": "center",
    "runs": [
      { "text": "Bold part ", "bold": true, "color": "FF0000" },
      { "text": "normal part", "color": "333333" }
    ]
  }
]

Bullet list:

"text": [
  { "text": "First point", "bullet": true },
  { "text": "Second point", "bullet": true }
]

Optional: fill, line, shadow, rotation, margin, lineSpacing, italic, underline, strike.

Shape
{
  "type": "shape",
  "shapeType": "roundRect",
  "position": { "x": 1, "y": 1, "w": 4, "h": 3 },
  "fill": "4472C4",
  "line": { "color": "333333", "width": 2 },
  "text": "Label",
  "fontSize": 18,
  "color": "FFFFFF",
  "align": "center",
  "vertAlign": "middle"
}

Shape types: rect, roundRect, ellipse, triangle, diamond, pentagon, hexagon, octagon, star5, star6, rightArrow, leftArrow, upArrow, downArrow, line, cloud, heart, lightningBolt, callout1, callout2, chevron, donut, blockArc, arc, pie, plaque, can, parallelogram, trapezoid.

Fill can be gradient:

"fill": {
  "type": "gradient",
  "stops": [
    { "position": 0, "color": "4472C4" },
    { "position": 100, "color": "2E5CA8" }
  ],
  "angle": 135
}

Optional: noFill (outline only), adjust (geometry tweaks), shadow, rotation.

Image
{
  "type": "image",
  "src": "assets/photo.png",
  "position": { "x": 2, "y": 2, "w": 5, "h": 3 }
}

Optional: hyperlink, crop: { left, top, right, bottom }, line, rotation.

Table
{
  "type": "table",
  "position": { "x": 0.5, "y": 2, "w": 12, "h": 4 },
  "headerRow": true,
  "fontSize": 14,
  "rows": [
    ["Column A", "Column B", "Column C"],
    ["Data 1", "100", "OK"]
  ]
}

Styled cells: { "text": "Header", "bold": true, "fill": "4472C4", "color": "FFFFFF", "align": "center" }.

Tables do NOT support animations.

Group

Groups wrap multiple elements into a single unit. Children use absolute coordinates (not relative to the group).

{
  "type": "group",
  "position": { "x": 0, "y": 0, "w": 8, "h": 8 },
  "rotation": 0,
  "children": [
    { "type": "shape", "shapeType": "ellipse", "position": { "x": 0, "y": 0, "w": 8, "h": 8 }, "fill": "FAFAFA" },
    { "type": "shape", "shapeType": "ellipse", "position": { "x": 3.8, "y": 0, "w": 0.4, "h": 0.4 }, "fill": "FF0000" }
  ],
  "animations": [
    { "type": "fadeIn", "duration": 500, "trigger": "afterPrevious", "order": 0 },
    { "type": "spin", "degrees": 90, "duration": 800, "trigger": "afterPrevious", "order": 1 }
  ]
}

Key points:

  • rotation on the group sets the initial rotation (degrees). This is a static base angle.
  • Animations on the group apply to the entire unit — all children move/fade/spin together.
  • Group rotation + spin animation compose: you can set different base rotation across slides and add the same spin to create a continuous rotation effect (e.g. 0, 72, 144... base + spin 72 each time).
  • Children inside a group cannot have their own animations — only the group itself animates.

Animations

Add "animations": [...] to any text, shape, image, or group element.

"animations": [
  { "type": "fadeIn", "duration": 500, "trigger": "afterPrevious", "delay": 0 }
]
Triggers (how animations are sequenced)
TriggerBehavior
onClickPlays on mouse click (default). Starts a new click group.
withPreviousPlays at the same time as the previous animation.
afterPreviousPlays after the previous animation finishes.

The first afterPrevious animation on a slide auto-plays on slide entry — no click needed. This is the standard way to make things appear automatically.

All animation types

Entrance (element appears):

TypeRequired fieldsDescription
appear—Instant appearance
fadeIn—Opacity 0 -> 100%
flyIndirectionFly in from a direction
wipeIndirectionWipe reveal from a direction
zoomIn—Scale from 0% to 100%
splitIn—Barn-door reveal
bounceIn—Scale with overshoot
floatIn—Fade + vertical drift up
swivel—Fade + horizontal unfold
dissolveIn—Dissolve effect

Exit (element disappears):

TypeRequired fieldsDescription
fadeOut—Opacity 100% -> 0
flyOutdirectionFly out to a direction
wipeOutdirectionWipe out to a direction
zoomOut—Scale from 100% to 0%
floatOut—Fade + drift away
dissolveOut—Dissolve out

Emphasis (element is already visible):

TypeRequired fieldsDescription
pulsescale (default 110)Pulse size briefly
spindegrees (default 360)Rotate in place
growShrinkscaleScale up/down
colorChangecolorAnimate fill to new color
transparencyopacityAnimate to opacity %
teeterdegreesRock back and forth
blink—Quick hide/show

Motion:

TypeRequired fieldsDescription
motionPathpoints array or path+direction+distanceMove along a path
Direction values (for flyIn/Out, wipeIn/Out)

top, bottom, left, right, topLeft, topRight, bottomLeft, bottomRight


Animation Patterns

Pattern 1: Staggered entrance (elements appear one after another)

Use afterPrevious with increasing delay on each element:

// Element 1 — auto-plays on slide entry (first afterPrevious = auto-play)
{ "type": "fadeIn", "duration": 500, "trigger": "afterPrevious" }

// Element 2 — starts after element 1 finishes, plus 200ms pause
{ "type": "fadeIn", "duration": 500, "trigger": "afterPrevious", "delay": 200 }

// Element 3 — starts after element 2 finishes, plus 200ms pause
{ "type": "fadeIn", "duration": 500, "trigger": "afterPrevious", "delay": 200 }
Pattern 2: Simultaneous entrance (multiple elements at once)

Use withPrevious on elements that should appear together:

// Element 1
{ "type": "fadeIn", "duration": 500, "trigger": "afterPrevious" }

// Element 2 — plays at the same time as Element 1
{ "type": "fadeIn", "duration": 500, "trigger": "withPrevious" }
Pattern 3: Auto-play sequence on slide entry

All afterPrevious — the entire chain plays automatically when the slide appears:

// Title fades in automatically
{ "type": "fadeIn", "duration": 800, "trigger": "afterPrevious" }

// Subtitle fades in after title, with a 300ms gap
{ "type": "fadeIn", "duration": 600, "trigger": "afterPrevious", "delay": 300 }

// Divider line wipes in after subtitle
{ "type": "wipeIn", "direction": "right", "duration": 400, "trigger": "afterPrevious", "delay": 200 }

// Content cards fly in one by one
{ "type": "flyIn", "direction": "bottom", "duration": 600, "trigger": "afterPrevious", "delay": 200 }
{ "type": "flyIn", "direction": "bottom", "duration": 600, "trigger": "afterPrevious", "delay": 200 }
Pattern 4: Multiple animations on one element

An element can have multiple animations that play in sequence. Use order to control sequence:

"animations": [
  { "type": "fadeIn", "duration": 300, "trigger": "afterPrevious", "order": 0 },
  { "type": "spin", "degrees": 72, "duration": 900, "trigger": "afterPrevious", "order": 1 }
]
Pattern 5: Rotating wheel across slides

Use a group with a base rotation that changes per slide + a spin animation:

// Slide 2: rotation 0, spin +72
{ "type": "group", "rotation": 0, "animations": [
    { "type": "fadeIn", "duration": 300, "trigger": "afterPrevious", "order": 0 },
    { "type": "spin", "degrees": 72, "duration": 900, "trigger": "afterPrevious", "order": 1 }
]}

// Slide 3: rotation 72, spin +72
{ "type": "group", "rotation": 72, "animations": [
    { "type": "fadeIn", "duration": 300, "trigger": "afterPrevious", "order": 0 },
    { "type": "spin", "degrees": 72, "duration": 900, "trigger": "afterPrevious", "order": 1 }
]}

// Slide 4: rotation 144, spin +72
{ "type": "group", "rotation": 144, "animations": [...same...] }

Each slide starts where the previous left off (base rotation = previous base + spin degrees).

Pattern 6: Click-to-reveal (interactive)

Use onClick for elements that should appear only on click:

// Visible immediately
{ "type": "fadeIn", "duration": 500, "trigger": "afterPrevious" }

// Appears on first click
{ "type": "fadeIn", "duration": 500, "trigger": "onClick" }

// Appears on second click
{ "type": "flyIn", "direction": "left", "duration": 600, "trigger": "onClick" }

Layout Reference

Slide: 13.333" x 7.5". Safe area: x=0.5 to x=12.833, y=0.5 to y=7.0.

Y=0.4–0.5    Title area         (h ~ 1.0–1.5)
Y=1.8–2.0    Content start      (h ~ 4.0)
Y=6.0–6.5    Footer / source    (h ~ 0.5)
Common column layouts
LayoutColumn 1Column 2Column 3
2-colx=0.5, w=5.9x=6.8, w=5.9—
3-colx=0.5, w=3.8x=4.7, w=3.8x=8.9, w=3.8
4-colx=0.5, w=2.83x=3.67, w=2.83x=6.83, w=2.83

Gap between columns: ~0.4".

Centering N items horizontally

Formula: given itemW, gap, and N items:

  • totalW = N * itemW + (N-1) * gap
  • startX = (13.333 - totalW) / 2
  • Each item: x = startX + i * (itemW + gap)
Placing items in a circle

For N items on a circle of radius R centered at (cx, cy), item size s:

  • angle_i = i * (360 / N) - 90 (start from top)
  • x = cx + R * cos(angle_i) - s/2
  • y = cy + R * sin(angle_i) - s/2

Components (high-level)

These expand into primitive groups automatically. Use position and optional animations.

progressBar
{ "type": "progressBar", "position": { "x": 1, "y": 1, "w": 5, "h": 0.5 },
  "value": 72, "color": "4472C4", "trackColor": "E6E6E6", "showLabel": true }
progressRing
{ "type": "progressRing", "position": { "x": 1, "y": 1, "w": 2, "h": 2 },
  "value": 65, "color": "70AD47", "trackColor": "E6E6E6", "thickness": 0.16, "showLabel": true }
barChart
{ "type": "barChart", "position": { "x": 1, "y": 3, "w": 6, "h": 3 },
  "data": [40, 70, 55, 90], "labels": ["Q1", "Q2", "Q3", "Q4"],
  "colors": ["4472C4", "5B9BD5", "70AD47", "ED7D31"], "showValues": true, "axis": true }
kpiCard
{ "type": "kpiCard", "position": { "x": 1, "y": 1, "w": 3, "h": 1.5 },
  "value": "$1.2M", "label": "Revenue", "delta": "+12%", "accent": "5B9BD5" }
ratingStars
{ "type": "ratingStars", "position": { "x": 1, "y": 1, "w": 4, "h": 0.9 },
  "rating": 4, "max": 5, "color": "FFC000", "emptyColor": "D9D9D9" }
timeline
{ "type": "timeline", "position": { "x": 1, "y": 1.5, "w": 11, "h": 2 },
  "items": [{ "label": "2021", "sub": "Founded" }, { "label": "2022", "sub": "Seed" }],
  "dotColor": "4472C4", "lineColor": "CCCCCC" }
processFlow
{ "type": "processFlow", "position": { "x": 1, "y": 5, "w": 6, "h": 0.8 },
  "steps": ["Plan", "Build", "Test", "Ship"],
  "colors": ["4472C4", "5B9BD5", "70AD47", "ED7D31"], "shape": "chevron" }

Complete Example: Title Slide + Content Slide

{
  "width": 13.333, "height": 7.5,
  "meta": { "title": "Demo", "author": "Agent" },
  "theme": {
    "colors": { "accent1": "4472C4", "accent2": "ED7D31" },
    "majorFont": "Calibri Light", "minorFont": "Calibri"
  },
  "slides": [
    {
      "background": { "type": "gradient", "stops": [{ "position": 0, "color": "0B0B1F" }, { "position": 100, "color": "162447" }], "angle": 135 },
      "transition": "fade",
      "elements": [
        {
          "type": "text", "text": "Presentation Title",
          "position": { "x": 0.8, "y": 2.5, "w": 11.7, "h": 1.2 },
          "fontSize": 48, "bold": true, "color": "FFFFFF", "align": "center", "fontFamily": "Calibri Light",
          "animations": [{ "type": "fadeIn", "duration": 800, "trigger": "afterPrevious" }]
        },
        {
          "type": "text", "text": "Subtitle goes here",
          "position": { "x": 2, "y": 3.8, "w": 9.3, "h": 0.6 },
          "fontSize": 20, "color": "8899BB", "align": "center", "fontFamily": "Calibri Light",
          "animations": [{ "type": "fadeIn", "duration": 600, "trigger": "afterPrevious", "delay": 300 }]
        },
        {
          "type": "shape", "shapeType": "rect",
          "position": { "x": 4.3, "y": 4.6, "w": 4.7, "h": 0.022 },
          "fill": "4472C4",
          "animations": [{ "type": "wipeIn", "direction": "right", "duration": 500, "trigger": "afterPrevious", "delay": 200 }]
        }
      ]
    },
    {
      "background": "FFFFFF",
      "transition": "fade",
      "elements": [
        {
          "type": "text", "text": "Section Title",
          "position": { "x": 0.5, "y": 0.4, "w": 12.3, "h": 1 },
          "fontSize": 36, "bold": true, "color": "2D3436", "align": "center",
          "animations": [{ "type": "fadeIn", "duration": 500, "trigger": "afterPrevious" }]
        },
        {
          "type": "shape", "shapeType": "roundRect",
          "position": { "x": 0.5, "y": 1.8, "w": 3.8, "h": 2.5 },
          "fill": "4472C4",
          "text": [
            { "text": "Card 1", "fontSize": 20, "bold": true, "color": "FFFFFF" },
            { "text": "Description here", "fontSize": 14, "color": "CCDDFF" }
          ],
          "align": "center", "vertAlign": "middle",
          "animations": [{ "type": "flyIn", "direction": "bottom", "duration": 600, "trigger": "afterPrevious", "delay": 200 }]
        },
        {
          "type": "shape", "shapeType": "roundRect",
          "position": { "x": 4.7, "y": 1.8, "w": 3.8, "h": 2.5 },
          "fill": "ED7D31",
          "text": [
            { "text": "Card 2", "fontSize": 20, "bold": true, "color": "FFFFFF" },
            { "text": "More details", "fontSize": 14, "color": "FFE0C0" }
          ],
          "align": "center", "vertAlign": "middle",
          "animations": [{ "type": "flyIn", "direction": "bottom", "duration": 600, "trigger": "afterPrevious", "delay": 200 }]
        },
        {
          "type": "shape", "shapeType": "roundRect",
          "position": { "x": 8.9, "y": 1.8, "w": 3.8, "h": 2.5 },
          "fill": "70AD47",
          "text": [
            { "text": "Card 3", "fontSize": 20, "bold": true, "color": "FFFFFF" },
            { "text": "Third point", "fontSize": 14, "color": "D4EFCC" }
          ],
          "align": "center", "vertAlign": "middle",
          "animations": [{ "type": "flyIn", "direction": "bottom", "duration": 600, "trigger": "afterPrevious", "delay": 200 }]
        }
      ]
    }
  ]
}

Workflow: Modify Existing PPTX

slidej parse original.pptx --no-images -o deck.json   # Step 1: parse
# Edit deck.json (remove `id`, `name`, `srcBase64` fields if present)
slidej generate deck.json -o updated.pptx              # Step 2: regenerate

Workflow: Create from Template

slidej template list                                   # browse
slidej template info pitch-deck                        # see style guide
slidej template use pitch-deck -o deck.json            # export
# Edit deck.json
slidej generate deck.json -o presentation.pptx         # generate

Comments

Markdown supported