OpenElement — Web Standards Lab
THE WEB, composed.

A Web Components-native application framework — beautiful, static-first applications composed from real browser primitives.
§1 — Element
One durablecontract.
Custom Elements are the application component contract — not a renderer integration, not a leaf-widget format. Write the element once; it renders on the server and upgrades in the browser.
import { element, OpenElement, property } from '@openelement/element'
@element('open-counter', { root: 'shadow-open' })
export class OpenCounter extends OpenElement {
@property({ reflect: true, attribute: 'count', type: Number })
count = 0
render() {
return (
<button type="button">Count: {this.count}</button>
)
}
}
// SSR: <open-counter count="0"> + DSD shadow root.
// Markup paints and reads with no JavaScript.§2 — Declarative Shadow DOM
The server writes HTML.The browser upgrades it.
DSD is a first-class server output — no client re-render, no double payload. The compiled default root is light DOM today; the markup is the application either way.
<open-counter count="0">
<template shadowrootmode="open">
<button>0</button>
</template>└─ <button> → markup available/readable
upgrade → signals/handlers bound§3 — Islands
Upgradeselectively.
Interactive regions hydrate on your schedule. Non-interactive regions ship no JavaScript of their own.
First-screen controls: imported and upgraded as early as possible.
Non-critical interaction, scheduled into idle opportunities; actual timing depends on the scheduler fallback.
IntersectionObserver gates hydration until scroll-in.
Client-only, for what the server cannot know.
§4 — Output
Static first.Deployable anywhere.
§5 — Begin
Begin.
$npm create @openelement@alpha my-appThe @alpha dist-tag resolves to 1.0.0-alpha.9 — the current baseline.
Facts behind the feeling
Continue the composition.
Every number and claim on this page is sourced from the repository’s release and benchmark truth.