Minimal single layout site query

I currently have a minimal Astro site with a single layout and a single CSS file for all pages, except for some additional CSS used on the post listing page. I’m now looking to migrate the site to Zola.

I’d like to set up a base template for all pages, and ideally use the same template for both posts and the 404 page. However, I want all other top-level pages to remain as markdown files.

Here’s the structure I have in mind:

├───content
│   ├───index.md
│   ├───projects.md
│   ├───....md
│   └───writings/
├───static/
│   ├───.well-known/
│   └───assets/
│       ├───audio/
│       ├───css/
│       ├───font/
│       ├───img/
│       └───video/
└───templates/
    ├───base.html
    ├───404.html
    └───writings.html

Is it possible to keep the top-level pages in markdown? If so, how can I set this up in Zola?

I think I understand what you’re saying, tell me if I’m wrong.

To you “top-level pages” are the zola concept of “sections”. For example, content/index.md would be a section, which would compile to just / as a URL path. A section is any markdown file, inside the content directory, named index.md.

So if you had writings/index.md then that would also be a section and the URL path when compiled would be /writings/.

All other markdown files are “pages” in zola lingo. So that would be projects.md, ....md, and whatever else is inside writings.

You can certainly have all the pages share the same template and it looks from your directory structure that you understand how to do that. You would just need to put in the front matter of each of your pages the template that you want them to use. If not template is specified then Zola will automatically use page.html for pages.

Is it possible to keep the top-level pages in markdown?

I think you’re asking if it’s possible to have the sections have their markdown content shown literally, instead of being rendered as html? Tell me if I have that wrong.

Anyways, yes you can certainly do that.

The variable that stores the contents of the markdown, section.content, keeps everything in escaped html, so that won’t work in this case. Instead you would need to load the content more like this:

{% set content = load_data(path=section.path) %}

And then you can use it literally.

One other thing is that you will probably want to use that literal content within <pre> tags, if you don’t already know, because in html all the whitespace will be stripped out otherwise.

Last piece of advice, you’ll probably want to have your structure like this

  • a base.html template with all of your <head> information
  • a section.html template that extends base.html and inserts the content how I showed just above
  • a page.html template that extends base.html
  • a 404.html template that extends base.html

You probably don’t want the 404.html to be the same as the page templates because there is no page variable, but you can certainly have it extend base.html and then do any further customization needed from there.

Hopefully that answer helps? Good luck with Zola!

let me make it more clear. I have my whole site as literally a single template and a single css file. Everything has same header, footer, <head> contents except for title of the final pages.

I want to make it such that, my /, /projects, /writings/some-random-page all are in markdown. I don’t want to make certain pages like index.html for /. I rather want to make a base.html for everything (if not possible then ig i will do the standard thing) and then write all pages as markdown in my content folder ig.

I see. Ok so to do that you just need to do something like this for each variable that you use.

{% set title = page.title | default(value=section.title) %}
{% set content = page.content | default(value=section.content) %}
{# etc... #}

The 404 page is one corner case. Zola looks for a specific file called 404.html. So if you really want to have just one template for everything then I guess you could name that template 404.html… although I’ve never tried that.

Another thing that I’ve never tried would be symlinking base.html to 404.html… that would probably work too and any updates made to base.html would show in 404.html.

One last thing is that for 404.html most of those variables above I mentioned won’t be available. So if you must take the route of exactly one template then you can nest those default statement like this:

{% set content = page.content | default(value=section.content | default(value="404 - Page Not Found!")) %}
{# etc... #}

Does that answer your question?

1 Like