# Asset management without Node.js

**URL:** <https://discourse.hanakai.org/t/asset-management-without-node-js/1305>\
**Category:** questions\
**Created:** [September 23, 2025, 7:44pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305 "2025-09-23T19:44:05Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![davidcelis](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/davidcelis/32/966_2.png) [@davidcelis](https://discourse.hanakai.org/u/davidcelis)\
**Post date:** [September 23, 2025, 7:44pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/1 "2025-09-23T19:44:05Z")

</div>

Some of the more compelling newer features of Rails like Propshaft and importmaps have resulted in the framework no longer having a hard dependency on Node.js for asset bundling. I’ve found that not requiring Node has made Rails even easier for newer developers to get started with, and greatly simplifies deployment for new apps (or existing apps that are updated to take advantage). I may be reading the guides wrong, but it seems like Hanami still has requirements for having Node.js available so I was wondering if the team has any long-term plans for removing that dependency?

---

<div class="post-metadata">

**Author:** ![wout](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/wout/32/684_2.png) [@wout](https://discourse.hanakai.org/u/wout)\
**Post date:** [September 26, 2025, 6:49am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/2 "2025-09-26T06:49:13Z")

</div>

Not having Node.js as a dependency is also a goal for me. What I’m building needs to be self-hostable and eliminating the frontend build step would greatly simplify that process. I can’t speak for the long-term planning of Hanami/Hanakai, but I will certainly be taking a stab at it in the next few months, if no one else beats me to it of course.

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [September 26, 2025, 12:47pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/3 "2025-09-26T12:47:43Z")

</div>

> [@davidcelis](#):
>
> I may be reading the guides wrong, but it seems like Hanami still has requirements for having Node.js available so I was wondering if the team has any long-term plans for removing that dependency?

Hey David! Thanks for checking this out 🙂 You’re right: Node.js is currently a requirement for our assets layer. We chose this to begin with because it would support the widest range of frontend arrangements.

I’d love for us to be able to provide a simpler non-Node.js-requiring alternative. What would it look like, in your eyes? Is it like Rails’ [import maps support](https://guides.rubyonrails.org/working_with_javascript_in_rails.html#import-maps)?

To make this happen we’d need someone to come in and champion it. I’d be happy to provide support for the effort. @wout or @davidcelis, if this is either one of you (or both!), that’d be awesome. ❤

Note: I would not want us to go beyond two blessed first-party ways of doing assets. Any more and it would be confusing to users (I’ve lost track of all of Rails’ ways of doing it) and too hard for us to support.

---

<div class="post-metadata">

**Author:** ![wout](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/wout/32/684_2.png) [@wout](https://discourse.hanakai.org/u/wout)\
**Post date:** [September 26, 2025, 2:15pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/4 "2025-09-26T14:15:04Z")

</div>

I’d be happy to help out here, or take on the complete task if no one did so before me. Right now this is not very high on my priority list though, so it would be something for in a few months.

@timriley I completely agree on limiting it to two options. Importmap for simple frontends (e.g. htmx + Alpine.js + plain CSS), and esbuild if there’s a need for preprocessing, tree shaking, and/or legacy support.

The cherry on the cake would be to have something like [hotwire-spark](https://rubygems.org/gems/hotwire-spark) to get (hot) reloading via SSE/WebSockets in development, but that’s more long-term, and probably also a separate gem.

---

<div class="post-metadata">

**Author:** ![aaronmallen](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/aaronmallen/32/890_2.png) [@aaronmallen](https://discourse.hanakai.org/u/aaronmallen)\
**Post date:** [September 26, 2025, 3:50pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/5 "2025-09-26T15:50:49Z")

</div>

Personally I’d like to see this be totally configurable on `hanami new` something like `hanami new my_app –bun` or `hanami new my_app –vite`

---

<div class="post-metadata">

**Author:** ![davidcelis](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/davidcelis/32/966_2.png) [@davidcelis](https://discourse.hanakai.org/u/davidcelis)\
**Post date:** [September 26, 2025, 5:00pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/6 "2025-09-26T17:00:02Z")

</div>

> [@timriley](#):
>
> I’d love for us to be able to provide a simpler non-Node.js-requiring alternative. What would it look like, in your eyes? Is it like Rails’ [import maps support](https://guides.rubyonrails.org/working_with_javascript_in_rails.html#import-maps)?

I’m admittedly much stronger on the backend than I am on the frontend 😅 I’ve used Rails’ import maps and preferred that to having to bundle, but the frontend ecosystem moves so quickly that I don’t know if something else has come along that’s becoming more of a canonical standard. From @wout’s message, it seems like maybe import maps are still the way to go for this kind of alternative?

---

<div class="post-metadata">

**Author:** ![wout](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/wout/32/684_2.png) [@wout](https://discourse.hanakai.org/u/wout)\
**Post date:** [September 26, 2025, 5:13pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/7 "2025-09-26T17:13:38Z")

</div>

> [@davidcelis](#):
>
> From @wout’s message, it seems like maybe import maps are still the way to go for this kind of alternative?

As far as I know, `importmap` is the best option if you want no build step. It’s a web standard so it’s (hopefully) less likely to be replaced by the next shiny new tool like it’s customary in JS land 😄.

---

<div class="post-metadata">

**Author:** ![tcannonfodder](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/tcannonfodder/32/969_2.png) [@tcannonfodder](https://discourse.hanakai.org/u/tcannonfodder)\
**Post date:** [September 26, 2025, 11:02pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/8 "2025-09-26T23:02:48Z")

</div>

In my experience, it’s really, really hard to get importmaps to work nicely in anything beyond the most rudimentary needs. I actually tried to write a version of an importmaps resolver that fixed a number of issues that Rails’ importmaps approach has; but ultimately the maintenance overhead (especially once you factor in modern packages that are composed by smaller packages, private packages, and dependency updates) killed that project.

I think that ultimately it’s easier from a conceptual & maintenance standpoint for JS bundling to be in node; with a basic entrypoint/configuration approach. It’s easy to explain, automated dependency management can already pick up the changes, and the variety of JS runtimes gives people options.

I can understand the hesitancy to keep something as messy as JS in the dev environment; but I think Hanami has a chance to be good neighbors in the web stack with JS, rather than deriding it.

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [September 27, 2025, 2:02am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/9 "2025-09-27T02:02:59Z")

</div>

Thanks for this helping input, @tcannonfodder (and welcome to the forum!).

One thing I should point out is that we also rely on our hanami-assets esbuild plugin to find CSS (via JS entry points in our case), but also images and fonts and any other static asset you want available in the frontend.

These files get built or copied into `public/`, and are then indexed in `assets.json` manifest files (one per slice), which our asset helpers reference to generate the relevant URLs or HTML tags.

Any approach that looks to work without Node.js will need to handle all of this logic, too. It does make me wonder how worthwhile it is, given the all limitations I hear about using import maps for real life.

I’ve pointed Konnor Rogers to this post. He seems to be very expert in these things and could have some sage advice to give us. (Update: he does! We can wait until he has time to kindly weigh in).

---

<div class="post-metadata">

**Author:** ![tcannonfodder](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/tcannonfodder/32/969_2.png) [@tcannonfodder](https://discourse.hanakai.org/u/tcannonfodder)\
**Post date:** [September 27, 2025, 2:32am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/10 "2025-09-27T02:32:10Z")

</div>

> [@timriley](#):
>
> I’ve pointed Konnor Rogers to this post. He seems to be very expert in these things and could have some sage advice to give us. (Update: he does! We can wait until he has time to kindly weigh in).

Yep! Konnor and I have passed Miyazaki memes about importmaps back & forth dozens of times 😂😂

---

<div class="post-metadata">

**Author:** ![davidcelis](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/davidcelis/32/966_2.png) [@davidcelis](https://discourse.hanakai.org/u/davidcelis)\
**Post date:** [September 27, 2025, 2:48am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/11 "2025-09-27T02:48:48Z")

</div>

By that, do you mean that you strongly believe they’re an insult to life itself? 😅

---

<div class="post-metadata">

**Author:** ![KonnorRogers](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/konnorrogers/32/970_2.png) [@KonnorRogers](https://discourse.hanakai.org/u/KonnorRogers)\
**Post date:** [September 27, 2025, 4:39am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/12 "2025-09-27T04:39:02Z")

</div>

What was going to be a long post is pretty simple: (edit: this still ended up being long…oops.)

Hanami should only support as many bundlers / “asset management” systems as it feels comfortable with out of the box. Every additional “out of the box” way to do it introduces its own level of maintenance burden.

The good news is Hanami already has the plumbing for working with a common JSON schema for assets in the form of `assets.json` files. At this point, its largely writing plugins for Hanami to make this all come together.

That would mean the plugin is responsible for “gathering” and “writing” as many asset files as it plans to own to the relevant `assets.json` file for that slice.

The TLDR is that (without looking at code) a working solution is largely plugging APIs, grabbing the assets you need, and then writing them. Yes, that means a plugin also needs to be written for vite, webpacker, rspack, turbo, et al. But as long as the docs are clear on how the “AssetManager” expects you to write files, this is probably fine.

As a final note, importmaps _the spec_ , are good. they let you do a lot of things. And reduce the number of CLI processes you need running which is always nice.

Rails version of importmaps has self-imposed restrictions that make it incompatible with many packages in the NPM registry, particularly those with “multi-entrypoints”.

If anyone has any interest in this, im happy to “consult” with them and help them along the way if they have any questions. Ive pretty much read most of Propshaft, importmaps-rails, Sprockets, jsbundling-rails, Webpacker, and pretty much anything frontend assets related and have even written my own personal attempts as well.

---

<div class="post-metadata">

**Author:** ![moonglum](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/moonglum/32/968_2.png) [@moonglum](https://discourse.hanakai.org/u/moonglum)\
**Post date:** [September 27, 2025, 7:08am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/13 "2025-09-27T07:08:49Z")

</div>

> [@tcannonfodder](#):
>
> In my experience, it’s really, really hard to get importmaps to work nicely in anything beyond the most rudimentary needs.

This is my experience as well. I definitely want to have the option of using a bundler in Hanami 🙂

I am one of the two creators and maintainers of [https://www.faucet-pipeline.org](https://www.faucet-pipeline.org). The idea is quite simple: Build tools in JS come and go. We provide a wrapper around them, and curate it for you. And you don’t need to change anything when the underlying build tool changes, you just update. The project was on a bit of a hiatus for a time, but we recently started to revive it. But even with the hiatus, it is still used in production (Rails) apps.

I’m happy to propose a solution for Hanami for the “build” (as opposed to the “no build”) path that is flexible, but still easy to maintain for Hanami.

---

<div class="post-metadata">

**Author:** ![KonnorRogers](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/konnorrogers/32/970_2.png) [@KonnorRogers](https://discourse.hanakai.org/u/KonnorRogers)\
**Post date:** [September 27, 2025, 8:11pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/14 "2025-09-27T20:11:08Z")

</div>

Yes, unfortunately importmaps weren’t really designed in a backwards compatible way with the way Node and bundler module resolution algorithms work.

Importmaps expect a “flat” tree where all modules share the same dependency. NPM is designed with “isolated dependencies per-package” which means in the case where you have 2 packages with conflicting dependency requirements, importmaps will fail.

importmaps will also fail if they’re using non-standard JS syntax like `import “thing.css”` (though with type assertions importmaps, this may be more do-able in the future)

Any thing which requires custom “Transforms” to run (like React components not transpiled to JS for example)

importmaps are good, but limited.

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [September 28, 2025, 6:44am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/15 "2025-09-28T06:44:18Z")

</div>

Thanks for your input, @KonnorRogers!

> [@KonnorRogers](#):
>
> The good news is Hanami already has the plumbing for working with a common JSON schema for assets in the form of `assets.json` files. At this point, its largely writing plugins for Hanami to make this all come together.

So it sounds like a task for me (or anyone wants to take this on) is to define the “specification” for Hanami Assets: its expected behaviours and outputs. This is what people can refer to when adding support for additional asset management systems.

If someone does get to building a fully working system using importmaps, this sounds like a reasonable candidate to include in our first-party gems, as the option for people who want a non-Node.js setup, though of course I’d want us to be able to appraise it fully, given it would mean we bring it under maintenance along with everything else, and would need to document it alongside our existing setup.

> [@moonglum](#):
>
> I’m happy to propose a solution for Hanami for the “build” (as opposed to the “no build”) path that is flexible, but still easy to maintain for Hanami.

Thanks for your offer of help! We do already support a “build”-based approach in Hanami Assets right now. It’s based around esbuild and is set up by default with new Hanami apps.

Though once we get the above specification out, sounds like you could write support for Faucet, so you can easily use that with Hanami apps 🙂

---

<div class="post-metadata">

**Author:** ![moonglum](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/moonglum/32/968_2.png) [@moonglum](https://discourse.hanakai.org/u/moonglum)\
**Post date:** [September 28, 2025, 7:58am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/16 "2025-09-28T07:58:06Z")

</div>

Makes a lot of sense to me. With faucet, we chose a very simple contract between the framework and the asset pipeline: A JSON file that maps the original name of the file to the name after it has been processed. This is why the Rails plugin I wrote is tiny and works to this day without any adjustments: [faucet\_pipeline\_rails/lib/faucet\_pipeline\_rails/manifest.rb at main · faucet-pipeline/faucet\_pipeline\_rails · GitHub](https://github.com/faucet-pipeline/faucet_pipeline_rails/blob/main/lib/faucet_pipeline_rails/manifest.rb)

The processed name in most cases is the name with a hash injected. But in some cases, it is more than that: faucet can optimize images, so the input might be a JPG and the output an AVIF file.

The reason we decided to make the hashing the responsibility of the pipeline and not the framework is CSS, Fonts and Images. A font will be fingerprinted, the resulting path will be used in CSS but also might be used in HTML (preloading). So the pipeline needs the resulting font name for producing the CSS, and the framework still needs to look up the path for preloading. Rails went with an imho weird solution of post processing the CSS again to replace the paths in the already processed CSS.

---

<div class="post-metadata">

**Author:** ![wout](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/wout/32/684_2.png) [@wout](https://discourse.hanakai.org/u/wout)\
**Post date:** [May 15, 2026, 10:18am UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/17 "2026-05-15T10:18:41Z")

</div>

I’ve been working on a pure Bun implementation. So no Node.js dependency, but Bun for everything:

> **[bun\_bun\_bundle](https://codeberg.org/w0u7/bun_bun_bundle)**
>
> Zero-dependency asset bundler with CSS hot-reloading, fingerprinting, live reload, and a flexible plugin system. Works with Rails, Hanami, or any Rack app.

I tested it superficially with Hanami, but today I started on a new Hanami project so if there are any wrinkles, I’ll iron them out. Installation is simple: drop hanami-assets and configure bun\_bun\_bundle.

We’ve been using this setup it in two production apps without issues (Rails and Lucky). It’s blazing fast.

---

<div class="post-metadata">

**Author:** ![timriley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/timriley/32/621_2.png) [@timriley](https://discourse.hanakai.org/u/timriley)\
**Post date:** [May 15, 2026, 11:57pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/18 "2026-05-15T23:57:52Z")

</div>

It’s great to see more activity in this space. Thanks for building bun\_bun\_bundle, @wout, and for considering Hanami as part of it ❤

In terms of Hanami integration, I’d love to see whether it might be able to make this work _with_ the Hanami Assets Ruby Gem as opposed to requiring its removal.

I’ve just merged a `SPEC.md` into Hanami Assets, ([read it here](https://github.com/hanami/hanami-assets/blob/main/SPEC.md)), which outlines the expectations for a complete user experience for asset bundlers targeting Hanami, and how they can provide manifest files that allow Hanami’s standard assets layer to work out of the box, and remain consistent for all users.

To be clear, the hanami-assets Ruby Gem is already bundler agnostic. It just supplies the glue for reading those asset manifests. My goal is to make it easy for multiple bundlers to plug into this (including, eventually, into our CLI tools), and this SPEC is the first step.

The SPEC also outlines important details about e.g. how bundlers should be working with assets that are isolated per slice, which is an important part of the Hanami experience.

I’d be keen to hear what you think about the spec! Share me your feedback, and maybe we can use bun\_bun\_bundle as an opportunity to further the enhance of this area of Hanami 🙂

---

<div class="post-metadata">

**Author:** ![wout](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.hanakai.org/wout/32/684_2.png) [@wout](https://discourse.hanakai.org/u/wout)\
**Post date:** [May 16, 2026, 2:14pm UTC](https://discourse.hanakai.org/t/asset-management-without-node-js/1305/19 "2026-05-16T14:14:32Z")

</div>

Thanks for linking the spec, that’s really helpful. 🙂

Short answer: yes, totally on board. Requiring users to rip out `hanami-assets` is quite drastic anyway.

I just shipped bun\_bun\_bundle v0.13.0 with the easy fixes:

**SRI**  
`--sri=sha256,sha384,...` computes digests and embeds them in each manifest entry. The helpers `integrity=` and `crossorigin="anonymous"` when present.

**Manifest shape**  
Bumped from `{key: "string"}` to `{key: {url, sri?}}`, matching section 5.2.

One question here though: why `url` and not `path`? It’s a bit confusing because the spec calls it “Absolute path”. Is that for compatibility with Node.js builders?

**SIGINT**  
The dev server now releases its file watchers and WebSocket clients on Ctrl-C and exits 0 (section 7).

* * *

What’s left (to be released under v0.14) is a Hanami adapter. Likely as a hanami-cli command override so it can stay Node.js-free:

**Absolute paths**  
bbb currently writes `"url": "js/app-abc.js"` (relative, so Rails/Lucky helpers can prepend `public_path` for asset\_host support). The adapter will prepend `path_prefix` in the hanami output so the manifest meets section 5.2’s absolute-path requirement. Standalone bbb manifests stay relative to keep Rails/Lucky compatibility.

**Logical names**  
bbb keeps the type-dir prefix (`js/app.js`, `images/logo.png`). The adapter will strip it for Hanami.

**Per-slice invocation**  
The adapter will create one Bun sub-process per app/slice.

**`--watch`**  
bbb uses `--dev`, so there will be a `--watch` flag as an alias.

* * *

A couple of places where bbb’s design collides with the spec:

**Importing non-JS assets in JS (section 5.4)**  
bbb is intentionally three-pipeline (JS, CSS, static), so JS files don’t import CSS or static assets. To be honest, I never liked that approach, so I’d rather not change that. Side-effect asset emission could be pulled through a raw Bun plugin if necessary, but it feels like taking a step back.

**Globbing**  
bbb has a CSS/JS glob syntax (via plugins) for [CSS](https://codeberg.org/w0u7/bun_bun_bundle#user-content-cssglobs) and [JS](https://codeberg.org/w0u7/bun_bun_bundle#user-content-jsglobs) that lets users skip barrel files entirely. Great in CSS, but it’s especially nice for registering Alpine components or Stimulus controllers.

If the implicit goal of the spec is bundler-swap portability, users would lose this when moving off bbb. Not a blocker, just worth flagging.
