Skip to content

svebcomponents

Boilerplate-free, type-safe, server-rendered web components — with Svelte.

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.

src/FavoriteNumber.svelte
<svelte:options customElement="favorite-number" />
<script lang="ts">
let { value }: { value: number } = $props();
</script>
<p>My favorite number is {value}</p>
package.json
{
"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:

Terminal window
svebcomponents

That 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>
Svelte customElement: trueWith svebcomponents
Attribute types, reflectionhand-written <svelte:options customElement={...}>inferred from your $props() types
Packagingassemble your own pipelinepackage.json exports are the config
Types for consumersnone.d.ts plus a custom elements manifest
Server renderingnonedeclarative shadow DOM via Lit’s ElementRenderer
Hydrationshadow root wiped, component re-mountedserver DOM adopted in place
Evaluated twicecustomElements.define throwsidempotent

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.