Announcing BareDOM (Alpha) Lightweight CLJS UI components built on web standards (Custom Elements, Shadow DOM, ES modules). No framework, just the DOM. After building UIs with excellent tools like Reagent and Re-frame, I found that bundle size and complexity increased quickly—even for generic elements like buttons. This led me to explore Web Components in ClojureScript. This is my first open-source project. What started as a research hobby turned into an experiment using Claude Code to help architect a larger, useful set of components. It is an interesting experiment in AI-assisted development for me. The Specs: • Total bundle size: 136kb (for 54 components). • Framework Agnostic: Demos for CLJS-only, Reagent, and Vanilla HTML/JS. • Customisable components: Light/darkmode versions out of the box • Alpha State: Expect some bugs. I’d love to hear feedback on pretty much anything at this point 😊 Check it out here: https://github.com/avanelsas/baredom
Fantastic contribution! I'm curious if this is necessary:
(defn- register-components! []
(.init x-navbar)
(.init x-sidebar)
(.init x-button)
(.init x-modal)
(.init x-container))
What would be the downside of taking this out of the hands of your users and just .init-ing components automatically on first usage?
Are we able to hook something in here that we don't want to lose by doing it automatically?
Also, I'm noticing most setups recommend something like:
(defn create-nodes [x]
(cond
(nil? x) []
(false? x) []
(string? x) [(.createTextNode js/document x)]
(number? x) [(.createTextNode js/document (str x))]
(vector? x) [(create-element x)]
(seq? x) (mapcat create-nodes x)
:else []))
Is it that variable between environments that each user should be impl'ing this? Seems like another one of these things that could be invisible by default, while giving users an escape hatch to override these sorts of sane defaults.
Or is this a high traffic place for users to hook into things and get things done?
Seems a little advanced...
I like to have a high level api and a low level api, with the high level being super simple for beginners, but letting them have full control if they want.
Super awesome work though!@john registration is always a trade off. It can be automated, but there is a risk that aggressive optimisers remove the registration when you only import the component. Or things get registered more than once. I ended up doing it explicitly, giving me the most control. Would you prefer an auto-registration? wrt create-nodes, its used to normalise every child in a hiccup vector to a flat sequence of DOM nodes. Without it I would have to special case this inline.
Yeah, these are just personal preferences. I wouldn't want auto registrations if they're flaky in some of the intended target environments
But if it can be reliable and deterministic I'd prefer auto by default
Thanks for the feedback, I will think about it!
Perhaps BareDOM also works with squint. Even smaller bundle size
Btw:
Step 1 — Add the npm dependency to your package.json:
Then run npm install.
Step 2 — shadow-cljs: no extra configuration needed. shadow-cljs resolves npm packages automatically via the :npm-deps or node_modules integration built into every shadow-cljs project.
This looks odd. When you first optimize+compile a CLJS lib to JS and then include the JS back into a CLJS (shadow-cljs) project, you will get basically two full copies of the CLJS standard library in your project.
> Perhaps BareDOM also works with squint. Even smaller bundle size Did not event think about that, that would be interesting! > This looks odd. That is a readme text confusion. Step 2 really isn't a step. It is just an explanation really. I'll update the readme. Thanks for the feedback @borkdude!
CLJS users should not be using NPM for this at all
just a clojars or git whatever dependency in deps.edn
I've added it for convenience, but you are correct of course. It isn't needed. I will revisit the README for things like this. Thanks.
🤖
also app.components.x-cancel-dialogue.x-cancel-dialogue isn't great for a library namespace I guess
I considered using component.cljs or something like it. Ended up staying here. What would you suggest?
usually a library name starts with an organization name to make the namespace somewhat unique
e.g. vanelsas.components would be better than app.components
ah, sorry, misunderstood. I'll take a look at that as well
you're totally right ;)
Lol
The things we do for acceleration
It's okay... Make a comment about it, have the bot go fix it, take a walk
Not sure I trust "the bot" that much yet 😉
Just reroll the dice! ;)
Well, add a test, then reroll
Curious - have you seen https://github.com/raystubbs/zero? Was it not sufficient in some way, or just different enough from your own vision?
@p-himik I saw several implementations, including this one. For me it started as a learning exercise tbh. I'm pretty sure there are others that have done a lot more work on this topic. For me it was just a good first project that combined something I wanted to learn with the idea of trying to work with claude code on something i was interested in 😅
Congrats on your first open source project!!! 🎉
Hello, friends! I just published this: https://noumenon.leifericf.com/ > Ask your codebase precise questions. > Get grounded answers. > > Noumenon builds a Datomic knowledge graph from your repository so agents query structured facts instead of dumping raw files into context windows. In benchmarks across 9 repos and 8 languages, graph-augmented answers scored 2× higher on average. See the landing page and GitHub repo for more info.
That's what I was dreaming these days, testing now
Actually Claude is testing for me 😆
Looks like I fat-fingered something so the JAR publish CI/CD is broken. But the Clojure tool should work.
@leif.eric.fredheim trying it out. If it have LLM api auth already set up in agent harness (ECA), do i still need to supply agent auth keys in .env for MCP use?
I'm not sure off the top of my head! I didn't think of that scenario and haven't tested it. It might work without.
I have a claude subscription plan. In ECA i “log in” to anthropic account, authenticate with a durable session token they provide. I’m not sure this is a proper api key. Will try it mcp with simple cljs command first.
That should work. It shells out to claude
But be careful! Your tokens will run out fast on big repos.
Do you mean claude code or claude desktop. Because I am not using those atm. Thanks for warning. Are updates also very expensive? Via docs it is suggested that sonnet-level model is ok?
I meant Claude Code CLI (`claude` in the terminal). Regular updates should usually be a lot cheaper than a full analysis. The expensive part is when it starts doing broad LLM-powered analysis across many files, especially in a big repo. Yeah, Sonnet is probably the right default (I'm mainly using GLM myself because it's cheaper). That is what I would try first. It should be good enough unless you are doing something unusually heavy or want deeper analysis quality.
Noumenon can now also https://noumenon.leifericf.com/#introspect. Seehttps://github.com/leifericf/noumenon/blob/main/reports/introspect-development-2026-03-28.md for more details.
Browsable docs embedded in Clojure library JARs I've been working on a set of tools that let library authors ship Markdown documentation (API docs, README, CHANGELOG, etc.) inside their JARs, and let users browse them at the REPL or from their editor. Three repos: • https://github.com/dcj/codox-md — A Codox writer that generates Markdown instead of HTML, designed for embedding in JARs as classpath resources. (available on Clojars: com.dcj/codox-md) • https://github.com/dcj/clj-doc-browse — Runtime classpath-based documentation browser for Clojure. Query and read library docs from the REPL. (available on Clojars: com.dcj/clj-doc-browse) • https://github.com/dcj/clj-doc-browse-el — Emacs package that integrates with CIDER to browse embedded library docs directly in your editor. (MELPA submission pending; manual install for now) All at 0.1.0 — feedback welcome!
something to consider that's maybe of interest. in the Java ecosystem, javadocs are not shipped inside the library jar, they are shipped with a "standard" Maven classifier of "javadoc" (and sources with classifier of "sources"). So if you look at jackson-core in https://repo1.maven.org/maven2/tools/jackson/core/jackson-core/3.1.0/ - you see jackson-core-3.1.0-javadoc.jar, which contains the javadoc documentation.
because there is a standard mapping of maven coords -> javadoc coords, IDEs can obtain and use this documentation automatically based on your project dependencies. it would be pretty great if we established a convention for the coordinate classifier for markdown docs and deployed them that way in Clojars (to avoid increasing the size of all our libraries)
adding more stuff to prod downloads and classpaths seems like a bad direction to go - this would allow that to be dev time-only
Hi folks -Clojurists Together just posted https://www.clojuriststogether.org/news/annually-funded-developers-update-january-february-2026/ updates from the 5 developers receiving 2026 annual funding. News from Bohzidar Batsov, Clojure Camp, Eric Dallo, Jeaye Wilkerson, Michiel Borkent, and a final report from FastMath. There is a lot of work here - so have fun exploring!