Mflask

Mflask is a small, Flask-inspired web framework for Elixir built on top of Plug and Bandit. It provides a minimal, expressive routing DSL, simple response helpers, and a few convenience middleware modules so you can write tiny web apps with familiar patterns.

This README covers:


Quick start

Add mflask to your dependencies (if using this project as a dependency). For local development, you can use the example app pattern or run a module directly with the included mix task.

Example minimal app:

  1. Create a file example_app.ex:
defmodule ExampleApp do
  use Mflask

  get "/" do
    text(conn, "Hello, world!")
  end

  get "/hello/:name" do
    name = path_param(conn, "name") || "friend"
    html(conn, "<h1>Hello #{name}</h1>")
  end
end
  1. Serve the app from the directory containing example_app.ex:
# from the project root (or directory containing example_app.ex)
mix mf.serve . --port 4000

Open http://localhost:4000 to see the app.


Router and DSL

Mflask exposes a compact routing DSL inspired by Flask. Inside a module use Mflask to get routing macros and helpers.

Supported route macros:

Path parameters:

Query and body helpers:

Example:

defmodule UsersApp do
  use Mflask

  get "/users/:id" do
    id = path_param(conn, "id")
    json(conn, %{user_id: id})
  end

  get "/search" do
    q = query_param(conn, "q", "")
    json(conn, %{query: q})
  end
end

Response helpers

Mflask provides helpers to send common response types:

These are imported automatically into router modules.


Middleware

Mflask supports composing plugs as middleware. Use Mflask.Router.plug/2 in a router to attach middleware.

Included middleware:

Example:

defmodule ApiApp do
  use Mflask

  # attach middleware for this router
  Mflask.Router.plug(Mflask.Middleware.BodyParser)
  Mflask.Router.plug(Mflask.Middleware.Logger)

  post "/echo" do
    json(conn, body_params(conn))
  end
end

Notes:


Templates

Mflask ships a small EEx-based helper Mflask.Template:

When rendering a template with a layout:, the layout can reference <%= @inner_content %>. Helpers ensure a couple of common assigns are present to avoid warnings.

Example:

inner = "<p>Inner content: <%= @name %></p>"
layout = "<html><body><%= @inner_content %><footer>v<%= @ver %></footer></body></html>"

full =
  Mflask.Template.render_string(inner, assigns: [name: "Alice"])
|> then(fn content ->
  Mflask.Template.render_string(layout, assigns: [inner_content: content, ver: "0.1"])
end)

Running example apps with mix mf.serve

The project includes a mix task mix mf.serve to load Elixir files from a directory and start a Bandit server.

Usage:

mix mf.serve [PATH] [--module MyApp] [--port 4000] [--ip 127.0.0.1]

# examples:
mix mf.serve examples/                # scan and pick a module to serve (prefers ExampleApp)
mix mf.serve . --module ExampleApp    # explicitly serve ExampleApp from current dir
mix mf.serve examples/ --port 8080    # serve on port 8080

Behavior:

Security note: requiring arbitrary code will execute top-level code. Only run this task on trusted source trees.


Testing

This project uses ExUnit. Tests are split into focused files under test/:


Development notes


Contributing

Contributions are welcome. Suggested workflow:

  1. Fork the repository.
  2. Create a feature branch.
  3. Add or update tests when introducing behavior changes.
  4. Run mix test and ensure all tests pass.
  5. Open a merge request describing the change.

Please follow idiomatic Elixir formatting (mix format) and keep commits focused.


License

Mflask is distributed under the GPL-3.0 license. See LICENSE.md for details.


Contact / Support

If you run into issues, report them through the project tracker. For quick questions, open an issue with a minimal reproduction.