Lustre
✨ Make your frontend shine ✨
A framework for building Web apps in Gleam!
---
## Table of contents
- [Features](#features)
- [Example](#example)
- [Philosophy](#philosophy)
- [Installation](#installation)
- [Where next](#where-next)
- [Support](#support)
## Features
- A **declarative**, functional API for constructing HTML. No templates, no macros,
just Gleam.
- An Erlang and Elm-inspired architecture for **managing state**.
- **Managed side effects** for predictable, testable code.
- Universal components. **Write once, run anywhere**. Elm meets Phoenix LiveView.
- A **batteries-included CLI** that makes scaffolding and building apps a breeze.
- **Server-side rendering** for static HTML templating.
## Example
```gleam
import gleam/int
import lustre
import lustre/element.{text}
import lustre/element/html.{div, button, p}
import lustre/event.{on_click}
pub fn main() {
let app = lustre.simple(init, update, view)
let assert Ok(_) = lustre.start(app, "#app", Nil)
Nil
}
fn init(_) {
0
}
type Msg {
Incr
Decr
}
fn update(model, msg) {
case msg {
Incr -> model + 1
Decr -> model - 1
}
}
fn view(model) {
let count = int.to_string(model)
div([], [
button([on_click(Incr)], [text(" + ")]),
p([], [text(count)]),
button([on_click(Decr)], [text(" - ")])
])
}
```
## Philosophy
Lustre is an _opinionated_ framework for building small-to-medium-sized Web
applications. Modern frontend development is hard and complex. Some of that
complexity is necessary, but a lot of it is accidental or comes from having far
too many options. Lustre has the same design philosophy as Gleam: where possible,
there should be only one way to do things.
That means shipping with a single state management system out of the box, modelled
after Elm and Erlang/OTP. Open any any Lustre application and you should feel
right at home.
It also means we encourage simple approaches to constructing views over complex
ones. Lustre _does_ have a way to create encapsulated stateful components (something
we sorely missed in Elm) but it shouldn't be the default. Prefer simple functions
to stateful components.
Where components _are_ necessary, lean into the fact that Lustre components can
run _anywhere_. Lustre gives you the tools to write components that can run inside
an existing Lustre application, export them as a standalone Web Component, or run
them on the server with a minimal runtime for patching the DOM. Lustre calls these
**universal components** and they're written with Gleam's multiple targets in mind.
## Installation
Lustre is published on [Hex](https://hex.pm/packages/lustre)! You can add it to
your Gleam projects from the command line:
```sh
gleam add lustre
```
Lustre also has a companion package containing development tooling that you might
like to isntall:
```sh
gleam add --dev lustre_dev_tools
```
If you're using a different build tool, like Rebar3 or Mix, you can add Lustre
to your `rebar.config` or `mix.exs` file respectively.
```erlang
{deps, [
{lustre, "4.0.0"}
]}
```
```elixir
defp deps do
[
{:lustre, "~> 4.0"}
]
end
```
## Where next
To get up to speed with Lustre, check out the [quickstart guide](https://hexdocs.pm/lustre/guide/01-quickstart.html).
If you prefer to see some code, the [examples](https://github.com/lustre-labs/lustre/tree/main/examples)
directory contains a handful of small applications that demonstrate different
aspects of the framework.
You can also read through the documentation and API reference on
[HexDocs](https://hexdocs.pm/lustre).
## Support
Lustre is mostly built by just me, [Hayleigh](https://github.com/hayleigh-dot-dev),
around two jobs. If you'd like to support my work, you can [sponsor me on GitHub](https://github.com/sponsors/hayleigh-dot-dev).
Contributions are also very welcome! If you've spotted a bug, or would like to
suggest a feature, please open an issue or a pull request.