Nunjucks, just like Twig and other template languages, has a feature called "blocks" which serves as a way to reuse elements.

Basically we have a layout file, and in this file we define a block to be populated from somewhere else.

<!-- layout.njk -->
{% block sidebar %}{% endblock %}

And then from a content page we can create an element that uses the defined block:

<!-- page.md -->
{% extends "layout.njk" %}
{% block sidebar %}
    <aside>
        Some aside content here
    </aside>
{% endblock %}

Which then gets rendered in the layout in the place where the block was defined.

<!-- layout.njk -->
<aside>
    Some aside content here
</aside>

Eleventy does carry this functionality from the template languages it supports, but there's a bit of a trick I had to do to be able to use it in this website.

By default, Eleventy uses the frontmatter data on a page, to indicate which layout should be used to render the page and its contents, and the layout would have a content variable where the whole content of the page gets placed. This does not work if we want to use extends and blocks from a page to a layout.

Eleventy allows us to use extends instead of the layout property, but then we have to make sure the content of the page itself uses a block so it can be passed down to the layout, because the content variable will not be populated, which also means the layout will need to have the block defined for the content because the content variable doesn't work with extends.

So my layout file ended up having both (which by the way, gets ignored if there's nothing to populate) and I can use one or the other where needed.

<!-- layout.njk -->
<main>
    {{ content | safe }}
    {% block content %}{% endblock %}
</main>
{% block sidebar %}{% endblock %}

And on pages that don't need to use the sidebar block, I can use layout: "layout.njk" normally, which ignores the content block, and pages where I want to use a sidebar, I can use extends instead, and wrap the content in the {% block content %}{% endblock %} tags to get it displayed, which ignores the content variable.

Hopefully this helps if you find yourself needing to use both ways.