No boilerplate options
Your $props() TypeScript types become attribute names, converters and
reflection settings. Write increments: number, and increments="5"
arrives as a number.
Svelte already allows compiling to custom elements today. svebcomponents is the toolchain for everything that comes next: packaging it, typing it for the people who use it, and rendering it on the server.
No boilerplate options
Your $props() TypeScript types become attribute names, converters and
reflection settings. Write increments: number, and increments="5"
arrives as a number.
package.json is the build config
Declare where the built files go in exports, then run the svebcomponents
command. No bundler config, no entry list.
Typed for your consumers
A custom elements manifest plus .d.ts, so editors autocomplete your tags
and querySelector comes back typed — in Svelte, React, Vue or plain HTML.
Server-rendered, and hydrated
Declarative shadow DOM on the server; the browser adopts that DOM in place instead of throwing it away. Svelte’s own custom elements can’t do this.
<svelte:options customElement="favorite-number" />
<script lang="ts"> let { value }: { value: number } = $props();</script>
<p>My favorite number is {value}</p>{ "exports": { ".": { "types": "./dist/client/FavoriteNumber.d.ts", "default": "./dist/client/FavoriteNumber.js" } }, "customElements": "custom-elements.json"}@svebcomponents/build installs a command called svebcomponents. Run it:
svebcomponentsThat is the whole setup. It compiles the component, infers that value is a
Number attribute, emits declarations and a custom elements manifest, and
makes registration idempotent. Consumers write:
<favorite-number value="42"></favorite-number>customElement: trueSvelte customElement: true | With svebcomponents | |
|---|---|---|
| Attribute types, reflection | hand-written <svelte:options customElement={...}> | inferred from your $props() types |
| Packaging | assemble your own pipeline | package.json exports are the config |
| Types for consumers | none | .d.ts plus a custom elements manifest |
| Server rendering | none | declarative shadow DOM via Lit’s ElementRenderer |
| Hydration | shadow root wiped, component re-mounted | server DOM adopted in place |
| Evaluated twice | customElements.define throws | idempotent |
Start building
The Getting Started guide walks through the template repo, your first component, and a SvelteKit app that consumes it.
Or read why it exists
What is svebcomponents? covers the problems it solves and where it fits next to Lit and plain Svelte custom elements.