jonnifyelixir
Contents / F6 · Phoenix Framework / What we’re building

F6 · system design · 2 of 3

What we’re building

A real learning platform, not a framework demo. A learner opens the Portal, browses a catalog, enrolls in a course, works through lessons, and watches their progress — and when an instructor publishes a lesson or another learner finishes one, the page updates live, with no refresh. Underneath, the picture is the F5 stack with one band added on top: a Phoenix web layer — endpoint, router, controllers, and LiveViews — that calls the F5 facade and renders the result. The engine, the domain core, and the F4 store are exactly as F5 left them. F6 builds the top band and the persistence adapter beneath; everything between stays put.

Select a layer to see what it does and which chapter builds it. The new work in F6 is the web band on top and the Ecto adapter at the bottom; the two middle layers are the F5 engine.

The full stack

A request travels down and a render travels back up, exactly as in the F5 blueprint — only now the top layer is Phoenix rather than a thin server. A controller or a LiveView receives the request, calls the facade, and turns the result into HEEx; live updates push back up the same stack. The engine still reaches no further than its own boundary.

The stack · select a layer

request ↓ ↑ render · live updates PHOENIX WEB endpoint · router · controllers · LiveView F6 ENGINE FACADE Portal — the one public API F5.08 DOMAIN CORE contexts · commands · queries · events F5.02–F5.06 PERSISTENCE branded CHAMP store + Ecto adapter F4 / F6.03

layer: Phoenix web

built by: F6

The product is the platform, but the new code is a thin band on top and an adapter at the bottom. The two layers that hold the rules were finished in F5; F6 does not reopen them.

The web layer in code

Every handler in the platform has the same shape: receive a request, call the facade, render the result. A controller does it for a classic request; a LiveView does it in mount and handle_event. Neither reaches past Portal and %Portal.Error{}, so the whole web layer stays a thin translation between HTTP and the engine.

# the web layer is thin: call the facade, branch on its result, render
defmodule PortalWeb.EnrollmentController do
  use PortalWeb, :controller

  def create(conn, %{"user" => u, "course" => c}) do
    case Portal.enroll(u, c) do
      :ok ->
        redirect(conn, to: ~p"/courses/#{c}")

      {:error, %Portal.Error{message: msg}} ->
        conn |> put_flash(:error, msg) |> redirect(to: ~p"/courses")
    end
  end
end

# a LiveView is the same shape, live: mount queries, handle_event commands (F6.06)

one product, many surfaces

Catalog, enroll, lessons, progress, a live dashboard — all of it over one facade.

a thin web band

Controllers and LiveViews translate HTTP to facade calls and back — nothing more.

Next in the design brief: wiring Phoenix onto the F5 engine — the supervision tree, the router, and the LiveView seam in code.

References

The layers F6 adds on top of the F5 engine.

Sources

Related in this course