filipecabaco
Hi everyone,
I’ve been working on Francis, a lightweight framework built on top of Plug and Bandit that tries to get you from idea to a running endpoint with as little ceremony as possible. Think Sinatra for Elixir.
What it is
You use Francis in a module, define routes with get/post/ws/sse, and you have a running server. No routers, no controllers, no context boilerplate, just a function per route.
defmodule MyApp do
use Francis
get "/", fn _ -> %{hello: :world} end
get "/:name", fn %{params: %{"name" => name}} -> "hello #{name}" end
post "/", fn conn -> conn.body_params end
ws "/chat", fn
:join, socket -> {:reply, "welcome"}
{:received, msg}, _ -> {:reply, msg}
end
sse "/events", fn
:join, socket -> {:reply, %{id: socket.id}}
{:received, m}, _ -> {:reply, m}
end
unmatched fn _ -> "not found" end
end
Return a string and it renders as HTML. Return a map and it renders as JSON. Return a Plug.Conn for full control.
Get started
mix archive.install hex francis
mix francis.new my_app
cd my_app
mix francis.server
Or add to an existing project:
{:francis, “~> 0.3”}
If you use Claude Code, install the Francis skill for route patterns, SSE/WS gotchas, and security guidance:
npx skills add francis-build/francis@francis-thinking
Links
- Hex: francis | Hex
- Docs: Francis v0.3.3 — Documentation
- Site: https://francis.build
Curious what the community thinks. It is not trying to replace Phoenix, it is for when you want something closer to raw Plug without writing the same boilerplate every time. Happy to answer questions.
Trending in Announcing
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Benjamin-Philip
How exactly is Francis different from Plug’s built in Router DSL?
filipecabaco
Honestly not much as the idea it’s just to be a boiler plate reducer more than anything. The implementation it’s basically a DSL to simplify the approach with some “sane defaults” focused on reducing as much as we can the boilerplate needed for a quick API
AndyL
Francis is great! Quick API endpoints, prototypes, admin apps…
Related: FrancisHtmx — Francis HTMX v0.2.2
Thank you @filipecabaco !!
PS Does anyone have experience embedding Francis into a Phoenix app?
I think it would be done in the Phoenix router…
filipecabaco
Thank you
honestly never tried it but can experiment with it and add as an example later
filipecabaco
Ok I did try out and it does work as you said
since it’s just Plug it’s all good
AndyL
A new super-power unlocked!
Thanks again for this great library.
josefrichter
Thanks for Francis @filipecabaco ! Always loved Sinatra for prototyping and side projects, so I love Francis by definition.
So much so that I just migrated my personal website https://josefrichter.design to it, and added a simple chat widget there using Francis’ SSE, telegram bot and Mac widget.
Also created francis_template | Hex in the process, because I needed it and the francis_htmx didn’t fit my needs.
LostKobrakai
I’d love to know what you feel is heavy.
phoenix_htmlorphoenix_templateare maybe like twice the loc offrancis_templateand most of the additional loc are the additional form abstraction of phoenix_html. None of that is a heavy dependency.josefrichter
You are right, that was gross overstatement. Fixing! Thank you
filipecabaco
Thank you so much! Really glad to hear that.
I need to rethink fully
francis_htmxas it really got way out of hand in complexity which was a sign of bad implementationWill check
francis_template. I do like the idea as again follows the same ideas as francis - boilerplate reduction