How to structure a Phoenix project with frontend and api?

In a stock Phoenix app you get the following router:

> mix phx.new stock
> cat stock/lib/stock_web/router.ex

defmodule StockWeb.Router do
  use StockWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

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

  scope "/", StockWeb do
    pipe_through :browser

    get "/", PageController, :index
  end

  # Other scopes may use custom stacks.
  # scope "/api", StockWeb do
  #   pipe_through :api
  # end
  
  if Mix.env() in [:dev, :test] do
    import Phoenix.LiveDashboard.Router

    scope "/" do
      pipe_through :browser
      live_dashboard "/dashboard", metrics: StockWeb.Telemetry
    end
  end
end

Note the part commented out. Simple solution is to use that and create new folder in lib/ called stock_api/ (or wtv) that holds all your API logic, and just route API calls (that hit /api scope) to modules in stock_api/. Your “ecto backend” naively maps to contexts and as such should already be separate (at least in terms of file structure, in lib/stock/). As for extracting that into an app separate from your phoenix app, that is a matter of high debate; same for splitting into Umbrella.

Personally I’d start off with a reasonably decoupled monolith and abstract pieces out as I go. As with all technical opinions YMMV

4 Likes