adamu
Benefit of app layout being defined inline in Layouts, rather than in heex file?
I understand that heex code can either be defined inline with the ~H sigil, or placed into a .heex file and embedded with embed_templates.
I’m curious why Phoenix puts the root layout in a heex file, but the defines the app layout inline.
Is there a specific benefit to defining the app layout inline? Or is it simply because the default app layout is pretty small? Or maybe to provide an example of each method?
Marked As Solved
josevalim
`root` could work as a regular function. I just double checked by converting it in tidewave.ai and it worked just fine! And I believe this is true since Phoenix v1.6 (or v1.7?) when we unified everything to be function components.
So let’s answer this by parts.
First, why do we need layouts?
Mainly because LiveView pages need to denote some content that cannot be live updated. This is typically in the `head` tag. We know there are frameworks who have attempted to update and merge `head` tags but it is very easy to run into hard-to-debug JavaScript bugs and corner-cases in browser. So the root layout helps us denote the static part.
Who renders the layout? After all, we could have made it so all of your regular templates simply called `<Layout.root>`.
Per the above, we know that the contents of `<Layout.root>` cannot be updated and therefore they should not be re-rendered. If we made your template call it, the one rendered on every LiveVIew update, then we would always re-render the root layout too, only to later figure out a way to discard its updates, which would be wasteful.
Beyond the above, it is important to note that frameworks generally want to own how the layout is rendered because it can lead to UX improvements such as sending the layout upfront, up to the `body` tag, before your LiveView and Controllers get invoked. This would allow browsers to parse `head` tag while you are still runing queries and what not, leading to faster page loads. Of course, there are complications, such as what to do if you send the `head` and then you get an exception, but the point is that leaving the framework to control how the layout is rendered can be feature!
IMO, this is not about inheritance at all, especially because frameworks that do offer template inheritance allow you to extend the layout with additional information beyond the inner block, which we don’t. We intentionally keep the layout decoupled from the application contents because we want to have flexibility over it.
So why do we have root.html.heex?
The reason we moved the app layout to a component is because you can declare your own attributes and slots and we wanted to make it clear you should invoke it. You can’t do any of that with root layouts, so we kept them distinct to avoid confusion. Leading someone to think they should call `Layout.root` would most likely lead to disaster. ![]()
TL;DR: the `app` and `root` layouts are defined differently as to signal users you are supposed to invoke the former but not the latter. That’s it.
Also Liked
BartOtten
For those who want to: phoenix_live_head | Hex
The change to a layout component was a major improvement for all the reasons José mentions. It also removed one extra segment of the docs now it’s clear in every template where the layout comes from.
bartblast
My suspicion is there’s significant historical inertia at play. Early SPAs were purely client-side - your server sent a minimal HTML shell with a static <head>, and JavaScript mounted in the body. This wasn’t really a choice. Without SSR, you needed that pre-rendered for bootstrap. The ecosystem then built around this pattern (React Helmet, etc.), and by the time SSR became standard, there wasn’t enough reason to revisit the architecture when the workarounds were “good enough”.
bartblast
There are legitimate user-facing dynamic head updates: favicons (notification badges), page-specific scripts, A/B testing scripts, page-specific widgets (chat, analytics), theme metadata (theme-color), and viewport metadata.
You could create separate layouts for pages that need different head content, but if the only difference between pages is in the <head>, it’s much cleaner to just pass those as props to a single layout component. No need to duplicate the entire layout structure.
But here’s the broader point: even if the metadata is static and only matters for initial server-side rendering, treating the layout with its head section as a single component is still clearer. No special cases, no mental overhead of “this part uses the framework’s component model, but this other part uses a separate template system” or some impeative glue. It’s just components all the way down, which significantly simplifies the mental model.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









