zhenfeng-zhu

zhenfeng-zhu

Nex - A minimalist web framework for indie hackers and startups

Hello Elixir community!

I’m excited to share Nex, a web framework I’ve been building for the past few months. It’s designed for indie hackers, startups, and anyone who wants to ship web applications fast without enterprise complexity.

The philosophy:

Nex embraces simplicity and convention over configuration. It’s built for:

  • :rocket: Rapid development – Ship features, not prototypes
  • :bullseye: Indie hackers & startups – Build profitable products
  • :bar_chart: Internal tools & dashboards – Admin panels, data dashboards
  • :counterclockwise_arrows_button: Real-time applications – Live dashboards, chat, streaming with SSE
  • :globe_with_meridians: Server-side rendering done right – Modern web apps without JavaScript overhead

What makes it different:

  1. File-based routing – No configuration. Drop a file in src/pages/, get a route.
  2. HTMX-first – Build interactive UIs with server-side rendering. No JavaScript framework needed.
  3. Hot reload – Instant feedback while developing via WebSocket.
  4. Real-time ready – Built-in Server-Sent Events for streaming data.
  5. Zero config – Works out of the box with sensible defaults.
  6. Production-ready – Docker included, deploy to Railway/Fly.io/Render in minutes.

Quick example:

defmodule MyApp.Pages.Todos do
  use Nex.Page

  def mount(_params) do
    %{todos: fetch_todos()}
  end

  def render(assigns) do
    ~H"""
    <h1>My Todos</h1>

    <form hx-post="/add_todo" hx-target="#todos" hx-swap="beforeend">
      <input type="text" name="title" required />
      <button>Add</button>
    </form>

    <ul id="todos">
      <li :for={todo <- @todos}>{todo.title}</li>
    </ul>
    """
  end

  def add_todo(%{"title" => title}) do
    todo = create_todo(title)

    ~H"<li>{@todo.title}</li>"
  end
end

Get started:

mix archive.install hex nex_new
mix nex.new my_app
cd my_app
mix nex.dev

Visit http://localhost:4000 and you’re running.

What’s included:

  • File-based routing with dynamic routes ([id], [slug], [...path])
  • HTMX integration with automatic CSRF protection
  • Server-Sent Events for real-time streaming
  • JSON API support
  • Hot reload development experience
  • Production-ready Docker setup

Example projects:

I’ve included several examples to get you started:

  • chatbot – AI chat with streaming responses using SSE
  • chatbot_sse – Real-time streaming with HTMX SSE extension
  • guestbook – Simple guestbook with persistence
  • dynamic_routes – Comprehensive showcase of all routing patterns

What’s NOT included:

  • Built-in ORM (use Ecto directly)
  • Authentication system (integrate your own)
  • Asset pipeline (use CDN for Tailwind/DaisyUI)

This is intentional – Nex stays minimal so you can choose your own tools.

I’d love your feedback!

  • Have you tried it? What worked? What didn’t?
  • What features would make it more useful?
  • Any pain points with the current approach?
  • Would you use this for your projects?

Links:

https://github.com/gofenix/nex

Looking forward to hearing from you!

Most Liked

chrismccord

chrismccord

Creator of Phoenix

Nex looks neat!

Great initiative! (I really wish Phoenix would have a less boilerplate code approach, and this is a great foundation)

Periodic reminder that phoenix_playground exists and this is a full Phoenix LiveView app:

Mix.install([
  {:phoenix_playground, "~> 0.1.8"}
])

defmodule DemoLive do
  use Phoenix.LiveView

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

  def render(assigns) do
    ~H"""
    <span>{@count}</span>
    <button phx-click="inc">+</button>

    <style type="text/css">
      body { padding: 1em; }
    </style>
    """
  end

  def handle_event("inc", _params, socket) do
    {:noreply, assign(socket, count: socket.assigns.count + 1)}
  end
end

PhoenixPlayground.start(live: DemoLive)
bartblast

bartblast

Creator of Hologram

Hey @zhenfeng-zhu! Congrats on the Nex launch – it’s great to see more innovation in the Elixir web ecosystem.

Quick thought on the HTMX vs Datastar vs LiveView wrapper approach (saw the Reddit thread as well): I’d suggest focusing on either HTMX or Datastar rather than creating a LiveView wrapper, since LiveView itself could evolve to adopt similar simplification patterns over time – or evolve in other directions entirely. The key issue is that you wouldn’t control that evolution.

@thiagomajesk – I appreciate your thoughts from our earlier conversation about coordination in the community. While I understand the desire for consolidation, I think there’s real value in having different opinionated solutions that take distinct approaches. It’s not always about competing for the same users – often it’s about growing the Elixir pie by offering developers choices that match their specific needs and philosophies.

The simplicity-first philosophy that Nex is pursuing definitely resonates, and I’m heading in a similar direction with Hologram’s standalone mode (which is admittedly long overdue – sorry about that! – but the funding side quest took quite a lot of time, though successful. Big news coming soon). The key difference is the approach: server-driven frameworks like LiveView, HTMX, and Datastar excel at certain use cases, while Hologram takes a different path by compiling Elixir to JavaScript and running it client-side. This avoids latency issues and opens the door to local-first features down the road.

Different problems, different solutions – and that diversity can strengthen the ecosystem as a whole.

ostap

ostap

IMO it’s all about the learning curve. I suppose someone coming over from Next.js would prefer Nex’s same file-based routing concept. As for HTMX, I vote LiveView :slightly_smiling_face:

Where Next?

Popular in Announcing Top

ostinelli
Let’s write a database! Well not really, but I think it’s a little sad that there doesn’t seem to be a simple in-memory distributed KV da...
New
dbern
I’m excited to announce that TaxJar has developed and open-sourced DateTimeParser. We developed it because we found a need to parse user ...
New
brainlid
LangChain is short for Language Chain. An LLM, or Large Language Model, is the “Language” part. This library makes it easier for Elixir a...
New
type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
mbuhot
Leverage Open Api 3.0 (Swagger) to document, test, validate and explore your Plug and Phoenix APIs. Generate and serve a JSON Open API ...
New
Crowdhailer
Raxx is an alternative to Plug and is inspired by projects such as Rack(Ruby) and Ring(Clojure). 1.0-rc.1 is now available. To use it re...
New
achempion
Hi, I would like to tell about my initiative to further maintain and develop Waffle project which is the fork of Arc library. The progre...
New
alisinabh
Hey everyone i’ve developed a library for Jalaali calendar for elixir which supports converting Gregorian dates to Jalaali and vice vers...
New
tfwright
After working on it for a couple of months and using it in production for most of that time, today I’ve released LiveAdmin, a LiveView ba...
New
wfgilman
I’ve cleaned up and open sourced three financial libraries I was using for my company. They are bindings for the APIs of these three comp...
New

Other popular topics Top

siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement