README.md

<h1 align="center">Lustre</h1>

<div align="center">
  ✨ <strong>Make your frontend shine</strong> ✨
</div>

<div align="center">
  A framework for building Web apps in Gleam!
</div>

<br />

<div align="center">
  <a href="https://hex.pm/packages/lustre">
    <img src="https://img.shields.io/hexpm/v/lustre"
      alt="Available on Hex" />
  </a>
  <a href="https://hexdocs.pm/lustre">
    <img src="https://img.shields.io/badge/hex-docs-ffaff3"
      alt="Documentation" />
  </a>
</div>

<div align="center">
  <h3>
    <!--
    <a href="https://lustre.build">
      Website
    </a>
    <span> | </span>
    -->
    <a href="https://hexdocs.pm/lustre/guide/01-quickstart.html">
      Quickstart
    </a>
    <span> | </span>
    <a href="https://hexdocs.pm/lustre">
      Reference
    </a>
    <span> | </span>
    <a href="https://discord.gg/Fm8Pwmy">
      Discord
    </a>
  </h3>
</div>

<div align="center">
  <sub>Built with ❤︎ by
  <a href="https://twitter.com/hayleighdotdev">Hayleigh Thompson</a> and
  <a href="https://github.com/lustre-labs/lustre/graphs/contributors">
    contributors
  </a>
</div>

---

## 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(_flags) {
  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 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 install:

> **Note**: the lustre_dev_tools development server watches your filesystem for
> changes to your gleam code and can automatically reload the browser. For linux
> users this requires [inotify-tools]() be installed

```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.