This library provides Nitrogen-like templating for your Plug applications.
Each Nitroux
function represents an HTML tag and generates HTML content:
iex> Nitroux.hr()
"<hr/>"
Each Nitroux function can accept text as a function parameter, allowing you to include text content within the generated tags:
iex> Nitroux.div("hello world")
"<div>hello wordl<div/>"
Each Nitroux
function can accept keyword lists as function parameters. Each item in the list will
be appended as an attribute to HTML. Hyphen-separated attributes should be passed as strings:
iex> Nitroux.div(class: "red", id: "1", 'data-model': "2")
"<div class=\"red\" id=\"1\" data-model=\"2\"><div/>"
If html
key is present, its value is treated as HTML content. html
value can be a string, a Nitroux
function, or a list thereof.
iex> Nitroux.div(html: p("hello world"))
"<div><p>hello world</p></div/>"
If you want additional type hints and don't mind additional verbosity, use Nitroux.HtmlTypedTags
module. Instead of html
key in keyword parameters, content is passed via a second parameter, which can be either a tag or a list of tags.
iex> Nitroux.HtmlTypedTags.div([class: "red"], Nitroux.HtmlTypedTags.p([], "hello world"))
"<div class=\"red\"><p>hello world</p></div/>"
Take this HTML as an example:
<ul>
<li class="tab-1">Tab1</li>
<li class="tab-2">Tab2</li>
<li class="tab-3">Tab3</li>
</ul>
We usually don't think of HTML as code, but if we were to treat it as such, we would have to admit that this example does not adhere to the DRY (Don't Repeat Yourself) principle. Nitroux solves this problem by allowing us to think of HTML as code, while keeping our maintenance burden to the minimum. The above example becomes:
import Nitroux
ul(
1..3
|> Enum.map(fn x ->
li(
class: "tab-#{x}",
html: "Tab#{x}"
)
end)
)
While the benefits of Nitroux might not be immediately apparent in this simple example, its value becomes evident when compared to the "no-js" approach, as currently proposed by the Phoenix framework through Phoenix.LiveComponent
.
Imagine dealing with evolving business requirements that involve intricate conditional rendering logic, customization using a multitude of inline Tailwind CSS
utility classes, sprinkled with numerous phx-hooks
, all within non-standard HTML HEEx
component functions. Additionally, frontend developers might contribute JavaScript code to integrate with third-party services. This complex mix can quickly lead to what's known as a "Big Ball of Mud" in your codebase.
Nitroux offers an alternative approach. Instead of reinventing HTML with a custom DSL, it encourages you to treat all HTML as pure Elixir functions. This approach assumes that you want to leverage your existing front-end tools while minimizing the abstraction layers between your Elixir models and the front-end. With Nitroux, you can bid farewell to .eex
templates and eliminate the proliferation of empty _view
files that often clutter Phoenix projects.
Nitroux is an ideal choice for scenarios involving Web Components, lightweight JavaScript frameworks like Alpine JS, HTMX, Stimulus, or comprehensive HTML/XML parsers like Owl or the now-deprecated AngularJS. It simplifies the development process and promotes cleaner, more maintainable code that even novice frontend developers can maintain.
For a starter template using Nitroux in a Phoenix Application, check out PHX-Boilerplate.
If available in Hex, the package can be installed
by adding nitroux
to your list of dependencies in mix.exs
:
def deps do
[
{:nitroux, "~> 0.4"}
]
end
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/nitroux.