Why I Built Flynt.js: Reactivity Without Messy HTML Clutter
If you build Multi-Page Applications (MPAs) using Laravel Blade, Twig, or classic SSR, you've probably used Alpine.js. It's awesome for quick reactivity, but as your components grow, your HTML quickly turns into this:
<!-- The Alpine.js HTML clutter we all know... -->
<div x-data="{ open: false, items: [], fetch() { ... } }" x-init="fetch()">
<button @click="open = !open" :disabled="loading">Toggle</button>
</div>
I loved the lightweight nature of Alpine, but I hated losing Separation of Concerns. Why are we jamming entire JS functions inside HTML attributes?
I wanted something different: The reactivity of modern frameworks, but with clean HTML and strict Presenter-based architecture.
So I built Flynt.js.
What is Flynt.js?
Flynt.js (~2KB) brings the Presenter Pattern to MPAs. Your HTML stays 100% clean, referencing only behavior via data-fx attributes:
<div data-fx="productPresenter">
<select data-fx="productPresenter.sortBtn">...</select>
<ul data-fx="productPresenter.productListing"></ul>
<button data-fx="productPresenter.loadMoreBtn">Load more</button>
</div>
All logic lives in clean, testable JavaScript presenters with direct DOM reactivity:
<script>
window.productPresenter = fx.presenter(({ createState, render, map }) => {
const state = createState({ loading: false, products: [] });
return {
loadMoreBtn(el) {
el.onclick = () => fetchMoreProducts();
render(() => {
el.disabled = state.loading;
});
},
productListing(el) {
const mapProducts = map(el);
render(() => {
const items = state.products.map(prod => ({
key: prod.id,
html: `<li class="card">${prod.title}</li>`
}));
mapProducts(items); // Efficient key-based DOM updates!
}));
}
};
});
</script>
The Secret Weapon: map(el)
Unlike other micro-libraries that force you to re-render entire innerHTML blocks or mess with virtual DOMs, Flynt includes a native map() helper. It updates real DOM items in-place based on unique keys.
Key Features
๐งน Zero HTML clutter: Keep templates pristine.
โก Ultra-lightweight: ~2KB runtime, zero dependencies.
๐ Direct DOM Reactivity: createState + render loops without Virtual DOM overhead.
๐ฆ No build step required: Works directly via <script> tag
Check out the GitHub repo, star it if you like the approach, and let me know your thoughts!
๐ GitHub: https://github.com/marsbos/flynt.js
Top comments (0)