//// Lustre's Dev Tools is a CLI (Command Line Interface) that provides a set of commands //// for running and building Lustre projects. If you're familiar with frontend Web //// development, you could consider the Lustre Dev Tools as something similar to //// [vite](https://vitejs.dev) but built right into the framework! If you're not //// familiar with what these tools are used for... then read on. //// //// > **Note**: currently one of lustre_dev_tools' dependencies is not compatible //// > with the most recent version of `gleam_json`, making it impossible to install. //// > To fix this, add `gleam_json = "1.0.1"` as a dependency in your `gleam.toml` //// > file. //// //// Lustre Dev Tools is written in Gleam and requires **Erlang** to be installed even //// if you are only building a JavaScript project. Most methods of installing Gleam //// will guide you through installing Erlang too, but make sure you have it installed //// before you try to use the Lustre CLI! //// //// Because the CLI is written in Gleam, you will run it using the `gleam` command. //// As an example, starting a development server looks like this: //// //// ```sh //// gleam run -m lustre/dev start //// ``` //// ////

//// lustre/dev add ////

//// //// This command lets you install development-specific binaries and tools from outside //// the Gleam ecosystem. Lustre tries to be smart about the executables it understands: //// if you try to build a project without esbuild it will grab it, if it finds a //// tailwind.config.js it will use tailwind, and so on. All binaries are added to //// `build/.lustre/bin` in case you need to execute them manually. //// //// ### `lustre/dev add esbuild` //// //// [Esbuild](https://esbuild.github.io) is a bundler and build tool for JavaScript //// projects. This is the backbone of a lot of Lustre's build tooling and will be //// installed automatically if you use `lustre build` or `lustre dev`. //// //// Example: //// //// ```sh //// gleam run -m lustre/dev add esbuild //// ``` //// //// ### `lustre add tailwind` //// //// [Tailwind CSS](https://tailwindcss.com) is a utility-first CSS framework popular //// among devs that want to quickly iterate on designs without touching CSS directly. //// This will be installed automatically if Lustre detects a `tailwind.config.js` file //// in your project. //// //// Example: //// //// ```sh //// gleam run -m lustre/dev add tailwind //// ``` //// ////

//// lustre/dev build ////

//// //// Gleam projects can be compiled to JavaScript but this output is not always //// desirable for frontend projects where many individual modules can cause HTTP //// bottlenecks and slower load times. The `lustre build` command produces different //// _bundles_ that are single JavaScript files containing all the code needed for an //// application to run. //// //// If a `lustre build` subcommand is run without the necessary tooling installed, //// Lustre will attempt to install it automatically. //// //// ### `lustre/dev build app` //// //// Bundle a Gleam application into a single JavaScript file. This requires a Gleam //// module in your project with the same name as the project itself, and a public //// `main` function that will be called when the application starts. //// //// _This can be any Gleam program_, but if your `main` function returns an //// `App(Nil, model, msg)` then Lustre will automatically generate some boilerplate //// to mount the app onto an element with the id `"app"` and start it. //// //// In addition to bundling, Lustre's dev tools will apply the following //// transformations to the output: //// //// - FFI modules will be copied into Gleam's build directory even if they are //// not directly under the `src/` directory. This is a temporary patch until //// the Gleam compiler supports this itself. //// //// - FFI modules that have *relative* imports to `*.gleam` modules will have //// their imports rewritten to point to the compiled `*.mjs` files instead. //// //// Flags: //// //// - `--minify` - Reduce the size of the output bundle by removing whitespace and //// renaming variables. This is useful for production builds. //// //// Example: //// //// ```sh //// gleam run -m lustre/dev build app //// ``` //// //// ### `lustre/dev build component` //// //// Lustre components are based on standard Web Components. This means they should //// be usable outside of Lustre and Gleam! The `lustre build component` command takes //// a module and bundles it into a single JavaScript file that can be included in //// _any_ Web app to register a new Custom Element that can be used like native HTML //// elements. //// //// For a module to be bundled as a component, it must adhere to the following rules: //// //// - There must be a `pub const name` that is a string representing the name of the //// component to register. Remember that it must always contain a hyphen and follow //// [these rules](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names). //// //// - There must be a `pub fn` that has the type `fn() -> App(Nil, model, msg)`. It's //// name is not important but in cases where multiple functions in a module fit this //// type, the _first_ one will be used. //// //// In addition to bundling, Lustre's dev tools will apply the following //// transformations to the output: //// //// - FFI modules will be copied into Gleam's build directory even if they are //// not directly under the `src/` directory. This is a temporary patch until //// the Gleam compiler supports this itself. //// //// - FFI modules that have *relative* imports to `*.gleam` modules will have //// their imports rewritten to point to the compiled `*.mjs` files instead. //// //// Arguments: //// //// - `` - The path to the Lustre component you want to bundle. This should //// be in the same format that you would write to import the module in a Gleam file, //// e.g. `ui/my_componnt` and **not** `src/ui/my_component.gleam`. //// //// Flags: //// //// - `--minify` - Reduce the size of the output bundle by removing whitespace and //// renaming variables. This is useful for production builds. //// //// Example: //// //// ```sh //// gleam run -m lustre/dev build component ui/counter //// ``` //// ////

//// lustre/dev start ////

//// //// The `lustre/dev start` command starts a development server that builds and serves your //// project. This lets you focus on development without having to worry about a backend //// or additional tooling. The page will automatically reload when you make changes //// to your project. //// //// Flags: //// //// - `--port` - The port to serve the project on. Defaults to `1234`. //// //// Example: //// //// ```sh //// gleam run -m lustre/dev start --port=8080 //// ``` //// //// ## Getting help //// //// Lustre Dev Tools is still an experimental work in progress. If you run in to issues //// or have ideas for how it could be improved we'd love to hear from you, either by //// [opening an issue](https://github.com/lustre-labs/dev-tools/issues) or reaching out //// on the [Gleam Discord server](https://discord.gg/Fm8Pwmy). //// // IMPORTS --------------------------------------------------------------------- import argv import glint import lustre_dev_tools/cli/add import lustre_dev_tools/cli/build import lustre_dev_tools/cli/start // MAIN ------------------------------------------------------------------------ /// The `main` function is used as the entry point for Lustre's dev tools. You /// shouldn't run this function in your code, but instead use `Gleam run` to run /// this module from the command line. To see what the dev tools can do, run: /// /// ``` /// gleam run -m lustre/dev -- --help /// ``` /// pub fn main() { let args = argv.load().arguments glint.new() |> glint.as_module |> glint.with_name("lustre/dev") |> glint.path_help(["add"], add.description) |> glint.add(at: ["add", "esbuild"], do: add.esbuild()) |> glint.add(at: ["add", "tailwind"], do: add.tailwind()) |> glint.add(at: ["build"], do: build.app()) |> glint.add(at: ["build", "app"], do: build.app()) |> glint.add(at: ["build", "component"], do: build.component()) |> glint.add(at: ["start"], do: start.run()) |> glint.run(args) }