npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sanity-labs/slides

v0.1.0

Published

Brand-locked PowerPoint generation for LLMs. Write a slide template in React; Claude (or any MCP client) writes the deck through the bundled MCP server without drifting on fonts, colors, or layout.

Readme

@sanity-labs/slides

Brand-locked PowerPoint generation for LLMs. Write your slide template in React; Claude writes the deck.

ci npm

A template is a React project. Each slide type is a component + a Zod schema. The bundled MCP server reads your template and exposes it to Claude (or any MCP client) as auto-derived tools. The LLM can pick slide types and fill props, but it cannot pick fonts, colors, or layout — those are locked in the template.

One package on npm. Four subpath exports. One CLI bin.


Quickstart

1. Scaffold a template

npx @sanity-labs/slides scaffold my-template
cd my-template
pnpm install
pnpm dev    # opens the hot-reloading viewer at http://localhost:5173

You get a working template with one starter slide (Cover) and a Vite-backed dev viewer. Edit anything under src/ and the page updates.

2. Build it

pnpm build

That emits dist/index.js — the file the MCP server will import.

3. Wire it into Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (or the equivalent on your OS):

{
  "mcpServers": {
    "slides": {
      "command": "npx",
      "args": [
        "-y",
        "@sanity-labs/slides",
        "serve",
        "--template",
        "/absolute/path/to/my-template/dist/index.js",
        "--output",
        "/Users/you/Desktop"
      ]
    }
  }
}

Restart Claude.

4. Ask

"Make me a 5-slide Q4 review deck with my template."

Claude calls slides_list to learn what slide types exist, fills props from the conversation, calls slides_create, and hands you back the absolute path to the .pptx.

Total setup time once you have a template: about two minutes.


What you ship when you build a template

my-template/
├── package.json
├── src/
│   ├── index.ts          # the Template value — tokens, fonts, components map
│   ├── preview.tsx       # canonical slide order shown in the viewer
│   └── components/
│       └── Cover.tsx     # one component = one slide type = one MCP tool
└── dist/                 # `pnpm build` output — what the MCP server imports

A slide type is a React component with a Zod schema next to it:

// src/components/Quote.tsx
import { Slide, Box, Text } from '@sanity-labs/slides';
import { z } from 'zod';

export const QuoteSchema = z
  .object({
    quote: z.string().min(1).describe('The pull quote. Plain text.'),
    attribution: z.string().optional().describe('Optional speaker.'),
  })
  .strict();

export const Quote = ({ quote, attribution }: z.infer<typeof QuoteSchema>) => (
  <Slide>
    <Box rect={{ x: 0, y: 0, w: 960, h: 540 }} fill={{ kind: 'solid', color: '#ff5500' }} />
    <Box rect={{ x: 60, y: 200, w: 840, h: 160 }}>
      <Text textStyle={{ fontFamily: 'display', fontSize: 48, foregroundColor: '#0b0b0b' }}>
        “{quote}”
      </Text>
    </Box>
    {attribution ? (
      <Box rect={{ x: 60, y: 380, w: 840, h: 32 }}>
        <Text textStyle={{ fontFamily: 'mono', fontSize: 14, foregroundColor: '#0b0b0b' }}>
          — {attribution}
        </Text>
      </Box>
    ) : null}
  </Slide>
);

Register it in src/index.ts:

components: {
  Quote: defineTemplateComponent({
    component: Quote,
    schema: QuoteSchema,
    description: 'Pull-quote slide. Use sparingly between sections.',
  }),
}

pnpm build and Claude will see a new slides_add_quote tool on its next request.

The Zod schema field .describe(...) text becomes the LLM-facing documentation. The description on the template entry tells Claude when to pick the type.


What Claude sees

After you wire the MCP server in, Claude has three tools, auto-derived from your template:

| Tool | Purpose | | ------------------- | ------------------------------------------------------------------------- | | slides_list | Lists every slide type with its description. | | slides_add_<type> | Validates a single slide's props against the Zod schema. | | slides_create | Takes { title, slides }, writes the .pptx, returns the absolute path. |

The package also ships an LLM skill describing the calling convention. Print it with:

npx @sanity-labs/slides skill

Paste it into a Claude project's knowledge sources to teach the model the workflow up front.


Subpath layout

One npm package, four import surfaces:

| Subpath | Contents | | ------------------------------ | ----------------------------------------------------------------------- | | @sanity-labs/slides | Renderer + Template type + Slide/Box/Text primitives + runtime. | | @sanity-labs/slides/mcp | createSlideServer, renderSlides — programmatic MCP API. | | @sanity-labs/slides/dev | Dev-viewer building blocks (composeDeck, DeckViewer). | | @sanity-labs/slides/scaffold | scaffoldTemplate({ target, name }) — programmatic scaffold API. | | @sanity-labs/slides/skill | The bundled SKILL.md Markdown file. |

Vite, tailwind, react-dom, lucide-react and friends are listed as optional peer dependencies, only required when you import /dev. Users wiring the MCP into Claude pay for none of that install weight.

Bins

| Bin | Purpose | | ------------ | ---------------------------------------------------------------------------------------------- | | slidesctl | The CLI the MCP server runs on. Subcommands: serve, generate, list, scaffold, skill. | | slides-dev | The Vite-backed dev viewer used by template authors' pnpm dev. |

npx @sanity-labs/slides … resolves to the slidesctl bin (matches the package's short name).


Reference template

The Sanity-branded reference template lives in its own repo at sanity-labs/slides-template. It's the most thorough authoring example — eight slide types, brand chrome helpers, embedded raster assets, and SVG textures — and it dogfoods this package by consuming @sanity-labs/slides exactly the way an external user would.

To use it:

git clone [email protected]:sanity-labs/slides-template.git
cd slides-template
pnpm install
pnpm build

Then point Claude at it the same way as any other template:

"args": ["-y", "@sanity-labs/slides", "serve", "--template", "/abs/path/to/slides-template/dist/index.js"]

Repo layout

src/
├── index.ts              # root: renderer + Template + primitives
├── cli.ts                # `slidesctl` bin
├── core/                 # renderer + PPTX runtime
├── mcp/                  # MCP server framework
├── dev/                  # browser dev viewer (incl. slides-dev bin)
├── scaffold/             # scaffold logic + template-base/
└── __tests__/            # framework smoke tests + synthetic fixture template

scripts/copy-static-assets.mjs    copies non-TS assets (CSS, template-base, shims) into dist/
docs/                             architecture, testing strategy
.changeset/                       changesets config + queued release notes
.github/workflows/                CI + release pipeline
SKILL.md                          LLM skill — served by `slidesctl skill`

Contributing

See docs/architecture.md for the layer pyramid.

pnpm install
pnpm verify    # typecheck + lint + format + build + test + knip + verify-bins

Releases use Changesets:

pnpm changeset    # describe what changed (single package — just pick patch/minor/major)
git commit -am "feat: …"
# A "Version Packages" PR opens automatically on push to main.
# Merge that PR and the release workflow publishes @sanity-labs/slides to npm.

License

MIT