Better dev tooling with lustre_dev_tools
v2
As many of Lustre’s users are new to frontend or would prefer to avoid modern JavaScript toolchains, Lustre’s own development tooling has become a core part of the developer experience.
No more native dependencies
One of the standout improvements in this release is the move away from the Erlang fs package and the need for the Erlang build tool to compile a native C program for file system watching. This was most-commonly a sticking point for Windows users, where rebar3 is often packaged separately to Erlang/OTP and can be difficult or confusing to set up correctly.
With Lustre Dev Tools v2, we have moved to using Bun for bundling and as a side effect can piggy back off of Bun’s built-in file watching capabilities. This means dev tools no longer needs to compile native code and onboarding should be much smoother for folks new to Lustre, Gleam, and the BEAM.
TOML-based configuration
The number of Gleam-based development tools is steadily growing and with it has
come some conversations on how to handle configuration more consistently. After
some discussion, the community mostly settled on a tools.*
table in gleam.toml
inspired by Python’s pyproject.toml
.
In an effort to push this standard forward, Lustre’s new dev tools support a wide
variety of configuration options under the tools.lustre.*
namespace. A typical
configuration for a Lustre project going forward might look something like this:
[tools.lustre.bin]
# Use the system-installed `bun` binary instead of downloading one automatically.
bun = "system"
[tools.lustre.build]
minify = true
# Build the application into our server's `priv/static` directory so it can be
# deployed together with the backend.
outdir = "../server/priv/static"
[tools.lustre.dev]
host = "0.0.0.0"
# Configure an API proxy to forward requests to our backend during development.
# This lets us avoid CORS issues while the frontend and backend are running on
# different ports.
proxy = { from = "/api", to = "http://localhost:3000/api" }
[tools.lustre.html]
# Include Bootstrap in our project for simple styling.
stylesheets = [{ href = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" }]
scripts = [{ src = "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" }]
This should make it easier for teams to share configuration for Lustre projects without needing external scripts or documentation on what flags to pass. More information can be found on the TOML reference page.
Clearer handling of HTML, static assets, and build artifacts
One big wart in previous versions of dev tools was the handling of index.html
,
static assets, and where build artifacts were placed. Previously when starting
the dev server, an index.html
file would be generated in the root of your project
and used as the entry point during development. At the same time development
builds of your application would be placed in the same priv/static
directory
as your production builds, leading to confusion over which files were safe to
commit or deploy.
This has been massively cleaned up in v2, with the development server now no longer
generating any build artifacts in your project. Instead, dev tools is now fully
in control of the HTML entry file it serves. At build time, an index.html
file
will now be generated in the output directory alongside your JavaScript and CSS
bundles.
In the previous section we already saw how this HTML file can be customised under
the tools.lustre.html
table in your gleam.toml
. Additional scripts, stylesheets
and meta tags can be injected through this configuration.
Additionally assets placed in the assets/
directory in the root of your project
will now be served during development and copied to the output directory at build
time. This makes it easy and clear to include static assets like images, fonts,
or CSS in your projects. In development, changes to assets will be reflected in
real-time without a full page reload so feel free to nudge that div pixel-by-pixel
until it’s just right.
Finally, the default output directory for builds has been changed from priv/static
to dist/
. The previous directory was chosen to follow OTP application conventions,
but Lustre applications are JavaScript and following this convention was more
confusing than helpful. For full stack Gleam projects you should continue to build
your client applications into your server’s priv/static
directory, but this new
default will make it clearer for client-only projects that build artifacts placed
in dist/
are meant to be deployed.
For more information on how assets are handled, check out the assets page in the docs.
And the rest
Nix users can finally rejoice with the new ability to specify local paths to the
Bun and Tailwind binaries dev tools uses to build your projects. Users that want
to dip into the JavaScript ecosystem without changing their build tooling can now
properly import dependencies from node_modules
and have them work both during
development and in production builds. Dev tools will update your project’s
.gitignore
when it is first run to ensure build artifacts don’t make their way
into your Git history.
Lustre is still largely maintained by me – Hayleigh – with the support of a small number of contributors. To my existing sponsors on GitHub, thank you! Your support has fueled me with both motivation and caffeine to keep the project growing 💕.
If you’re interested in supporting Lustre, one of the best things you can do is build something with it and tell everyone about it!
If you or your company are using Lustre in production, please consider supporting the project financially over on GitHub sponsors.