Getting Started
Installation
In this section, we will install all the dependencies for the Phoenix framework including installation of Elixir and Erlang. We will cover installation instructions for macOS and Ubuntu/Debian here. However, Phoenix can run in several flavors of Linux as well as in Microsoft Windows. For installation instructions related to other platforms, check out the official installation page for Elixir and Phoenix.
Homebrew for macOS
We will be using the Homebrew package manager for installing all the Phoenix dependencies for macOS. So if you don’t have Homebrew installed, go to https://brew.sh and copy paste the install script on your terminal to install it. While Homebrew is not a prerequisite for Phoenix or Elixir, it helps us to install everything we need from the comfort of the command line.
Installing Elixir and Erlang
→ brew install elixir
The above command installs the latest stable version of Elixir along with Erlang. At the time of writing, this installs Elixir 1.4 which is what we need.
On Ubuntu and Debian
We need to install Erlang and Elixir individually.
Download the Erlang package and install it.
→ wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
→ sudo dpkg -i erlang-solutions_1.0_all.deb
→ sudo apt-get update
→ sudo apt-get install esl-erlang
Now you can install Elixir using:
→ sudo apt-get install elixir
Installing Postgresql
Phoenix projects by default are configured to work with the Postgresql database, though, any database that is supported by the Ecto library will work. We can also use Phoenix without any database if we need to. In this book, we will use the Postgresql database as it enjoys good support in the Elixir community. In addition to being well supported it also has features not provided by other databases that we will require later.
→ brew install postgresql
Once installed, Brew will print post installation notes as shown below:
... To have launchd start postgresql now and restart at login: brew services start postgresql Or, if you don't want/need a background service you can just run: pg_ctl -D /usr/local/var/postgres start
Be sure to run either of the commands shown above as per your need. Normally, I run brew services start postgresql
so that I can forget about starting the Postgres server every time I restart my system.
Brew installs Postgresql and creates a default super admin. The name of this super admin is the same as the name of your currently logged-in system account name while the password is left empty. We could just go with that. However, for every Phoenix project that we create, we need to modify the configuration file to give the right credentials for the Postgres database.
Phoenix projects by default expect the Postgres admin username to be postgres
with the password postgres
. We can save a few key strokes for every new project by creating a Postgres user as expected by Phoenix. Login to Postgres shell by typing psql -d postgres
on your terminal.
On the Postgres console, type the following commands to create a super user by name postgres
with the password postgres
.
postgres=# CREATE USER postgres;
postgres=# ALTER USER postgres PASSWORD 'postgres';
postgres=# ALTER USER postgres WITH SUPERUSER;
postgres=# \q
On Ubuntu and Debian
Install postgresql
and postgresql-contrib
through apt-get
as shown below:
→ sudo apt-get install postgresql postgresql-contrib
Ubuntu installation of Postgres creates a default super admin in the name of postgres
but doesn’t set the password. So you might want to set the password to postgres
on your local machine to match the default settings for Phoenix projects. Login to Postgres shell by typing sudo -u postgres psql postgres
on your terminal.
postgres=# ALTER USER postgres PASSWORD 'postgres';
postgres=# \q
Nodejs
Phoenix projects by default are setup to use Brunch — a nodejs tool for the management of asset files. In the development environment, all static files like images, fonts, CSS and Javascript files get processed by Brunch before Phoenix serves them. In the production environment we can use the precompiled files from our development machine without having to use Brunch on the production server.
Even in the development environment Brunch is not a hard dependency — meaning if we don’t want Brunch we can simply remove a simple configuration line in our project and still have Phoenix continue to work. Or we could replace Brunch with other tools like Webpack if we prefer. We will install Nodejs as we will use Brunch for managing the asset files in the development environment.
→ brew install node
→ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
→ sudo apt-get install -y nodejs
inotify-tools (only for linux)
In the development environment, Phoenix provides live reloading feature that automatically refreshes our browser tabs whenever we change the source code in our project. On linux machines, this feature is dependent on inotify-tools
while it’s not needed on macOS or windows.
Install inotify-tools
using the command shown below:
→ sudo apt-get install inotify-tools
Hex Package Manager
Hex is the package manager for Elixir libraries. It allows us to upload/download Elixir libraries from the https://hex.pm website.
→ mix local.hex
Rebar - Erlang Build Tool
rebar
and rebar3
are Erlang build tools for compiling and testing Erlang applications. Since our Phoenix project will depend on some of the Erlang libraries, we need Rebar to be installed on our machine.
→ mix local.rebar
mix
is a command line binary that gets installed as part of the Elixir language installation. Since this is a sub-command of mix
, a binary installed in our system as part of installing Elixir, the above command to install hex
and rebar
is same for all OS.
Phoenix Project Generator
And finally to install the Phoenix project generator, run the following command:
→ mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez
It’s important to note that the above command installs the Phoenix project generator and not Phoenix itself. After installing the Phoenix generator, all that we get is a new sub command to mix
, to create a new Phoenix project. The Phoenix framework itself gets installed within our project directory under the deps
folder when we run the mix deps.get
command which we will see shortly.
Validating the Installation
Run the following commands on the terminal to confirm you have installed the correct version of Elixir, Phoenix the required dependencies.
→ elixir -v
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Elixir 1.4.0
Elixir version should be 1.4.0 or higher.
→ mix help | grep 'phx.new'
mix phx.new # Creates a new Phoenix v1.3.0 application
Phoenix version should be 1.3.0 or higher.
→ psql --version
psql (PostgreSQL) 9.6.1
PostgreSQL version should be 9.4 or higher.
→ node -v
v7.2.1
Node version should be 5.0.0 or higher.
Code Editor
For a good developer experience, we will need a code editor that supports syntax highlighting and auto code completion for Elixir. There are several text editors that support the Elixir language. My personal choice is the Atom editor.
If you are a die-hard Emac or Vim fan, you might want to check out Spacemacs. For the rest of us, Atom works as a good editor for working with Elixir projects.
If you go with Spacemacs, do install the excellent Alchemist package for Elixir. It provides syntax highlighting, code completion and several other features that help your development workflow with Elixir projects. If you are on Atom, you can install language-elixir and atom-elixir packages to do similar stuff in Atom. The Atom packages can be installed from the terminal with a single command.
→ apm install language-elixir atom-elixir
If you are not a fan of either of these editors, pick up one that suits your taste, but make sure that it at least supports syntax highlighting for Elixir.
Create a New Phoenix project
In this section, we will quickly run through the steps required to create a new Phoenix project and add a new page to it. This exercise is to quickly glance at the various moving parts of Phoenix and not to master them. So don’t worry if you find it difficult to understand the code or if all this seems too fast paced. We will spend adequate time in the rest of the book to build understanding.
Let’s create a new Phoenix project using the mix generator command phx.new
. It is the new sub command to mix
binary that gets added when we installed the Phoenix generator in section 1.1.8.
Open up your terminal and run the following code.
→ mix phx.new learn_phoenix
This command creates a new folder learn_phoenix
in your present working directory. In my case, my pwd
is ~/pio
and the new Phoenix project is initialized in ~/pio/learn_phoenix
folder.
You will be prompted to either download the dependencies or skip them as below.
Fetch and install dependencies? [Yn]
Choose "Y" to download the dependencies. The installer will then proceed to download all required Elixir libraries from https://hex.pm (the official package manager site for Elixir projects). It will also download nodejs packages from https://npm.org, specifically Brunch and its friends which are used for assets management in Phoenix.
* running mix deps.get
* running npm install && node node_modules/brunch/bin/brunch build
We are all set! Run your Phoenix application:
$ cd learn_phoenix
$ mix phx.server
You can also run your app inside IEx (Interactive Elixir) as:
$ iex -S mix phx.server
Before moving on, configure your database in config/dev.exs and run:
$ mix ecto.create
For now, it will suffice to know that the mix phx.new
command has downloaded several Elixir libraries in your project’s deps
folder and also downloaded several nodejs packages in assets/node_modules
.
Note
|
It’s important to note that all dependencies are installed in deps folder inside our project folder including phoenix i.e., the Phoenix framework is installed locally per project and not system-wide.
|
However, the Phoenix new project generator that we installed in the previous section is a system-wide installation that gives us the command mix phx.new
.

The contents of the assets/node_modules
directory is too big to show here in full and not very relevant to what we are learing.
Now run mix phx.server
from inside the project directory.
→ mix phx.server
This will take some time as Elixir compiles all the Elixir source code from our project and its dependencies into .beam
files. Once compiled, you will see the following message on your terminal.

There are several error messages and then a line that reads
[info] Running LearnPhoenixWeb.Endpoint with Cowboy using http://0.0.0.0:4000
Let’s ignore those errors for now and open our browser to http://localhost:4000. We will be greeted with Phoenix welcome page:

Now back to the errors that we saw in the terminal. Our application is trying to connect to a Postgres database which doesn’t exist.
Let’s fix this error. Hit CTRL+c twice in the terminal running Phoenix server to stop it. Open config/dev.exs
file in your editor and check if the Postgres login credential given are correct and Phoenix has the privilege to create a new Postgres database.
config :learn_phoenix, LearnPhoenix.Repo,
adapter: Ecto.Adapters.Postgres,
username: "postgres",
password: "postgres",
database: "learn_phoenix_dev",
hostname: "localhost",
pool_size: 10
If our local PostgreSQL username is postgres
and password is supersecret
, we need to change the database configuration in config/dev.exs
file (shown above) to reflect the same.
# Change this only if your credentials are different
...
username: "postgres",
password: "supersecret",
...
However, if you followed the instructions to create Postgres superuser as previously explained in section 1.1.3, you don’t have to make any change in the config/dev.exs
file.
After the database connection details have been configured correctly, we can now run mix ecto.create
to create a database for our Phoenix app and then run mix phx.server
. This time we won’t see those db connection errors as our Phoenix application is now able to connect to the database.
→ mix ecto.create
→ mix phx.server
Phoenix File Structure
Our learn_phoenix
directory looks like this:

Assets and Priv
The top level directory assets
contains css, js, images, fonts and any other static files within respective sub folders. While the assets
directory contains the original source code for our assets, the priv
directory contains the compiled version of the same asset files. The priv
directory is also the place where translation files and database migration files get stored. We will dig into these files more in the coming chapters.
Config
The config
directory contains files that store various configurations for our project like the database credentials, port number of the web server etc. Phoenix projects by default are configured to support three different environments — dev
, test
, prod
.
Configuration files for each of these environments are present in the config
directory as shown below:

Test
The test
directory contains the various test code for our projects. We will create files in this directory when we start with Test Driven Development.
Lib
The lib
folder contains our project’s main code.

We will spend most of our time within the lib
directory. All code that is specific to our project belongs here. This directory contains two subdirectories: first with the same name as our project and the second with a web
suffix to our project name i.e., lib/learn_phoenix
and lib/learn_phoenix_web
The learn_phoenix_web
directory is the home of the web interface specific code for our project.
That is, the learn_phoenix_web
directory contains code for starting web server, defining routes, controllers, HTML templates etc.
All non-web related code go into the lib/learn_phoenix
directory. This includes the context and schema files for our project. We will look into these in detail in Chapter 3.
Note
|
Module names are nested in Phoenix just like the folder structure. From now on, we will refer to long module names such as |
Control Flow in Phoenix
We haven’t done anything with our new Phoenix project yet. Let’s try to understand how the welcome page works and then mimic the same to create a new page at http://localhost:4000/about.
My preferred way to read an MVC web app is to start at its router file. This approach makes it easy to understand the control flow of various paths.
The router file for our Phoenix project is at learn_phoenix_web/router.ex
.
defmodule LearnPhoenixWeb.Router do
...
scope "/", LearnPhoenixWeb do
pipe_through :browser
# => Focus just on this line below and ignore everything else
get "/", PageController, :index (1)
end
...
end
-
Router definition for homepage
/
If you are familiar with any MVC framework, you might have at least guessed what this line of code means:
get "/", PageController, :index
It basically says, for any request coming to /
path (i.e., homepage), call the index
function of the PageController
. The controller functions that are mapped in the router for a specific path are also called controller actions
.
Our PageController
defined at learn_phoenix_web/controllers/page_controller.ex
looks like this now:
defmodule LearnPhoenixWeb.PageController do
use LearnPhoenixWeb, :controller
def index(conn, _params) do
render conn, "index.html"
end
end
The index
action receives the control from router and it renders the index.html
file.
Again if you are coming from Rails or another MVC frameworks, you might guess that this file exists in the views
folder. However, it turns out that our learn_phoenix_web/views
folder does not have any html template files. Rather it contains a file called page_view.ex
which defines PageView
module.
Looking around in the other generated directories, it’s easy to find the index.html.eex
. It lives inside the directory learn_phoenix_web/templates/page/
. The contents of the file also confirms that it’s the same as the one that we see in the homepage.
Note
|
Naming conventions
The render function within the
|
At this point it might be difficult to understand the purpose of PageView
module as it is almost empty.
defmodule LearnPhoenixWeb.PageView do
use LearnPhoenixWeb, :view
# nothing here
end
While it’s tempting to conclude that PageView
does nothing, that is not correct. To understand it, let’s change the render function call in our PageController
module as below:
defmodule LearnPhoenixWeb.PageController do
use LearnPhoenixWeb, :controller
def index(conn, _params) do
render conn, "index_new.html" # Change the template name
end
end
Now if we visit the homepage, we are obviously greeted with an error. This error is however helpful to understand what is happening under the hood.

A layman’s translation of the error message is below:
Note
|
It’s common to see function names referred to in the format The number after |
Now instead of creating a new template index_new.html.eex
in the template folder, let’s create a new function render/2
in our PageView
module as below:
defmodule LearnPhoenixWeb.PageView do
use LearnPhoenixWeb, :view
def render("index_new.html", _) do
{:safe, """
<h1>Hello World!</h1>
<p>This template is rendered from PageView</p>
"""}
end
end
Now going back to our homepage, we should see the new message displayed as given in our PageView
module.

We will now remove this render
function from the PageView
module and add just the html to a new index_new.html.eex
file inside learn_phoenix_web/templates/page
. Back to the browser, the result is the same.
So what is happening here? It’s Phoenix magic powered by Elixir’s metaprogramming feature.
When we call render(conn, "index_new.html")
from our PageController
we are calling a function defined in the Phoenix.Controller
module. It then calls render("index_new.html", _)
defined inside our PageView
module.
But we have just removed this function from the module. So it’s not there to be called and we expect an error.
Here is the nice little trick that Phoenix does.
During compilation process, it looks for any template files in the template folder ending in .eex
suffix.
It then takes out the contents of each of these files and creates a render/2
function in the respective View modules similar to what we have created.
To summarize, the sequence of events happening when you visit http://localhost:4000/ are:
-
The router checks if the incoming request path is for
/
and calls theindex
action in thePageController
module. -
The
index
action on the controller calls thePhoenix.Controller.render(conn, "index.html")
function. Since the modulePhoenix.Controller
is imported in all controllers, we are calling the functionrender
without the module name prefix. If you are new to Elixir and don’t know whatimport
is, you will learn it in the next Chapter. -
Phoenix.Controller.render/2
calls a similarly namedrender/2
function inPageView
containing the compiled code from the template fileindex.html
. The result of this function call is then displayed on the browser.
Now armed with this knowledge, let’s create a new page at /about
. Based on knowledge gained so far, we know we need to do the following to complete our task:
-
Router
-
modify router to map the new path
/about
to a function in aPageController
. Let’s call this functionabout
-
-
Controller
-
create a new function
about/2
in our controller. It should call therender/2
function with the template nameabout.html
-
-
View
-
since
PageView
module already exists, we don’t have to create it again. -
define a new template
about.html.eex
insidelearn_phoenix_web/templates/page
folder and add the HTML content.
-
Let’s modify the router as below to create a static page at http://localhost:4000/about.
scope "/", LearnPhoenixWeb do
pipe_through :browser
get "/", PageController, :index # => Add this line below.
get "/about", PageController, :about
end
Modify our PageController
and add a new function as below:
defmodule LearnPhoenixWeb.PageController do
use LearnPhoenixWeb, :controller
(...)
def about(conn, _params) do
render conn, "about.html"
end
end
Inside our learn_phoenix_web/templates/page
, create a new file about.html.eex
and add some HTML data.
<!-- web/templates/page/about.html.eex -->
<h1>About</h1>
<p>Some content</p>
Now back to the terminal and run mix phx.server
if it’s not already running. Let’s open http://localhost:4000/about in our browser to see the message we added in our template file.

We have now learned how the request for a web page flows through various parts of our Phoenix app and how to create a new static page in our application.
Summary
Let’s recap on the key concepts that we learnt in this chapter.
We learnt to install the various dependencies of the Phoenix Framework for macOS & for Ubuntu/Debian OS. We also installed the Phoenix project generator which we use by issuing the command mix phx.new projectname
As with any other Elixir project, we learnt that the Phoenix framework is installed as one of the dependencies of our project inside the deps
folder. Hence all Phoenix projects are self-contained with a version of Phoenix installed inside each project.
We also configured the database connection, got to know a few mix tasks and understood the file structure of Phoenix.
Then we moved on to understanding how a page request is served by Phoenix. We did this by looking at the various interconnected critical components of our project including the Router, Controller, View and Templates.
Along with this, we also understood the inherent naming conventions and how Phoenix automatically identifies and links Controllers, Views and Templates.
Finally, we flexed our muscle by creating a new static page and getting it served successfully.