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

sveld

v0.40.3

Published

Generate TypeScript definitions and component documentation for your Svelte components.

Readme

sveld

NPM npm downloads to date

sveld generates TypeScript definitions and component documentation (JSON and Markdown) for Svelte component libraries. It statically analyzes props, events, slots, snippets, context, module exports, and rest props, and reads JSDoc where inference isn't enough.

The generated .d.ts files give consumers autocomplete and type checking through the Svelte Language Server and TypeScript, with little effort from the library author. Carbon Components Svelte uses sveld to generate its component types and API metadata.

sveld supports Svelte 3, Svelte 4, Svelte 5 without runes (export let, <slot>, $$restProps), and Svelte 5 runes ($props(), $bindable(), {@render}, callback props).

When to use sveld

If your library is built with SvelteKit's svelte-package, it already emits .d.ts files through svelte2tsx; start there.

sveld is for:

  • JavaScript-first libraries. Components written in plain JavaScript with JSDoc, where you want full editor types without converting to lang="ts".
  • Docs from the same source as the types. JSON and Markdown API docs, generated in the same run.
  • API drift checks. --check diffs the component API against a committed snapshot and fails CI on breaking changes.
  • Richer types from JSDoc. @typedef, @callback, @slot, @event, and context types that plain inference can't produce.

lang="ts" components work too: sveld keeps their type annotations as written.

Install

npm i -D sveld
# or: pnpm i -D sveld / bun i -D sveld / yarn add -D sveld

Quick start

sveld reads the "svelte" field of your package.json as the entry point: the file that re-exports your components.

{
  "svelte": "./src/index.js"
}

CLI

npx sveld                     # writes types/*.d.ts
npx sveld --json --markdown   # also writes COMPONENT_API.json and COMPONENT_INDEX.md

Run npx sveld --help for every flag. Options can also live in a sveld.config.js:

// sveld.config.js
import { defineConfig } from "sveld";

export default defineConfig({
  json: true,
  markdown: true,
});

Vite plugin

// vite.config.ts
import { svelte } from "@sveltejs/vite-plugin-svelte";
import sveld from "sveld";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [svelte(), sveld({ json: true })],
});

The plugin runs during vite build (and during vite dev with watch: true). It also works in Rollup configs.

Node

import { sveld } from "sveld";

const { document, diagnostics, exitCode } = await sveld({
  entry: "./src/index.js",
  json: true,
});

document is the same component API document json: true writes, so you can render your own formats from it. See Options for everything sveld() accepts and returns.

Example

Given this component:

<!-- Button.svelte -->
<script>
  export let type = "button";
  export let primary = false;
</script>

<button {...$$restProps} {type} class:primary on:click>
  <slot>Click me</slot>
</button>

sveld infers prop types and defaults, the forwarded click event, the default slot, and the rest props spread onto <button>:

// types/Button.svelte.d.ts
import { SvelteComponentTyped } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";

type $RestProps = SvelteHTMLElements["button"];

type $Props = {
  /**
   * @default "button"
   */
  type?: string;

  /**
   * @default false
   */
  primary?: boolean;

  children?: (this: void) => void;

  [key: `data-${string}`]: unknown;
};

export type ButtonProps = Omit<$RestProps, keyof $Props> & $Props;

export default class Button extends SvelteComponentTyped<
  ButtonProps,
  { click: WindowEventMap["click"] },
  { default: Record<string, never> }
> {}

The default slot is also typed as a children snippet prop for Svelte 5 consumers, and the data-* index signature lets callers pass data attributes through $$restProps.

Add JSDoc to tighten types and add descriptions:

<script>
  /** @type {"button" | "submit" | "reset"} */
  export let type = "button";

  /**
   * Set to `true` to use the primary variant
   */
  export let primary = false;
</script>
type $Props = {
  /**
   * @default "button"
   */
  type?: "button" | "submit" | "reset";

  /**
   * Set to `true` to use the primary variant
   * @default false
   */
  primary?: boolean;

  children?: (this: void) => void;

  [key: `data-${string}`]: unknown;
};

The runes version (let { type = "button", primary = false, children, ...rest } = $props(), spreading rest and rendering children) produces the same $Props. It has no click event, since runes components take onclick as a prop through rest.

The .d.ts extends SvelteComponentTyped by default, which works for consumers on Svelte 3, 4, and 5. Set typesOptions.format: "component" (--types-format=component) to emit the Svelte 5 Component type instead. See Output.

JSON and Markdown

npx sveld --markdown documents the same component in COMPONENT_INDEX.md:

## `Button`

### Props

| Prop name | Required | Kind | Reactive | Binding | Type | Default value | Description |
| :- | :- | :- | :- | :- | :- | :- | :- |
| type | No | <code>let</code> | No | -- | <code>"button" &#124; "submit" &#124; "reset"</code> | <code>"button"</code> | -- |
| primary | No | <code>let</code> | No | -- | <code>boolean</code> | <code>false</code> | Set to `true` to use the primary variant |

### Slots

| Slot name | Default | Props | Fallback | Description |
| :- | :- | :- | :- | :- |
| -- | Yes | <code>Record&lt;string, never> </code> | <code>Click me</code> | -- |

### Events

| Event name | Type | Detail | Description |
| :- | :- | :- | :- |
| click | forwarded | -- | -- |

npx sveld --json writes the same data to COMPONENT_API.json, validated by a JSON Schema that ships with the package. An excerpt of the prop entry:

{
  "name": "type",
  "kind": "let",
  "type": "\"button\" | \"submit\" | \"reset\"",
  "typeSource": "jsdoc",
  "value": "\"button\"",
  "isRequired": false,
  "reactive": false
}

See Output for the full shape.

In CI

Commit COMPONENT_API.json, then gate pull requests on API changes and inference gaps:

npx sveld --check    # exit 3 on a breaking API change against the snapshot
npx sveld --strict   # exit 4 when a prop fell back to `any`, a tag was dropped, ...
sveld --check: 2 API changes detected against "COMPONENT_API.json".
Suggested semver bump: major.

  Button
    [BREAKING] prop "target" added (required)
    [BREAKING] prop "href" removed

See CI for exit codes, the change classification table, diagnostic codes, and how to ignore a diagnostic.

JSDoc tags

| Tag | Use it to | Example | | :--------------------------------------------------------------------- | :-------------------------------------------------------- | :--------------------------------------------- | | @type | Type a prop | @type {"sm" \| "md" \| "lg"} | | @default | Override the inferred default shown in docs | @default () => true | | @typedef | Declare a shared, exported type | @typedef {{ id: string }} Item | | @property | Document a field of a @typedef {object} or event detail | @property {string} [label] - Label text | | @callback | Declare a function type | @callback OnChange + @param/@returns | | @slot / @snippet | Type slot or snippet props | @slot {{ item: Item }} row | | @event | Type a dispatched event's detail | @event {{ id: string }} save | | @param / @returns | Type an exported function | @param {string} id | | @restProps | Name the element rest props are spread onto | @restProps {button \| a} | | @extendProps | Extend another component's props | @extendProps {"./Button.svelte"} ButtonProps | | @template / @generics | Declare generics in a JS component | @template {Item} [T=Item] | | @bindable | Document a prop's bind: contract | @bindable writable | | @deprecated | Mark a prop, event, slot, or export deprecated | @deprecated Use "size" instead. | | @ignore / @internal | Hide from every output | @internal | | @since / @see / @example | Pass structured tags through to all outputs | @since 1.2.0 | | {@link} | Link in a description | {@link https://example.com\|docs} | | @csspart / @cssprop | Document shadow-DOM styling hooks | @cssprop {Color} [--bg=white] | | @sveld-ignore | Suppress a diagnostic | @sveld-ignore sveld/prop-unknown-type | | <!-- @component --> | Document the component itself | <!-- @component Renders a button. --> |

Context types come from setContext calls with no tag needed. See Context.

Docs

  • Options: every option and CLI flag, the config file, the Vite plugin, sveld() and its result, and sveld/browser.
  • JSDoc tags: how types are inferred and every tag sveld reads.
  • Output: .d.ts formats, JSON output and schema, Markdown, entry exports, custom element metadata, and custom output formats.
  • CI: exit codes, --check for API drift, --strict and diagnostic codes, and @example checking.
  • Troubleshooting

Try sveld in the browser at sveld.onrender.com (source in playground/).

Requirements

  • Node 22 or later, or Bun. sveld is ESM-only.
  • A sveld.config.ts needs a runtime that strips TypeScript: Bun, or Node 22.18+ / 23.6+.
  • The optional checkExamples check for TS/JS examples needs typescript 7+ and a tsconfig.json. Nothing else loads TypeScript.
  • Your installed Svelte version doesn't affect parsing. sveld parses with sveast, kept in parity with svelte/compiler.

Contributing

See the contributing guidelines.

License

Apache-2.0