# Raw mode

**URL:** <https://zola.discourse.group/t/raw-mode/2818>\
**Category:** Feature requests\
**Created:** [August 4, 2025, 4:53pm UTC](https://zola.discourse.group/t/raw-mode/2818 "2025-08-04T16:53:12Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonhurst](https://avatars.discourse-cdn.com/v4/letter/j/b782af/32.png) [@jonhurst](https://zola.discourse.group/u/jonhurst)\
**Post date:** [August 4, 2025, 4:53pm UTC](https://zola.discourse.group/t/raw-mode/2818/1 "2025-08-04T16:53:12Z")

</div>

I [recently proposed](https://zola.discourse.group/t/proposal-for-sharding-of-markdown-content/2664) that it should be possible to break up the markdown of an `.md` file in order to address sections of it seperately in the Tera templates. This is working well in my fork, and allowed me to simplify and clean up some of my pages and templates. However, it somehow still felt like I was working against Zola, so I figured I’d write a toy SSG to try to identify where that was coming from.

I think I have now identified what’s going on. Essentially, Zola is a very good blog generator, but if your website is not sufficiently like a blog, you’re going to have to do some ugly things.

The main difference between my toy SSG and Zola is that the content hierarchy represents the layout of the website rather than the structure of the data. The placeholders for HTML pages are `.page` files, which are pure TOML files. There is no concept of a section – if you want to have a page representing a section, just write a page representing a section. `index.page` does have one magical property which is that the weight defaults to `None`, meaning that it won’t, by default, appear in a sibling list, so this is probably a good place for it.

Each `.page` file has an optional `[content]` section listing files to load and an optional `[data]` section for ad hoc data. The only top level items are `template` to link the template to present the data to, and `weight` to control the ordering of siblings. There is no markdown involved. In fact markdown is explicitly out of scope in general. If you want to write markdown, rst, asciidoc or whatever, go right ahead, then convert it to HTML and reference the HTML file in the `[content]` section to present it to the templates.

Everything in the content hierarchy gets copied across verbatim to the public hierarchy other than the `.page` files, which get replaced with the created `.html` files, and any directories containing a file named `.ignore`. If you want SASS, SCSS or whatever, just write your code, stick an `.ignore` file in the directory containing that code and pre-process it to a CSS directory or whatever to be copied across.

Files listed under `[content]` may be HTML or TOML, and the HTML may be sharded. The templates have access to the data from all pages, the weighted relationship between siblings and the sub-directories of the directory they are in. This gives a huge amount of flexibility in structuring the data and text content of your website.

Since the content hierarchy is exactly the same as the layout of the site, all internal links can be handled as relative links. A variable called `root` is provided to the templates to facilitate this. `{{root}}/css/styles.css`, for example, refers to `/content/css/styles.css` from any `.page` file. This means that the whole public hierarchy can be dropped anywhere, and it just works. You can even test in the browser with `file://` urls. This has allowed me to go back to my preferred workflow of uploading to a staging domain and then synchronising that with a production domain once the website has been thoroughly tested.

All of which is to say that in around 300 lines of Python, my toy SSG covers a great many of the feature requests in this forum. I have now thoroughly scratched my own particular itch, and will be using it going forward. I think, however, that there would be value in allowing Zola to operate in the same way for those that are not building blog-like websites. Obviously this way of operating is completely opposed to the normal way Zola operates, so it would have to be a separate mode that you could select in the config file.

I’m honestly not at all sure this is a good idea, but I thought I would put it out there for discussion.

---

<div class="post-metadata">

**Author:** ![bemyak](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/bemyak/32/1106_2.png) [@bemyak](https://zola.discourse.group/u/bemyak)\
**Post date:** [August 5, 2025, 6:11am UTC](https://zola.discourse.group/t/raw-mode/2818/2 "2025-08-05T06:11:56Z")

</div>

That’s an interesting idea! Thank you for posting the summary here!

For me personally though, the main point of SSGs is separation between _data_ and _representation_. I don’t want to think about `<div>`s when I’m writing a post and I don’t want to care about the content when I’m writing a theme. Markdown plays a crucial role here, since it’s pleasant to write format (as opposed to HTML/XML) without too much clutter (but with many known downsides ofc, which are too minor for a successor to emerge yet).

I think with [section deprecation](https://zola.discourse.group/t/proposal-deprecate-sections/1968) Zola will take a step to unifying the content layout and the website layout.

Correct me if I’m wrong, but the proposed approach feels more like a linker rather than a renderer?

---

<div class="post-metadata">

**Author:** ![jonhurst](https://avatars.discourse-cdn.com/v4/letter/j/b782af/32.png) [@jonhurst](https://zola.discourse.group/u/jonhurst)\
**Post date:** [August 5, 2025, 8:10am UTC](https://zola.discourse.group/t/raw-mode/2818/3 "2025-08-05T08:10:22Z")

</div>

> [@bemyak](#):
>
> For me personally though, the main point of SSGs is separation between _data_ and _representation_. I don’t want to think about `<div>`s when I’m writing a post and I don’t want to care about the content when I’m writing a theme. Markdown plays a crucial role here, since it’s pleasant to write format (as opposed to HTML/XML) without too much clutter (but with many known downsides ofc, which are too minor for a successor to emerge yet).

For the [website that drove the development](https://emilyhurst.co.uk) I found that data and representation were actually _better_ separated. The representation all ends up in the templates, and the HTML content generally has nothing more complicated than `<p>` and `<em>` tags in it. The images are just a TOML array of relative urls in the `[data]` section of the `.page` file. It probably also does not help that personally I am more comfortable writing HTML than markdown – my markdown always ended up spattered with HTML sections wherever the going got tough.

Interestingly, themes ended up explicitly out of scope. There was just no natural way to do them. If you wanted, though, you could download a “starter site” which gives the same effect with much less magic. Themes actually cut to the heart of the matter; its an implicit versus explicit thing. Zola excels at implicit: download a theme, put some markdown in the right place with the right magic headers and hey presto! you have a great looking blog. There is absolutely nothing wrong with this, as long as you are willing to play within the rules. It only breaks down when idiots like me want to use it to make a website where every aspect is controlled.

> [@bemyak](#):
>
> Correct me if I’m wrong, but the proposed approach feels more like a linker rather than a renderer?

There’s something in that, for sure. Perhaps my toy SSG is in actuality a fundamentally different interpretation of what an SSG _actually is_ than that underlying Zola. It certainly makes most sense as a completely separate tool, unconnected in any way with Zola; my suggestion for including it as an alternate mode of Zola is purely driven by the fact that this forum suggests people are trying to force Zola to do the things that my toy SSG does very naturally and finding that experience frustrating.

---

<div class="post-metadata">

**Author:** ![jonhurst](https://avatars.discourse-cdn.com/v4/letter/j/b782af/32.png) [@jonhurst](https://zola.discourse.group/u/jonhurst)\
**Post date:** [August 5, 2025, 9:00am UTC](https://zola.discourse.group/t/raw-mode/2818/4 "2025-08-05T09:00:33Z")

</div>

I should probably at least give some code samples. These are the files involved in creating `index.html`:

`content/index.page`:

```toml
template = "home.html"
content.main = "data/index.html"

[data]
title = "Emily Hurst Millinery"

[[data.featured]]
bgimg = "images/featured-ss25.webp"
href = "collections/ss25/index.html"
text = "Explore the SS25 Collection"

[[data.featured]]
bgimg = "images/featured-about.webp"
href = "about.html"
text = "About Emily Hurst"

```

`content/data/index.html`:

```html
<!-- shard:hero -->
  <h1>CRAFTED BY TRADITION</h1>
  <h2>DESIGNED FOR TODAY</h2>
<!-- shard:blurb -->
  <h2>Discover the beauty of craftsmanship that stands the test of time</h2>

  <p>Luxury headwear created by blending timeless craftsmanship with modern
    design. Using traditional straw techniques alongside carefully sourced
    materials, Emily honours heritage and endeavors to renew endangered crafts.
    All pieces are carefully crafted by hand to add a touch of elegance, while
    making a positive impact on the environment.</p>

```

`templates/home.html`:

```html
{% extends "base.html" %}
{% block header %}
<link rel="preload" as="image" href="images/hero.webp" fetchpriority="high">
{% endblock %}
{% block content %}
<div class="j-page__content" style="background-image: url(images/hero.webp);">
<div class="j-hero-title">
  {{ page.content.main.hero[0].html }}
</div>
<div class="j-homepage-blurb">
  {{ page.content.main.blurb[0].html }}
</div>

{% if page.data.featured %}
<div class="j-featured">
  <h1>FEATURED</h1>
  <hr>
  <div class="j-featured__cards">
    {% for card in page.data.featured %}
    <div class="j-featured__card"
         style="background-image: url({{card.bgimg}});">
      <a href="{{card.href}}">{{card.text}}</a>
    </div>
    {% endfor %}
  </div>
</div>
{% endif %}
</div>
{% endblock %}

```

---

<div class="post-metadata">

**Author:** ![jonhurst](https://avatars.discourse-cdn.com/v4/letter/j/b782af/32.png) [@jonhurst](https://zola.discourse.group/u/jonhurst)\
**Post date:** [August 5, 2025, 5:29pm UTC](https://zola.discourse.group/t/raw-mode/2818/5 "2025-08-05T17:29:13Z")

</div>

Pondering further on this…

I think that ultimately the best way to integrate this into Zola would be a new command, `zola raw`. This would mean the only change to the current codebase would be an extra few lines in the command line parsing, and that there is an expectation that none of the other Zola commands could be used when using “raw” processing.

My thinking is that I will port the prototype from Python/Jinja to Rust/Tera at some point in the next few months, ensuring that the TOML crate is the same as used by Zola. Since the only dependencies will be this TOML crate and Tera, integrating this code would be a very small addition to Zola’s footprint. I will build it as a library crate with a standalone binary, and I will leave it up to @keats as to whether he wants to integrate it. If he does, great, if not, the standalone binary will be available to anyone that wants it.

---

<div class="post-metadata">

**Author:** ![jonhurst](https://avatars.discourse-cdn.com/v4/letter/j/b782af/32.png) [@jonhurst](https://zola.discourse.group/u/jonhurst)\
**Post date:** [August 7, 2025, 8:56am UTC](https://zola.discourse.group/t/raw-mode/2818/6 "2025-08-07T08:56:16Z")

</div>

Please would an admin change the title of this thread to “Raw mode”, as I think that more accurately describes what’s being discussed. Many thanks!

---

<div class="post-metadata">

**Author:** ![jonhurst](https://avatars.discourse-cdn.com/v4/letter/j/b782af/32.png) [@jonhurst](https://zola.discourse.group/u/jonhurst)\
**Post date:** [August 19, 2025, 11:37am UTC](https://zola.discourse.group/t/raw-mode/2818/7 "2025-08-19T11:37:24Z")

</div>

The prototype site generator that I built to explore why Zola wasn’t working for me has now evolved into a nice little application in its own right. Documentation and download from [https://hursts.org.uk/ssg](https://hursts.org.uk/ssg), source code on [github](https://github.com/JonHurst/ssg), if you’re interested.

Unfortunately, the directions it evolved in have taken it too far away from Zola to realistically fold it in as an alternative mode; the coding would be straightforward, but the documentation would be all but impossible.

A couple of features could easily and very usefully be added to Zola if the maintainers want to take a look. The [[data] and [content] sections](https://hursts.org.uk/ssg/page_files.html) would make a really nice addition to Zola’s frontmatter concept and the [sharding](https://hursts.org.uk/ssg/content.html) has also turned out very nicely, particularly when combined with loading from the [content] section. I think it works much better than [my original markdown sharding idea](https://zola.discourse.group/t/proposal-for-sharding-of-markdown-content/2664).
