Skip to content

The no-bullshit, bullshit web component framework -- lightweight, React-ish custom elements with signals for reactivity

Notifications You must be signed in to change notification settings

toddpress/glint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Glint ✨ [WIP]

🔥 The no-bullshit, bullshit web component framework 🔥

🚀 Glint is a fast, build-less native web component-based UI framework that makes reactive web development simple and fun again — All without the virtual DOM, complex hooks, or build tools.

  • ✅ No Babel, No JSX, No Webpack
  • ✅ Native Web Components & Scoped Styles
  • ✅ Fine-Grained Reactivity Without Re-Renders
  • ✅ Auto-Batching, No useEffect Hell
  • ✅ Built-in State Management, No Context API Needed

💡 Think React, but simpler, faster, and without the bloat.

⚠️ Disclaimer

👉 Use something like lit-element or React/Preact if you require production-grade component abstractions. Glint is conceptually awesome, but it's not yet ready for prime time -- just remember to check back soon! And please contribute 🙏

Glint is still very much a work in progress: Features, APIs, and documentation may be assumed incomplete and are subject to change. While we’re actively developing and iterating, please expect breaking changes or inconsistencies between the code and the docs. In essence... Proceed with caution if you need production stability!

MVP Todo

  • Arbitrary property binding, e.g. :value=${mySignal}. Only form inputs' value property has partial support.
  • Devise suitable data structure for more direct updates to a signals dependent nodes (and attr maybe), e.g. Map<Signal, Node>
  • Scoped and global styling; e.g. via css tag function and, for scoped, css.scoped

🚀 Quick Start

Glint runs directly in the browser—no setup required. Check it out on codepen!

1️⃣ Install (Coming soon!)

Via npm:

npm install glint-js

or just use CDN:

<script type="module" src="https://cdn.jsdelivr.net/npm/glint-js"></script>

2️⃣ Define a custom component

import { component, signal, html } from "glint-js";

component("counter-button", ({ start = 0 }) => {
  const count = signal(Number(start));

  return html`
    <button @click=${() => count.value++}>
      Clicked ${count} times
    </button>
  `;
});

3️⃣ Use it in other components

<counter-button start="5"></counter-button>

4️⃣ Bootstrap your Glint✨ App entrypoint

// top-level app component
const App = () => html`
  <div>
      <counter-button start="5" />
  </div>
`;
  // bootstrapping in entry point
  render(App, {
    autoRegister: true,
    rootNode: document.querySelector('#glint-app')
  })

Boom! 💥 Your component just works—no build step, no config, no bullshit.

🎯 Why Glint?

🔥 Glint aims for a DX similar to React without the headache.

  • ✅ No VDOM Overhead → Faster, direct DOM updates.
  • ✅ Zero Build Step → Works without Babel/Webpack/Vite.
  • ✅ Signals & Computed State → No useEffect boilerplate.
  • ✅ Event Binding Like HTML → Just use @click=${fn}.
  • ✅ Native Web Standards → No lock-in, just HTML, JS, and CSS.

🔍 React vs. Glint

Feature React Glint
Build Tools Required (Babel, Webpack) 🚀 None (Runs in browser)
Reactivity Hooks (useState, useEffect) 🚀 Signals & Computed State
Event Handling Synthetic Events 🚀 Native DOM Events (@click=${fn})
Context API Required for state sharing 🚀 Global store() (No Prop Drilling)
Performance VDOM Reconciliation 🚀 Direct DOM Updates

📖 Features

🛠️ Simple, Reactive Components

Define components using signals—no hooks needed.

component("my-counter", () => {
  const count = signal(0);
  return html`
    <button @click=${() => count.value++}>
      Count: ${count}
    </button>
  `;
});

⚡ Computed State (No useMemo)

const doubleCount = computed(() => count.value * 2);

🎭 Slots & Composition

component("custom-card", () => html`
  <style>
    .card { border: 1px solid #ccc; padding: 1em; }
  </style>
  <div class="card">
    <slot name="header"></slot>
    <slot></slot>
  </div>
`);
<custom-card>
  <h3 slot="header">Title</h3>
  <p>Content here</p>
</custom-card>

🌍 Global State Without Context API

const theme = store("dark");
theme.value = "light";  // Updates all subscribers

🚀 Event Delegation, No Re-Renders

<button @click=${handleClick}>Click Me</button>

Uses native event listeners, unlike React’s synthetic event system.

🎬 Live Demo

DEMO on Codepen

💡 Glint was developed entirely on Codepen... Thank you Chris Coyer (:

🚀 Check out the interactive playground:

  • 👉 Glint Sandbox (Coming soon!)

🛠️ API Reference

1️⃣ component(name, rendererFn)

Registers a Web Component.

component("hello-world", () => html`<h1>Hello, World!</h1>`);

2️⃣ signal(initialValue)

Creates reactive state.

const count = signal(0);
count.value++;

3️⃣ computed(fn)

Creates a derived state.

const double = computed(() => count.value * 2);

4️⃣ store(initialValue)

Global state management.

const user = store({ name: "Alice" });

5️⃣ html Tagged Template

Tagged template for templating.

return html`<button>${count}</button>`;

💻 Installation & Usage

1️⃣ Using CDN (Coming soon!)

<script type="module" src="https://cdn.jsdelivr.net/npm/glint-js"></script>

2️⃣ Install with NPM

npm install glint-js
import { component, signal, html } from "glint-js";

🤝 Contributing

🚀 Want to help shape Glint? Open an issue or submit a PR!

  • 👉 GitHub Issues (Coming soon!)

📜 License

MIT License – Use it freely!

🎯 TL;DR

  • 🚀 No JSX, No build step, Just Web Components.
  • ⚡ No VDOM, only updates what changes.
  • 🎨 Scoped styles for free: No CSS-in-JS, no extra tooling.
  • 🔗 Works anywhere: Use inside React, Vue, Svelte, or vanilla JS.



✨ Glint – The lightweight UI framework we've been waiting for (that we're waiting for 😉) ✨

About

The no-bullshit, bullshit web component framework -- lightweight, React-ish custom elements with signals for reactivity

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published