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
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
- Phoenix — Overview — the web layer on top of the stack.
- Ecto — the persistence adapter at the bottom.
- Phoenix — LiveView — the live surface of the platform.
Related in this course
- F6.0.1 · The developer journey — the path to this platform.
- F6.0.3 · Wiring Phoenix onto the F5 engine — how the bands connect.
- F5.0.1 · The Portal engine blueprint — the stack F6 extends.
- F5.08 · Boundaries & integration seams — the facade the web band calls.