bun_bun_bundle
Bun, Bun, Bundle for Crystal
A self-contained asset bundler for Crystal powered by Bun. No development dependencies, no complex configuration. Lightning fast builds with CSS hot-reloading, fingerprinting, live reload, and a flexible plugin system. Works with Kemal or any Crystal HTTP server.
This is the Crystal version of the Ruby gem with the same name.
[!NOTE] If you are using the Lucky framework, this functionality is already built in. You do not need this shard.
Installation
-
Add the dependency to your
shard.yml:dependencies: bun_bun_bundle: codeberg: fluck/bun_bun_bundle -
Run
shards install -
Make sure Bun is installed:
curl -fsSL https://bun.sh/install | bash -
Install the BunBunBundle CLI (Ruby gem):
gem install bun_bun_bundle
Configuration
BunBunBundle reads its configuration from config/bun.json. This file is shared between the JavaScript bundler and this shard.
{
"entryPoints": {
"js": ["src/js/app.js"],
"css": ["src/css/app.css"]
},
"outDir": "public/assets",
"publicPath": "/assets",
"manifestPath": "public/bun-manifest.json",
"devServer": {
"host": "127.0.0.1",
"port": 3002
}
}
All fields have sensible defaults. See the BunBunBundle documentation for the full configuration reference.
Usage with Kemal
Setup
Load the asset manifest and register the development cache handler:
require "kemal"
require "bun_bun_bundle"
BunBunBundle::Manifest.load
# In development, prevent stale asset caching:
add_handler BunBunBundle::DevAssetCacheHandler.new
Helpers in views
Include BunBunBundle::Helpers and BunBunBundle::ReloadTag in your layout or view:
require "kemal"
require "bun_bun_bundle"
BunBunBundle::Manifest.load
class Layout
include BunBunBundle::Helpers
include BunBunBundle::ReloadTag
def initialize(@content : String)
end
ECR.def_to_s "src/views/layout.ecr"
end
get "/" do
content = "<h1>Hello</h1>"
Layout.new(content).to_s
end
add_handler BunBunBundle::DevAssetCacheHandler.new
Kemal.run
In your layout template (src/views/layout.ecr):
<!DOCTYPE html>
<html>
<head>
<%= bun_css_tag("css/app.css") %>
<%= bun_js_tag("js/app.js") %>
<%= bun_reload_tag %>
</head>
<body>
<%= @content %>
<%= bun_img_tag("images/logo.png", alt: "My App") %>
</body>
</html>
Running
Start the BunBunBundle dev server and your Kemal app:
# Terminal 1: start the asset bundler with file watcher
bun_bun_bundle dev
# Terminal 2: start your app
crystal run src/app.cr
For production, build fingerprinted assets first:
bun_bun_bundle build --prod
crystal build --release src/app.cr
API reference
BunBunBundle::Manifest
BunBunBundle::Manifest.load- loads the asset manifest at compile time. Call this once during app setup.BunBunBundle::Manifest.asset("js/app.js")- returns the fingerprinted path. Checked at compile time with typo suggestions.BunBunBundle::Manifest.dynamic_asset("images/icon-#{name}.png")- returns the fingerprinted path at runtime. Use when you need string interpolation.BunBunBundle::Manifest.css_entry_points- returns all CSS entry point keys. Used internally by the reload tag.
BunBunBundle::Helpers
Include this module to get:
bun_asset(path)- returns the public path for a manifest asset.bun_js_tag(source, **options)- generates a<script>tag.bun_css_tag(source, **options)- generates a<link>tag with automatic cache busting in development.bun_img_tag(source, alt: nil, **options)- generates an<img>tag.
BunBunBundle::ReloadTag
Include this module to get:
bun_reload_tag- returns a<script>tag that connects to the dev server's WebSocket for CSS hot-reloading and live reload. Returns an empty string unless running in development (checksKEMAL_ENV, thenCRYSTAL_ENV, defaults to"development").
BunBunBundle::DevAssetCacheHandler
An HTTP::Handler that sets no-cache headers on asset requests in development.
# Kemal:
add_handler BunBunBundle::DevAssetCacheHandler.new
# Plain HTTP::Server:
server = HTTP::Server.new([
BunBunBundle::DevAssetCacheHandler.new,
# ...other handlers...
])
BunBunBundle::Config
Reads config/bun.json and provides typed access to all configuration values. Shared between the JavaScript bundler and this shard.
config = BunBunBundle::Config.instance
config.public_path # => "/assets"
config.out_dir # => "public/assets"
config.dev_server.ws_url # => "ws://127.0.0.1:3002"
License
MIT
bun_bun_bundle
- 1
- 0
- 0
- 0
- 1
- 15 days ago
- April 9, 2026
Wed, 29 Apr 2026 22:30:08 GMT