Page titles, descriptions and social-card tags for an app folder.
A page, and any layout.ex above it, can define metadata/1. It gets
the page's assigns and returns a map:
# app/layout.ex: the defaults for every page
def metadata(_assigns) do
%{
title: "Acme",
title_template: "%s · Acme",
description: "Acme makes rockets.",
open_graph: %{site_name: "Acme", type: "website"}
}
end
# app/posts/[slug]/page.ex
def metadata(assigns) do
%{title: assigns.post.title, description: assigns.post.summary}
endXenia merges them from the outermost layout to the page: a key set lower
down wins, and open_graph and twitter merge key by key. The page's
title goes through the nearest title_template ("Hello · Acme"); a
page without a title gets its layouts' title as it is.
The result is assigned as @xenia_metadata, and its title as
@page_title, so the browser tab follows live navigation like any
page_title. It's computed after the page has its data: after mount/3,
or after the page's own handle_params/3 if it has one.
A page that assigns page_title itself, and has no metadata title,
keeps its page_title: a layout's default title only fills in for pages
without one.
Render the tags in root.html.heex, inside <head>:
<.live_title default="Acme">{assigns[:page_title]}</.live_title>
<Xenia.Metadata.tags metadata={assigns[:xenia_metadata]} />The root layout is rendered once, on the first page load, which is what
search engines and link previews read. On live navigation LiveView
updates the <title>, but not the other tags in <head>.
Keys
:title- the page title:title_template- wraps titles set below this layout;%sis the title:description-<meta name="description">:canonical-<link rel="canonical">, a full URL:robots-<meta name="robots">, e.g."noindex":open_graph-og:tags, e.g.%{type: "article", image: "https://..."}.og:titleandog:descriptiondefault to the title and description:twitter-twitter:tags, e.g.%{card: "summary_large_image"}
Any other key raises an ArgumentError, so a typo doesn't go unnoticed.
Summary
Functions
Merges the metadata of layouts (outermost first) and page, called with
assigns. Modules without metadata/1 are skipped. Returns nil when
none of them has any.
Renders the <meta> and <link> tags for resolved metadata. Put it in
root.html.heex, inside <head>, next to <.live_title>, which renders
the title.
Types
Functions
Merges the metadata of layouts (outermost first) and page, called with
assigns. Modules without metadata/1 are skipped. Returns nil when
none of them has any.
Renders the <meta> and <link> tags for resolved metadata. Put it in
root.html.heex, inside <head>, next to <.live_title>, which renders
the title.
Attributes
metadata(:map) - assigns[:xenia_metadata]. Defaults tonil.