F5 · system design · 1 of 3
The Portal engine blueprint
Before the first module, here is the thing the chapter builds. The Portal engine is a framework-free domain core: it knows the Portal’s rules and holds its state, but nothing in it imports Phoenix. It sits in the middle of a stack — the branded CHAMP store from F4 underneath it, the Phoenix LiveView UI from F6 on top — and exposes a single boundary, the facade, that the UI calls. Four layers, and each one is the work of a specific F5 module, so the whole chapter points at one destination: an engine with a clean, UI-ready edge.
Select a layer to see what it does and which module builds it. The engine is the two middle layers; F4 already built the bottom, and F6 will build the top.
The four layers
Reads and writes travel the same stack in opposite directions: a write enters at the top as an event from the UI and settles into the store at the bottom; a read climbs back up as a projection. The engine never reaches past its own boundary — it does not render markup and it does not open sockets — which is exactly what lets F6 mount it without the engine knowing F6 exists.
The stack · select a layer
layer: Engine facade
built by: F5.08
The engine is the two middle layers. Everything F5 does is make those two layers correct and give them a single edge; the layers above and below are someone else’s job, by design.
The shape in code
The boundary is small on purpose: one way to change the system and one way to read it. A LiveView (or a test, or a script) only ever touches these two functions; everything else is private to the engine. That single edge is what F5.08 assembles and what the F5.09 lab mounts behind a LiveView sketch.
# the boundary the UI calls — assembled across F5, mounted in F6 defmodule Portal.Engine do # write: a command is checked, emits an event, transitions state (F5.04-F5.06) def dispatch(command), do: # {:ok, event} | {:error, reason} # read: a projection over the current state (F5.05) def query(name, args), do: # {:ok, result} end # nothing above imports this; nothing here imports Phoenix — the seam is the point
a framework-free core
The engine knows the rules and holds the state, with no web framework inside it.
one UI-ready edge
dispatch/1 and query/2 — all a LiveView needs.
Next in the design brief: the domain model — the entities and contexts that live inside the core.
References
The ideas behind a framework-free core with one boundary.
Sources
- Alistair Cockburn — Hexagonal architecture — a core with ports, isolated from the UI.
- Hunt & Thomas — The Pragmatic Programmer — orthogonality and decoupling.
- Phoenix — LiveView — the UI layer F6 mounts on top.
Related in this course
- F5.0.2 · The domain model — what lives in the core.
- F5.0.3 · The command & event flow — how the core moves.
- F4.09 · Branded CHAMP maps & GenServer — the store at the bottom layer.
- F5 · Pragmatic Programming