Getting started

docker run -v $(pwd):/tmp tokumei/embark hello_tokumei
cd hello_tokumei
docker-compose up

Visit localhost:8080 from your browser.

See your new projects for working with your new service.

Don’t have docker installed? see Manual setup below.

Manual setup

Valid for version 0.7.1 and earlier only.

Go to Raxx channel for latest.

Create a new mix project

First use mix to setup a new elixir project.

mix new greetings_app --sup
cd greetings_app

Using --sup includes a supervision tree. This will oversee a webserver for the application.

Umbrella applications, A Tokumei application can be part of an umbrella or run independently. For larger project umbrella applications are reccommended.

Add Tokumei and webserver

Add :tokumei to the list of dependencies. We will use :ace_http for a webserver.

# mix.exs

  defp deps do
      {:tokumei, "~> 0.6.4"},
      {:ace_http, "~> 0.4.5"}

Run the mix task to fetch our dependencies.

mix dep.get

Supported webservers, several other webservers are available, see Raxx for details.


Define the application

All we need to make a compatible Raxx application is to use Tokumei. This module will become the entry point for web requests to our application.

defmodule GreetingsApp.WWW do
  use Tokumei

Starting the webserver

Once the application is defined it needs to be mounted on a server. Next we need a server to host it.

# lib/greetings_app.ex

defmodule GreetingsApp do
  use Application

  def start(_type, _args) do
    GreetingsApp.WWW.start_link([port: 8080, name: GreetingsApp.WWW])

To start the whole application, server included, use iex.

iex -S mix

Visit localhost:8080

Write tests

Testing applications built with Tokumei is incredibly easy. This is because under the hood it uses the simple Raxx interface.

test "The homepage should return a status 200 response" do
  response = Raxx.Request.get("/") |> GreetingsApp.WWW.handle_request(%{})
  assert response.status == 200
  assert response.body == "Hello, World!"

test "The www app has an action for the home page" do
  assert "/" == GreetingsApp.WWW.path(:index)

Run our tests using mix and we should see two failing tests

mix test


With the application, server and tests setup we can start adding features.


Routing is pattern matching a requests path to action handlers. Paths in Tokumei (and Raxx) are represented as a list of segments.

To serve an index page create a route for [].

# lib/greetings_app/www.ex

defmodule GreetingsApp.WWW do
  use Tokumei

  @route_name :index
  route [] do
    :GET ->
      Response.ok("Hello, World!")

See Tokumei.Router for further information on routing.


Create a template for the homepage at lib/greetings_app/www/templates/home_page.html.eex.

<!-- lib/greetings_app/www/templates/home_page.html.eex -->
<h1><%= @message %></h1>   

Using Tokumei will compile all .eex templates from a ./templates directory (relative to the router file). Render functions are available for each template and are called with a map of values.

# :index action
:GET ->
  Response.ok(render("home_page.html", %{message: "Hello, World!"}))

Content Type, Tokumei.Templates will add a content type to the response generated from the render function. The content type is derived from the file extension. A file called home_page.html.eex will generate a render function setting content type to text/html.

Static content

To add a favicon save one to lib/greetings_app/www/public/favicon.ico.

Content in ./public directory (relative to the router file) is automatically served.

See Tokumei.Static for more details.

Error handling

Tokumei action handlers are expected to return a response or a error tuple. Error handlers are used to transform errors to a valid response.

# lib/greetings_app/www.ex

defmodule GreetingsApp.WWW do
  use Tokumei

  @route_name :index
  route [] do
    :GET ->
      Response.ok("Hello, World!")
    :POST ->
      {:error, :bad_request}

  error :bad_request do
    Response.bad_request("This request was no good.")

  error %NotFoundError{path: path} do
    Response.not_found("Nothing here :-(")

A not NotFoundError exception is returned for any request that doesn’t match to an action handler.

See Tokumei.ErrorHandler for more options to handle errors.


Tokumei adds helpers to implement action handlers.

Lets rewrite our error handler so that users are redirected to the home page.

  # :error handler
  error %NotFoundError{path: path} do
    |> Flash.write(error: "Redirected from missing path")

See Tokumei.Helpers for the full range of available helpers.


HTTP requests are passed to action handlers as a Raxx.Request. These objects contain metadata associated with the request.

@route_name :info
route ["info"], request do
  :GET ->
    IO.inspect(request.scheme)  # "http"
    IO.inspect(    # ""
    IO.inspect(request.port)    # 8080
    IO.inspect(request.method)  # :GET
    IO.inspect(request.mount)   # []
    IO.inspect(request.path)    # ["info"]
    IO.inspect(request.query)   # %{"page" => "5"}
    IO.inspect(request.headers) # [{"accept", "text/html"}]
    IO.inspect(request.body)    # "Lorem ..."


Configuration is available to action handlers as the third argument to a route.

route ["config"], _request, config do
  :GET ->



  1. create app
heroku apps:create eexperiment
  1. Load up build pack
heroku buildpacks:set
  1. make sure port is taken from env variable
  {port, ""} = System.get_env("PORT") |> Integer.parse()

  children = [
    worker(Ace.HTTP, [server, [port: port, name: Tmp.WWW]])
  1. push
git add .
git commit -m 'initial commit'
git push heroku master

Building releases

Using releases is probably the recommended way to deploy elixir applications. Release can be build in Vagrant. This section of the getting started guide will use Vagrant, see /vm_sandox for setup.


Code reloading

NOTE: On Linux you may need to install inotify-tools.

ExSync is a general purpose code reloading facility. First add it to the list of dependencies.

# mix.exs

  defp deps do
      # ... previous dependencies
      {:exsync, "~> 0.1", only: :dev}

Then modify the applications to run ExSync on startup.

# lib/greetings_app.ex

defmodule GreetingsApp.WWW do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    case Code.ensure_loaded(ExSync) do
      {:module, ExSync} ->
      {:error, :nofile} ->

    # ... rest of applications start script.

Development dependencies, are loaded only when working in the development environment. By using ensure_loaded/1 we will only start code reloaded in the appropriate enviroments.

Where next

  • flash, see Tokumei.Flash
  • sessions, see Tokumei.Session.SignedCookies
  • HTTPS, see guide security with HTTPS
  • middleware, see guide writing middleware with macros
  • streaming (In progress, awaiting updated Raxx)
  • large projects router/action_handler/umbrellas overkill action handler and domain (In progress)