←back to thread

77 points TonyPeakman | 2 comments | | HN request time: 0.424s | source

TL;DR: dagger.js is a buildless, runtime-only micro-framework that plays nicely with native Web Components. It uses HTML-first directives (e.g. +click, +load) so you can ship a page by dropping a single <script> from a CDN—no bundlers, no compile step.

Why I built it Modern stacks are powerful but often heavy: bundlers, compile steps, framework DSLs, local CLIs. For internal tools, small apps, and edge/serverless deployments, I wanted something you can view-source, paste into a page, and ship.

What it is:

Runtime-only: no build or VDOM compile; hydrate behaviors directly on HTML. HTML directives: e.g. +click, lifecycle +load / +loaded / +unload / +unloaded. Zero APIs: dagger.js works in pure declarative mode, modules and directives provide everything you need to build your application. Web-Components-first: works alongside Custom Elements; keep concerns local. Distributed modules: load small, focused script modules via CDN. Progressive enhancement: the page renders without a build step.

Use cases:

Admin panels & dashboards that don’t warrant a full toolchain Embed widgets, docs-sites with interactive bits Edge/serverless apps where cold start and simplicity matter

Links

GitHub: https://github.com/dagger8224/dagger.js Docs/Guide: https://daggerjs.org Examples: https://codepen.io/dagger8224/pens

I’d love feedback on edge-cases, and where it breaks. Happy to answer tough questions here.

1. imiric ◴[] No.45252188[source]
This is interesting. Thanks for sharing!

As someone who is disillusioned by the state of modern frontend web development, I'm always curious about novel approaches that do things differently.

At first glance, I like that this is buildless and declarative. Supporting Web Components is also a nice touch.

However, I don't like that it abuses HTML attributes for the "directives" feature. I appreciate that these are stackable, and it seems like a concise and flexible way to specify behavior, but at the same time, it's not valid HTML, and the framework shouldn't rely on unspecified behavior of HTML parsers to ignore them. The correct approach would be to use data attributes, which would make the API more verbose, and possibly less flexible, but it ensures future compatibility across browser engines.

I'm also not a fan of attributes having any sort of logic or JavaScript code in them. That is IMO an anti-pattern popularized by JSX and frameworks of the time which we've accepted as standard, for some reason. Separation of concerns is a powerful concept that simplifies development and maintenance. HTML should define the structure and content of the page; JavaScript should define the logic. Whenever you write JS inside HTML, or viceversa, you're breaking this principle. This doesn't mean that JS and HTML can't coexist in a single file―that has been possible since the dawn of the web. But it means that each layer should be concerned about a single aspect of the application. And, yes, I'm aware that Web Components also technically break this, and, no, I don't like it.

Dagger.js takes this to an extreme level and seems to allow JS expressions inside text content, which is surely too inefficient to have any practical value.

FWIW I experimented with own buildless and declarative micro framework a few months ago[1], after a frustrating experience with Vue. I was curious if "primitive" data binding could be used with an intuitive API, while keeping separation of concerns as much as possible, and without abusing HTML. Turns out that it's really not that difficult. It doesn't have any of the advanced features and flexibility of modern frameworks, but that was a deliberate design decision. I don't expect anyone else to use it, but I plan to adopt it in personal projects. So far it has worked well for implementing the options UI of a small browser extension.

Also, for the love of all things holy, please prompt your LLM to tone down the emojis in the docs. It's quite distracting.

[1]: https://github.com/hackfixme/miu

replies(1): >>45257231 #
2. TonyPeakman ◴[] No.45257231[source]
Thanks for the thoughtful feedback — you raise valid concerns.

The reason dagger.js allows JS expressions in attributes is mostly about lowering the barrier to entry. By keeping everything in plain HTML, you can copy-paste a snippet, view-source it, and immediately see both the structure and the behavior in one place. For small widgets, docs, or internal tools, that convenience often outweighs the drawbacks.

You’re right that it’s technically not “valid HTML,” and that data-attributes would be more standards-compliant. I chose the lighter +click="count++" style because it makes the examples concise and easy to reason about — essentially HTML as a living playground. The trade-off is that it bends the rules a bit.

That said, I agree separation of concerns is important. dagger.js is not trying to replace large frameworks or enforce this pattern everywhere. It’s intended as a minimal option where simplicity and quick iteration matter more than strict layering. If it proves useful but the attribute style becomes a blocker, I’m very open to exploring a data-* form or even alternate syntax.

Also, thank you for sharing your own framework — it looks great. Actually I’m considering adding a pre-compiled, separation-of-concerns version of dagger.js in the future to support a wider range of development needs.

And thanks as well for the docs suggestion about emojis. Feedback like this really helps shape the project in a healthier direction.