Headless & hybrid patterns
Purpose: Serve non-AEM frontends (apps, SPAs, kiosks) from AEM content with sensible API and caching shapes.
Who this page is for
| Audience | Why it matters to you |
|---|---|
| All engineers | Multi-channel delivery decisions |
The spectrum
Full head Hybrid Headless
(HTL pages) (HTL pages + JSON for apps) (AEM = content API only)
βββββββββββββ most sites land here βββββββββββββΆ
| Pattern | Mechanism | PHI example |
|---|---|---|
| Component JSON | Sling Model Exporter .model.json | Plan card data for the mobile app |
| Page model | <page>.model.json (SPA pattern) | Full plan page in the app webview |
| CF via Assets HTTP API | /api/assets/β¦ JSON of fragments | Plan data records for the comparison service |
| CF via GraphQL (where the 6.5 headless add-on is in place) | Persisted queries per model | Same, with client-shaped queries |
| Custom aggregate servlet | resourceType servlet | "Everything for the plans screen" endpoint |
API discipline (because now you have an API)
- Exported JSON is a contract: additive evolution, documented samples, consumer-driven review before model changes (JSON delivery).
- Version by path/selector when breaking changes are unavoidable (
.model.v2.jsonselector) β never silently reshape. - Cache like pages: extensioned GET URLs, dispatcher rules including JSON in /invalidate, CDN TTLs per freshness need.
- Auth for non-public APIs at a gateway in front, not bespoke token code inside AEM.
Hybrid rendering rule of thumb
Render with HTL anything that must be SEO-visible, fast-first-paint, and authored as pages. Consume JSON from the same models for the app. One model, two channels keeps web and app consistent by construction β the main reason to prefer exporter-based JSON over parallel custom servlets.