HATEOAS & REST
The server owns the state. Hypermedia carries the controls. The client renders what it receives.
SPA
Thin controller squeezes to JSON. Complexity shifts to the client.
Where it shines
- ▶ The UI is the application — editors, canvases, design tools
- ▶ Complex local state with rich drag-and-drop interactions
- ▶ Real-time collaboration with shared cursors and CRDTs
- ▶ Offline-first with conflict resolution and background sync
Where it sucks
- ▶ CRUD apps — two state stores that drift apart, connected by load-bearing JSON
- ▶ Every layer generates more layers — DB schema, Go structs, OpenAPI, TS types, Zod schemas
- ▶ Bundle size, hydration cost, time-to-interactive — the user pays for your architecture
- ▶ The DTO/mapping layer exists only to translate between what the DB knows and what JSON needs
- ▶ Two complexity lairs instead of one — and the JSON between them is load-bearing
Hypermedia
Client is thin. Server narrows from fat handler to thin repository. HTML over the wire.
Where it shines
- ▶ Pages represent resources — the server is the application
- ▶ Content and data-centric workflows with CRUD patterns
- ▶ No serialization layer — no DTOs, no mapping, no OpenAPI
- ▶ Each server layer does less than the one above it
- ▶ Client is intentionally thin — most behavior stays on the server
Where it sucks
- ▶ Rich interactive UIs — spreadsheets, design tools, canvas rendering
- ▶ Offline-first with conflict resolution — the server can't drive what it can't reach
- ▶ Real-time collaborative editing — CRDTs and OT live on the client
- ▶ Every round-trip is latency — some interactions need instant local feedback
Drag the handle or tap either side to compare architectures.
The Reach-Up Model
REST says resources are navigated through hypermedia. HATEOAS says the server tells you what you can do next. Each layer below honors that contract — only reach up when it can't.
Behavior
How resources are discovered and transitioned
Presentation
How representations are rendered
Where Your Code Should Live
Most of your application is HTML templates with HTMX attributes. Client-side code is a thin sliver, intentionally. This chart is rendered with Charts.css, a CSS-only charting framework. No JavaScript.
| HTML | |
|---|---|
| CSS | |
| HTTP | |
| HTMX | |
| HS | |
| Alpine | |
| JS |
The Domain Map
Map two dimensions of the hierarchy — where it runs and what it manages — and six domains emerge. Each tool has a place. Nothing crosses boundaries it shouldn't.
Go + SQL
Source of truth. Resource state. The server owns the data.
HTTP + HTMX
Hypermedia controls. Resource transitions. The server drives the UI.
templ + DaisyUI
Typed components. Semantic markup. Theme-aware rendering.
Alpine.js
View state. Ephemeral. A modal's open flag, not resource data.
_hyperscript
DOM interactions. Transitions. Toggles. No server round-trip.
Tailwind + CSS
Layout. Spacing. Visual adjustments. The cascade at work.
Server row: thick, authoritative. Client row: thin, ephemeral. Nothing in the bottom row pretends to be the top row.
See It In Action
Every pattern described above is implemented in the demo. Browse the pages to see how each layer works.