Phoenix Min

Slim down Phoenix to LiveView-only with inline HEEx templates

Phoenix Min is a post-installation tool that transforms a default Phoenix installation by removing controller-based infrastructure and converting all templates to inline HEEx using the ~H sigil.

Why Phoenix Min?

Phoenix is fantastic, but the default installation includes controller infrastructure that you might not need if you're building a LiveView-only application. Phoenix Min embraces:

  1. LiveView-first: All pages are LiveViews, no controllers needed
  2. Colocation: Templates live in the same file as behavior (no more .html.heex files)
  3. Simplicity: Fewer files, fewer directories, easier navigation
  4. Flexibility: Works with or without Ecto, assets, gettext, etc.

Installation

Option 1: One-Step Install (Recommended)

Create a new Phoenix application with Phoenix Min already applied:

mix igniter.new my_app --install phoenix_min --with=phx.new

This single command creates a new Phoenix application and immediately applies all Phoenix Min transformations.

Option 2: Add to Existing Project

Add phoenix_min to your Phoenix project's mix.exs:

def deps do
  [
    {:phoenix_min, "~> 0.1.0", only: [:dev], runtime: false}
  ]
end

Then fetch dependencies:

mix deps.get

Usage

Option 1: One-Step Install

Create a new Phoenix application with Phoenix Min in one command:

mix igniter.new my_app --install phoenix_min --with=phx.new
cd my_app

Igniter will show you a diff of all the changes. Review and accept them.

Option 2: Add to Existing Project

After creating a new Phoenix application:

mix phx.new my_app
cd my_app

Run the Phoenix Min installer:

mix igniter.install phoenix_min

Or directly:

mix phoenix_min.install

Igniter will show you a diff of all the changes. Review and accept them.

What Gets Modified

Phoenix Min makes the following transformations:

Files Created

Files Modified

Files Removed

What's NOT Modified

Example: Before & After

Before (Default Phoenix)

lib/my_app_web/controllers/page_controller.ex:

defmodule MyAppWeb.PageController do
  use MyAppWeb, :controller

  def home(conn, _params) do
    render(conn, :home)
  end
end

lib/my_app_web/controllers/page_html.ex:

defmodule MyAppWeb.PageHTML do
  use MyAppWeb, :html
  embed_templates "page_html/*"
end

lib/my_app_web/controllers/page_html/home.html.heex:

<div>Welcome to Phoenix!</div>

Router:

get "/", PageController, :home

After (Phoenix Min)

lib/my_app_web/home_live.ex:

defmodule MyAppWeb.HomeLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  def render(assigns) do
    ~H"""
    <div>Welcome to Phoenix!</div>
    """
  end
end

Router:

live "/", HomeLive, :index

Inline Templates in Phoenix

Phoenix Min uses inline HEEx templates via the ~H sigil. Here's how to write them:

defmodule MyAppWeb.MyLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, name: "World")}
  end

  def render(assigns) do
    ~H"""
    <div class="container">
      <h1>Hello, {@name}!</h1>
      
      <.button phx-click="greet">
        Say Hello
      </.button>
      
      <%= if @show_message do %>
        <p>Message shown!</p>
      <% end %>
    </div>
    """
  end

  def handle_event("greet", _params, socket) do
    {:noreply, assign(socket, show_message: true)}
  end
end

Layouts

Layouts are also converted to inline:

defmodule MyAppWeb.Layouts do
  use MyAppWeb, :html

  def root(assigns) do
    ~H"""
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <.live_title>{@page_title}</.live_title>
      </head>
      <body>
        {@inner_content}
      </body>
    </html>
    """
  end

  def app(assigns) do
    ~H"""
    <header>
      <nav>Navigation here</nav>
    </header>
    <main>
      <.flash_group flash={@flash} />
      {@inner_content}
    </main>
    """
  end
end

Philosophy

Phoenix Min is opinionated about LiveView-first development:

Compatibility

FAQ

Can I still use controllers?

Yes! Phoenix Min only removes the default PageController. You can still generate controllers with mix phx.gen.html or create them manually. Your existing controllers are not touched.

What about core_components.ex?

Phoenix Min leaves core_components.ex untouched. It's a large file with many components that you'll use across your app, so keeping it as-is makes sense.

Can I convert my existing LiveViews to inline?

Yes! Simply move the content from your .html.heex file into a render/1 function with the ~H sigil, then delete the template file.

What if I already deleted PageController?

Phoenix Min gracefully handles missing files. It will only modify what exists in your project.

Does this work with umbrella apps?

Yes! Phoenix Min detects umbrella apps and operates on the _web application.

Can I undo these changes?

While there's no automated "undo" feature, all changes are shown in a diff before you accept them. You can review and reject any changes you don't want.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Credits

Built with Igniter - the code generation and project patching framework for Elixir.