Views & Rendering Trusted Content
Website Rebuild with Astro
Chapter 4 · Views & Rendering Trusted Content
This chapter builds the real layout Chapter 3's own database-backed route uses — and, like every sibling course before it, needs a way to render stored HTML content as real markup, not escaped text.
The Layout
getBreadcrumb walks current.parentId one row at a time inside a while loop — one database query per ancestor level, exactly the pattern every sibling rebuild course (and the standalone astro1 course itself) built into its own breadcrumb code on purpose. It's left as written here, to be caught and fixed in Chapter 6.
set:html: Astro's Own Answer
set:html={page.body} sets an element's HTML content directly, bypassing Astro's own default auto-escaping — the exact same job Django's |safe filter, Laravel's {!! !!}, and Rails' <%== %> each do in their own frameworks. Astro's version is a template directive on the element itself, rather than a filter or a special output-tag syntax — its own genuine syntactic shape, doing an identical job to every sibling.
set:html is only safe for content this project's own admin interface writes — never for rendering arbitrary user input directly, since it bypasses the exact escaping that protects against injected markup. The same warning every sibling course's own equivalent mechanism carries.
Compared Across the Series
| Framework | Mechanism |
|---|---|
| Django | {{ page.body|safe }} — a template filter |
| Laravel | {!! $page->body !!} — a Blade output-tag variant |
| Rails | <%== @page.body %> — an ERB output-tag variant |
| Astro | <div set:html={page.body} /> — a template directive on the element |
Hands-On Exercises
Build PageLayout.astro rendering a page's title and body via set:html, and confirm real stored HTML (e.g. a <strong> tag inside body) renders as actual formatted HTML, not escaped text.
📄 View solutionBuild getBreadcrumb() and confirm it produces the correct, correctly-ordered ancestor chain for a real page stored at least three levels deep.
📄 View solutionTemporarily replace set:html={page.body} with plain {page.body} interpolation, and confirm Astro's default behavior actually escapes the stored HTML — the raw tags appear as visible text instead of rendering.
📄 View solutionChapter 4 Quick Reference
set:html={page.body}— Astro's own directive-based equivalent of|safe/{!! !!}/<%== %>- Only for admin-controlled content — never for arbitrary user input
getBreadcrumb— a deliberately planted N+1 pattern, caught in Chapter 6- Plain
{ }interpolation escapes by default —set:htmlis a genuine, deliberate opt-out - Next chapter: Styling — Dark Theme