The Complete Web Components Framework
Build modern components with strict TypeScript, zero dependencies, and a clean functional API. Designed for speed, standards compliance, and productivity.
๐น๏ธ Try it on Codepen.io.
- โก Blazing Fast: Minimal runtime, instant updates, zero dependencies.
- ๐จ JIT CSS: On-demand, utility-first styling directly in your HTML at runtime.
- ๐ช No Build Necessary: Instant development feedback, no bundling required.
- ๐งโ๐ป TypeScript First: Strict types, intellisense, and safety everywhere.
- ๐งฉ Functional API: No classes, no boilerplateโjust pure functions.
- ๐ ๏ธ SSR & HMR Ready: Universal rendering and instant hot reloads.
- ๐ Extensible: Directives, event bus, store, and more for advanced use cases.
- ๐ Developer Friendly: Clean docs, examples, and a welcoming community.
- Install:
npm install @jasonshimmy/custom-elements-runtime - Create a Component:
import {
component,
ref,
html,
useEmit,
useProps,
} from '@jasonshimmy/custom-elements-runtime';
component('my-counter', () => {
const props = useProps({ initialCount: 0 });
const count = ref(props.initialCount);
const emit = useEmit();
const handleClick = () => {
count.value++;
emit('update:initial-count', { count: count.value });
};
return html`
<button
type="button"
class="px-4 py-2 bg-primary-500 text-white rounded"
@click.prevent="${handleClick}"
>
Count: ${count.value}
</button>
`;
});- Use in HTML:
<my-counter
initial-count="5"
@update:initial-count="handleCountUpdate"
></my-counter>
<script>
function handleCountUpdate(event) {
console.log('Count updated to:', event.detail.count);
}
</script>- Enjoy instant reactivity and type safety!
Below is the complete list of public symbols exported by the runtime and its named subpaths (root entry + subpath entries).
Package: @jasonshimmy/custom-elements-runtime
| Export | Description |
|---|---|
component |
Define a custom element with the functional component API. |
html |
Template tag function producing runtime VNodes from template literals. |
css |
Define component-scoped/JIT styles or register stylesheets. |
ref |
Create a reactive reference object with a .value property. |
computed |
Create a derived, read-only reactive value from other reactives. |
watch |
Register watchers reacting to changes in reactive values. |
useProps |
Hook to declare/consume typed component props with defaults. |
useEmit |
Hook returning an emit function for dispatching custom events. |
useOnConnected |
Hook that runs a callback when the component connects. |
useOnDisconnected |
Hook that runs a callback when the component disconnects. |
useOnAttributeChanged |
Hook observing host attribute changes. |
useOnError |
Hook to register a component-level error handler. |
useStyle |
Hook to register or compute component styles at runtime. |
unsafeHTML |
Insert raw HTML into a template (unsafe; use carefully). |
decodeEntities |
Utility to decode HTML entities in strings. |
Package: @jasonshimmy/custom-elements-runtime/directives
| Export | Description |
|---|---|
when |
Conditional rendering: render children when the condition is true. |
each |
Iterate arrays and render a VNode per item with stable keys. |
match |
Fluent branching API (when/otherwise/done) returning VNodes. |
anchorBlock |
Create a stable anchor VNode used as block boundaries. |
Package: @jasonshimmy/custom-elements-runtime/directive-enhancements
| Export | Description |
|---|---|
unless |
Inverse of when (render when condition is false). |
whenEmpty |
Render content when a collection is empty or null. |
whenNotEmpty |
Render content when a collection has items. |
eachWhere |
Filter + iterate; render only items matching a predicate. |
switchOnLength |
Render different content based on array length cases. |
eachGroup |
Group array items by a key and render per-group content. |
eachPage |
Render a paginated subset (page) of items. |
switchOnPromise |
Render loading/success/error/idle states for async data. |
whenMedia |
Render content when a CSS media query matches. |
mediaVariants |
Map of responsive media queries (sm, md, lg, xl, 2xl, dark). |
responsiveOrder |
Ordered breakpoint keys used by responsive helpers. |
responsive |
Per-breakpoint helpers (sm/md/lg/xl/2xl/dark). |
whenVariants |
Compose multiple variants (e.g., dark + lg) into one media query. |
responsiveSwitch |
Render different content for different breakpoints. |
switchOn |
Fluent switch/case API matching a value to content. |
Package: @jasonshimmy/custom-elements-runtime/transitions
| Export | Description |
|---|---|
Transition |
Wrap content with enter/leave transition metadata consumed by the runtime. |
TransitionGroup |
Animate lists with enter/leave/move transitions for children. |
transitionPresets |
Built-in transition presets (fade, slide, scale, etc.). |
createTransitionPreset |
Create a reusable transition preset programmatically. |
getTransitionStyleSheet |
Obtain the CSSStyleSheet used by the transition runtime. |
| Types | TransitionClasses, TransitionHooks, TransitionOptions, TransitionGroupOptions |
Package: @jasonshimmy/custom-elements-runtime/event-bus
| Export | Description |
|---|---|
EventHandler |
Type: callback signature used by the event bus. |
GlobalEventBus |
Class: singleton implementing a global pub/sub event bus. |
eventBus |
Proxy: lazy proxy to the singleton GlobalEventBus instance. |
emit |
Emit a global event with an optional payload. |
on |
Register a handler for a global event (returns unsubscribe function). |
off |
Remove a handler for a global event. |
once |
Register a one-time handler; returns a Promise resolving with the payload. |
listen |
Listen for native CustomEvent on the global event bus (returns unsubscribe). |
Package: @jasonshimmy/custom-elements-runtime/store
| Export | Description |
|---|---|
Store |
Interface describing subscribe / getState / setState. |
createStore |
Create a simple observable store that notifies subscribers. |
Package: @jasonshimmy/custom-elements-runtime/router
| Export | Description |
|---|---|
useRouter |
Create and use a router instance configured with routes (client & SSR). |
initRouter |
Initialize the router and register router-view / router-link. |
matchRoute |
Match a path against configured routes and extract params. |
matchRouteSSR |
SSR-friendly wrapper for route matching. |
parseQuery |
Parse a query string into a key/value map. |
resolveRouteComponent |
Resolve/load a route's component (supports async loaders + caching). |
| Types | Route, RouteState, RouteComponent, GuardResult, RouterLinkProps, RouterLinkComputed, RouterConfig |
Package: @jasonshimmy/custom-elements-runtime/ssr
| Export | Description |
|---|---|
renderToString |
Render a VNode tree to HTML for server-side rendering. |
VNode (type) |
The runtime VNode shape used by renderers and SSR. |
Package: @jasonshimmy/custom-elements-runtime/css or @jasonshimmy/custom-elements-runtime/css/style.css
| Export | Description |
|---|---|
style.css |
CSS export that contains CSS variables and a base reset. |
Package: @jasonshimmy/custom-elements-runtime/css/variables.css
| Export | Description |
|---|---|
variables.css |
CSS export that contains design tokens (colors, fonts, etc.). |
Package: @jasonshimmy/custom-elements-runtime/css/reset.css
| Export | Description |
|---|---|
reset.css |
CSS export that contains a base reset for styles. |
Explore the complete documentation for every runtime feature:
- ๐ฏ Functional API - Start here! Complete guide to the modern functional component API
- ๐งฉ Template - Template syntax and html function
- ๐งญ Directives - Conditional rendering with
when,each, andmatch - ๐ ๏ธ Directive Enhancements - Advanced directive utilities:
unless- Inverse ofwhenwhenEmpty/whenNotEmpty- Collection checkseachWhere- Filtered iterationswitchOnLength- Render based on array lengtheachGroup- Group and render itemseachPage- Pagination supportswitchOnPromise- Async state renderingwhenMedia- Media query responsive renderingresponsive- Responsive utilities
- ๐ Bindings - Data binding with
:prop,@event,:model,:class,:style - ๐ Events Deep Dive - Custom event emission and handling patterns
- ๐ฌ Transitions Guide - Animation and transition effects
- ๐จ JIT CSS - On-demand utility-first styling system
- ๐ Prose Typography - Beautiful typography for long-form content
- ๐ข Event Bus - Global event system for cross-component communication
- ๐๏ธ Store - Global state management
- ๐ฆ Router - Client-side routing
- ๐ค Cross-Component Communication - Patterns for component interaction
- ๐ฎ Virtual DOM - VDOM implementation and performance details
- ๐ SSR - Server-side rendering support
- โป๏ธ HMR - Hot module replacement
- ๐ก๏ธ Infinite Loop Protection - Runtime safeguards against infinite loops
- ๐ Secure Expression Evaluator - Safe evaluation of dynamic expressions in templates
- โ๏ธ React Integration - Using components in React apps
- ๐ฆ Vue Integration - Using components in Vue apps
๐ ฐ๏ธ Angular Integration - Using components in Angular apps- ๐ฅ Svelte Integration - Using components in Svelte apps
- ๐ง Troubleshooting - Common issues and solutions
For examples and implementation details, explore the source code in src/lib/.
- Showcase your components! Open a PR to add your project to our gallery.
- Questions or ideas? Start a discussion or open an issue.
- Contribute: We welcome PRs for docs, features, and examples.
- โค๏ธ Like what you see? Support ongoing development on Patreon
Custom Elements Runtime is a labor of love built to make modern web development faster and more expressive. If it's helping you build better components, consider supporting me on Patreon to help keep the momentum going.
Your support helps fund continued development, documentation, and community engagement. Every bit helpsโthank you!