A start to developing a phoenix application

phoenix elixir

alt text

This is the start of long journey that will hopefully bring you as much joy as it has brought to me. In this post I will walk over how I personally like to get a new Elixir Phoenix Application going.

But before you can start you will need a few things installed on your system.

Installing the tools and languages.

Before you can start to play with the Phoenix framework you will the language that it runs on which is Elixir. There are many well written docs on this subject. https://elixir-lang.org/install.html

Though you can quickly become overwhelmed by the number of options if you are new to this. So for that I will give my personal opinion on how to best address installing elixir. For that I personally like to use a version manager tool called asdf.

Installing ASDF

ASDF is version tool used for many languages and applications. I wont go over how to install ASDF because there is already a well written guide for that here. https://asdf-vm.com/guide/getting-started.html

Once you get ASDF installed then its time to install Erlang. You will need to install Erlang before you install elixir as its a dependency and is also the language that Elixir is built upon. To do that lets use our ASDF tool to first add a plugin to install Erlang then install Erlang itself.

Note: Before we just into this before to also read this document for dependencies your OS may need before installing erlang. https://github.com/asdf-vm/asdf-erlang?tab=readme-ov-file#before-asdf-install

Once you feel ready to install Erlang via ASDF then its a matter of just simply:

asdf plugin-add erlang
asdf install erlang 27.1.2
asdf global erlang 27.1.2

Note as of writing this 27.1.2 is the current more recent version. You can check this by running asdf list-all erlang.
Also note that we use global to set the active global version of erlang. This is because we can have many active different installs of a Erlang. IE global vs local. In this case we are saying we want to activate this given version on a global level.

Installing elixir

Now we are ready to install elixir via ASDF.

asdf plugin-add elixir
asdf install elixir 1.17.3-otp-27
asdf global elixir 1.17.3-otp-27

Something to note here. We are saying we want to install elixir version 1.17.3 but also with otp version 27. OTP is the major version of the erlang version we just installed in the step before. Its important that this matches the major version you installed in the prior step.

Now with both of these languages installed you should be able to run asdf current and get an output of all the currently installed/active languages you have via asdf.

Installing phoenix.

There is a well written document on this already here https://hexdocs.pm/phoenix/installation.html But in short its really as simple as just running the following.

mix local.hex
mix local.rebar
mix archive.install hex phx_new

Given all the above ran successfully then you will now have access the phoenix mix commands for generating a new application, database migration and many other mix tasks.

Creating your Phoenix App.

With all the above installed and working we should be able to run the following to scaffold a new Phoenix application.

mix phx.new foo_bar --binary-id

Taking a quick look at the command we just ran we will see that first we use the mix task runner to run the phx.new task. We then passed it a project name of foo_bar and then an option of --binary-id I favor using binary ids over incrementing integers for many reasons but that’s a blog post for another day. Just realize that’s what each of these values are doing. You can obviously name your application anything, though in our example case here we named it foo_bar. Note this is a snake cased name to add with how the modules will be named. IE foo_bar turns into FooBar module names. Be sure to read up on the many options for the phx.new task as there are many other things you can do with it. You can read these options via the help command in mix.

mix help phx.new

After running the phx.new task you will likely be prompted to pull the deps. Fetch and install dependencies? [Yn] I would go ahead and do so since you will have to do it anyways at some point. This may take a moment as it will then go and download and then compile your app. From this point you will then likely get a set of responses like so.

We are almost there! The following steps are missing:

    $ cd foo_bar

Then configure your database in config/dev.exs and run:

    $ mix ecto.create

Start your Phoenix app with:

    $ mix phx.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phx.server

Before we can continue its time to set up our local database.

Lets go in to our project and create a docker compose file we will use to define our local db for development using either docker or podman.

cd foo_bar
touch docker-compose.yml

Now open our new docker file and put this inside.

services:
  db:
    image: docker.io/postgres:16.4-alpine3.20
    environment:
      POSTGRES_DB: foo_bar_dev
      POSTGRES_HOST_AUTH_METHOD: trust
    ports:
      - "5432:5432"
    volumes:
      - foo_bar_dev_data:/var/lib/postgresql/data
  site:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    ports:
      - "0.0.0.0:4002:4000"
volumes:
  foo_bar_dev_data:

Note the use of foo_bar to define our db and our volume. Change as needed.

Now spin up the db,

podman compose up db

With this you should now have a running local db we can now use with our project.

Running mix setup

Given you have ran the [Y] as a part of the questions in the phx.new steps for fetching and compiling your mix deps, you should be able to run the following.

mix setup

This should do everything from making sure you have everything to setting up your db.

Have a look at where we get our mix setup task from in our mix.exs file.

 defp aliases do
    [
      setup: ["deps.get", "ecto.setup", "assets.setup", "assets.build"],
      "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
      "ecto.reset": ["ecto.drop", "ecto.setup"],
      test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
      "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
      "assets.build": ["tailwind foo_bar", "esbuild foo_bar"],
      "assets.deploy": [
        "tailwind foo_bar --minify",
        "esbuild foo_bar --minify",
        "phx.digest"
      ]
    ]
  end

At this point you should be able to spin up your local server via mix phx.server and see a typical landing page given you navigate to localhost:4000 alt text

Setting up User login.

From here I would recommend generating a User login system for your app.

mix phx.gen.auth Users User users

Go ahead and say Y to their question of Do you want to create a LiveView based authentication system? [Yn]

This command will scaffold a lot for you out of the box. You should see the following.

* creating priv/repo/migrations/20241118202522_create_users_auth_tables.exs
* creating lib/foo_bar/users/user_notifier.ex
* creating lib/foo_bar/users/user.ex
* creating lib/foo_bar/users/user_token.ex
* creating lib/foo_bar_web/user_auth.ex
* creating test/foo_bar_web/user_auth_test.exs
* creating lib/foo_bar_web/controllers/user_session_controller.ex
* creating test/foo_bar_web/controllers/user_session_controller_test.exs
* creating lib/foo_bar_web/live/user_registration_live.ex
* creating test/foo_bar_web/live/user_registration_live_test.exs
* creating lib/foo_bar_web/live/user_login_live.ex
* creating test/foo_bar_web/live/user_login_live_test.exs
* creating lib/foo_bar_web/live/user_reset_password_live.ex
* creating test/foo_bar_web/live/user_reset_password_live_test.exs
* creating lib/foo_bar_web/live/user_forgot_password_live.ex
* creating test/foo_bar_web/live/user_forgot_password_live_test.exs
* creating lib/foo_bar_web/live/user_settings_live.ex
* creating test/foo_bar_web/live/user_settings_live_test.exs
* creating lib/foo_bar_web/live/user_confirmation_live.ex
* creating test/foo_bar_web/live/user_confirmation_live_test.exs
* creating lib/foo_bar_web/live/user_confirmation_instructions_live.ex
* creating test/foo_bar_web/live/user_confirmation_instructions_live_test.exs
* creating lib/foo_bar/users.ex
* injecting lib/foo_bar/users.ex
* creating test/foo_bar/users_test.exs
* injecting test/foo_bar/users_test.exs
* creating test/support/fixtures/users_fixtures.ex
* injecting test/support/fixtures/users_fixtures.ex
* injecting test/support/conn_case.ex
* injecting config/test.exs
* injecting mix.exs

With this all this in place all that’s left to do is fetch our new deps and run our migrations. If your server is still running stop it by double hitting ctnl+c and run the following

mix deps.get
mix ecto.migrate
mix phx.server

We should now see a nav bar with our login at the top with links pointing to “register” or “login”.

At this point you have the starting point of a working site and this should be a great place to learn all that phoenix has to offer.

I would recommend going over the all the files generated and really getting to know and understand how they work.

This concludes my starting guide to starting a phoenix application. Best of luck on your adventures.