filipecabaco

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


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.

Showing Posts 1 to 10

Benjamin-Philip

Benjamin-Philip

How exactly is Francis different from Plug’s built in Router DSL?

filipecabaco

filipecabaco OP

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

AndyL

Curious what the community thinks.

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…

defmodule MyAppWeb.Router do
  use MyAppWeb, :router

  <<< phoenix routes >>>

  scope "/francis" do
    forward "/", MyApp.FrancisRouter
  end
end 
filipecabaco

filipecabaco OP

Thank you :folded_hands:

honestly never tried it but can experiment with it and add as an example later

filipecabaco

filipecabaco OP

Ok I did try out and it does work as you said :+1: since it’s just Plug it’s all good

defmodule PhoenixEmbedWeb.Router do
  use PhoenixEmbedWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, html: {PhoenixEmbedWeb.Layouts, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", PhoenixEmbedWeb do
    pipe_through :browser

    get "/", PageController, :home
  end

  # Forward all /api requests to the Francis API router.
  # Phoenix strips the /api prefix, so Francis routes are relative (e.g. /items).
  forward "/api", PhoenixEmbedWeb.FrancisApi
end
AndyL

AndyL

A new super-power unlocked!

Thanks again for this great library. :heart_eyes:

josefrichter

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

LostKobrakai

It depends only on francis — no phoenix_html, no heavy view layer.

I’d love to know what you feel is heavy. phoenix_html or phoenix_template are maybe like twice the loc of francis_template and most of the additional loc are the additional form abstraction of phoenix_html. None of that is a heavy dependency.

josefrichter

josefrichter

You are right, that was gross overstatement. Fixing! Thank you

filipecabaco

filipecabaco OP

Thank you so much! Really glad to hear that.

I need to rethink fully francis_htmx as it really got way out of hand in complexity which was a sign of bad implementation :sweat_smile:

Will check francis_template. I do like the idea as again follows the same ideas as francis - boilerplate reduction :heart:

— All posts loaded —

Where Next? Top

Trending in Announcing Top

woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews