Detailed documentation for Shadowbind can be found on Github.

Six months ago I opened an editor and a tutorial from Google, and started building my first web component. I felt a rush as “Hello world” appeared in my browser. I had created a self-contained component without running CLI commands, without bundling, without even running a server at all.

Web components are a new browser standard. They allow you to create your own HTML elements. Think of the <audio> or <video> elements, powerful little tags that are easy to drop in but surprisingly sophisticated. Now imagine being able to create your own HTML elements. Your music app could have elements for volume sliders, for progress bars, for album art. Your store could have elements for product galleries, recommended products, reviews, spec sheets and add to cart buttons. This is a powerful pattern we’ve seen in many frameworks, but now it’s standardized, interoperable. And around 80% of users on the web have access to them right now.

Toss some HTML, CSS and JS into a file with a descriptive name and snap together components like Legos to build an app.

I continued building, adding a counter to my first little component, adding buttons. I tested out the encapsulation, scoped CSS, lifecycle events and attached my first template element. But while web components have wonderful low-level APIs, they do not have high-level APIs. While they are so close to being enough, they do fall short.

Shadowbind was born in that moment. In web components, I had found something standard, where the component system would be the burden of the browser, and something closer to the platform, where my code would be safe from deprecation and build tools could be optional. But now I also wanted expressiveness, elegant and powerful APIs. I wanted to write a little and do a lot, to write clean code, to hack out fun ideas.

Part of what’s notable about Shadowbind is what it doesn’t do. It is a JavaScript framework, but it has no dependencies, no compiler, no build scripts, no CLI, no dev server, no JSX, no Typescript mandate, and no use of planned JS features. It is only 6KB. It has a strict, philosophical limitation of scope that will never change.

Shadowbind’s aim is to bridge the small but undeniable gap between the capabilities of web components and the requirements of a fully-fledged application framework, and, explicitly, nothing else.

<playing-card suit="spades" rank="8"></playing-card>

The above is a typical web component, as it appears in HTML. Clean, no? A primer on the technology:

Web components are shrewdly targeted at a single class of pain points: abstraction and encapsulation. In other words, the challenge of dividing your app into little self-contained components.

Google developed and released web component support in 2012, but it took five years to develop a version supported by all browsers. The feature is currently available for around 80% of users and the remaining browsers have committed to releasing support. Firefox expects to release support this year.

They contain internal content and styles (this component might look like a playing card).

They can contain functionality (perhaps the card could be flipped by adding a flipped attribute).

attribute). Thanks to a feature called shadow DOM, the internal logic is inaccessible from the outside. The encapsulation is so good that frameworks can’t see inside them, cannot mess with their internals. This is why web components can be used with any framework.

Shadowbind addresses a major missing feature of web components: dynamic content. It answers the challenge of piping your ever-changing data into your components, managing and manipulating it once present, and binding it to the UI.

Shadowbind components look an awful lot like web components, which isn’t surprising since they are web components. Web components are defined with JavaScript classes like this:

class MyComponent extends HTMLElement {}

customElements.define('my-component', MyComponent)

And Shadowbind components are almost identical:

class MyComponent extends Shadowbind.Element {}

Shadowbind.define({ MyComponent })

In either case, if you have any HTML Elements in the DOM called <my-component></my-component> they will transition from an inline element similar to a span to a fully-fledged web component when you call define. Since any valid web component is also a valid Shadowbind component, if you want to migrate an existing web component to Shadowbind, all you have to do is change its declaration as above, and you’re done.

The core value proposition of Shadowbind comes with two declarative methods it provides: subscribe and template .

subscribe allows you to mark the data you want to be available in your component. It can come through HTML DOM attributes, JavaScript property calls, or a data store like Redux, for which it provides first-party middleware to make integrating Redux incredibly simple.

template allows you to attach the inner HTML document that will be hidden from the outside. It supports an HTML-based data-binding syntax very loosely inspired by Vue.

The declarative style results in components that are remarkably easy to read.

import Shadowbind from 'shadowbind'

import scopedStyles from './styles' class PlayingCard extends Shadowbind.Element {

subscribe() {

return {

suit: 'attr',

rank: 'attr',

flipped: 'attr'

}

}

template() {

return `

<style>${scopedStyles}</style>

<main class:is-flipped="flipped">

<div class="front">

<card-label attr:rank="rank"></card-label>

<card-body attr:suit-icon="suit"></card-body>

</div>

<div class="back">

<card-back></card-back>

</div>

</main>

`

}

} Shadowbind.define({ PlayingCard })

With subscribe and template , Shadowbind’s work is almost complete. Yes, Shadowbind provides lifecycle callbacks and an API for form inputs, but you have seen pretty much all you need to know about the framework in just a minute or two. That limited scope is a very intentional choice.

It’s important to note that web components provide precisely zero functionality not already provided by React, Angular, Vue, Polymer and all the rest. In fact, they provide much, much less functionality. When you build your components with Shadowbind, you add some powerful features to web components… that still leave you far short. This is no mistake. This is the point.

Six months ago when I embarked on this journey, I made one gigantic assumption — that lots of other people, besides just me, want to build their apps out of the simplest possible building blocks. If you have a platform-enforced and portable component system as well as an elegant strategy for handling dynamic data, what else is really missing? On one hand, you’re missing a lot. On the other hand, are you missing anything you really want?

Existing frameworks provide CLIs and build tools, linters and server-rendering pipelines. More broadly, they each provide what you might call a “unified development environment” with their own sets of commands, starter kits, best practices and component libraries. The most popular of these frameworks do not use traditional HTML, CSS and JS at all, so you might even be choosing a new programming or markup language by making your choice.

To be frank, I’ve never wanted any of that stuff. I don’t want to learn one of multiple dueling supersets of JavaScript. I don’t want to be married to Babel because my framework uses planned JavaScript syntax that hasn’t even shipped to a single platform yet. I only want a linter on projects big enough to warrant it, and I don’t want to use a fancy development server that can break on me. I don’t want to install hundreds of megabytes of code before I can write a single line of my own. I want to deeply understand the technologies I use, and I don’t want the code I write to be chopped into a million pieces, transformed, recombined and dumped on the page. I want my framework to do almost nothing … instead of almost everything.

I just want to toss some HTML, CSS and JS into a file with a descriptive name, and snap together my components like Legos to build an app.

Shadowbind is for those who are sick of all the tooling, who are demoralized by unfixable build-system bugs, who believe that creating apps should be about confidently molding and shaping an experience instead of following checklists and punching buttons on an endless control panel. Shadowbind is for those who want to rediscover the joy of creation, the sense of productive flow. No longer fighting so many levels of failure-prone machinery, but free.

If you are interested in the project, check out the GitHub, and if you like it, leave a star!