Idea: better page metadata for published pages

(and thanks for the amazing static site generator <3)

Various platforms - like chat applications and social media - provide automatic link previews, when a link is shared. These previews / “unfurls” are based on metadata, see more information e.g. here in a Medium article by Slack developers. Both “native” html metadata tags and OpenGraph metadata are often parsed for by various services.

It is pretty easy - and common, i would guess - to add the title and description metadata in the front-matter of the markdown files. Those fields are well supported by Zola, and available for use as variables to access in the templates.

However, actually using those pieces of article metadata for the generated html page metadata requires quite a bit of boilerplate-writing in your template fields. See below for an example that populates both the generic meta tags and the OpenGraph ones:

  <meta property="og:type" content="website" />
  <meta property="og:site_name" content="" />
  {%if section.title%}
  <title>{{ section.title }}</title>
  <meta name="og:title" content="{{ section.title }}" />
  {%if page.title%}
  <title>{{ page.title }}</title>
  <meta name="og:title" content="{{ page.title }}" />
  {%if section.description%}
  <meta name="description" content="{{ section.description }}" />
  <meta name="og:description" content="{{ section.description }}" />
  {%if page.description%}
  <meta name="description" content="{{ page.description }}" />
  <meta name="og:description" content="{{ page.description }}" />

Could it be possible to have some sort of shorthand for filling in all of these in Zola templating - or e.g. a configuration setting for automatically adding these in the generated page metadata, for each metadata field that has been provided in the page’s front-matter? Currently, if a user doesn’t manually add any of these in their template, none of the metadata gets into the generated html.

(Bonus round: how would you implement support for declaring the page’s intended main image as a url in the markdown frontmatter, for use in an og:image tag - while conforming to the support for asset colocation in the directory structure?)

1 Like


You can use the first code snippet to reduce the boilerplate: Templates need a variable that could be “section” or “page” · Issue #687 · getzola/zola · GitHub
IMO this is the responsibility of a theme/template and not Zola. It could have a built-in macro to fill those though and it would be just a matter of calling {% opengraph(config=config, data=page_or_section) %}.

You can build it manually easily (I think?) {{ page.permalink ~ page.extra.og_image_name }}. That requires you to hardcode the name of the image in the front-matter though

Yeah, exactly! That sounds like a great solution to what i was trying to wave my hands at. How about something like {% metadata %}, that would by default fill in some basic metadata, e.g.

  • <title> based on page title
  • <meta name="description" />
  • date published? (on a cursory search, wait what, there’s no actual standard on a metadata field for this? huh.)
  • others?

Perhaps with additional flags configurable in the main config.toml, e.g. opengraph=true, or similar?

In my humblest personal opinion, it would be great if site metadata would be easy to generate and would include the OpenGraph data by default. Smart link previews are so ubiquitous - from various social media to chat applications and others. It’d be great if Zola empowered users to create websites that have good-looking previews when linked around - without having to dive in to the nitty gritty, or even having to know such special tags exist in the first place. If a poweruser wants to manually select which metadata fields to populate and how in the template, obviously it can be done as demonstrated in the snippet I pasted above.

One thing I’ve particularly loved about Zola is that the engine’s requirements from templates are very light - it is not only possible but easy to start creating your own template from scratch, and you can create the template pretty much as if you were creating a static site. Having some smart macros & smart defaults like above could further enable and encourage people to create great sites on their own. Having used a bunch of other site generators, some suffer from fairly heavy template baseline requirements and pretty much encourage just picking an existing template.

Correct me if i’m wrong, but that would mean you have to use asset colocation in the posts where you want to use a preview image? I.e. the template would not work if you used an image with the basic static/ location, introducing extra constraints in how you write your posts? Additionally, I’d humbly request considering the possibility of adding image as an optional field in the default page/section metadata. While typing the [extra] image="foo" in the posts and using page.extra.og_image as you suggested is not exactly a major pain, I’d argue the preview images are pretty widely adopted in practice and could be considered a rather standard piece of “making your site look good”.

Thank you! I’ll definitely adopt this in the short term - but as mentioned in the issue comments, it’s not exactly the most elegant solution and something even better could be invented for Zola :slight_smile:

EDIT: tried to use the {% set section_or_page = section | default(value = page) -%} method for my head.html template, but that ended up breaking things - because 404.html as a template is neither a section nor a page:

Failed to build the site
Error: Failed to render '404.html'
Reason: Variable `page` not found in context while rendering 'head.html'

I’d be happy to help with implementation if any of these raw ideas get polished into proper, accepted feature plans.

Probably not, many sites have a format like {{ page.title }} | Author name.

That’s not really easy, that requires parsing HTML to know where to insert it and will require some (breaking) changes to be able to refer to single item. What should happen with taxonomies pages in that case? Those don’t have title/description for example.

That would be a bit manual yes as you would need to differentiate between colocated image and the ones in assets. so they would need to be different keys in the front-matter.

I don’t think I want to add more default fields to the metadata. Maybe if the metadata gets built-in it would make sense (and even then, how can you know where is the image located: colocated or static?) but not until then.

404 is a bit special yes, it probably needs to redefine its own blocks to avoid any references to variables.

Thanks! There are a few link related features/PRs I want to work on/merge first but we can draft how the built-in metadata would look in the meantime.
I guess the first step is to look for any prior art and see how they work.

Oh I didn’t mean completely automatic, just that there would be something like the mentioned {% metadata %} or similar to easily add into your template, with useful defaults.