Where should I put component definitions in Zola 0.23?

I used to put shortcodes under templates/shortcodes, but putting component definitions there doesn’t work. I tried templates/components but still doesn’t work. It’s not mentioned at all in documentation and I can’t find any examples using 0.23!

1 Like

You can put them anywhere, they are discovered automatically. For the docs of Zola for example I’m putting them in zola/docs/templates/components.html at master · getzola/zola · GitHub but they could really any scattered across any files if you want.

1 Like

Yes, they are scattered in 8 template files on my converted site, and in 7 templates files in my local copy of the apollo theme I use.

They are scattered because I quickly auto-migrated my site to tera2 with AI, so they stayed in their previous place when they were macros or shortcodes, but I will surely now refactor them in a more logical way.

PS: AI is superbly efficient to work with opinionated systems such as Zola, it would have struggled with Hugo sites for instance. You can see how I did it at Migration of this site to the new Zola Tera2

Thanks I’ll try that out. Previously I used GPT 5.6 Sol and it did edit the files but keep failing the build (Unknown component `...` ), then it turns to persuade me that there’s some bug in scaning templates on Windows.

Well AI still keep persuading me there’s some bug in Windows. Probably I shall stop trying and wait until some more stable version releases.

Not that I am aware. Tera runs tests on Windows too. Can it create a repro that fails?

  • Did you use GPT 5.6 Sol (I used Luna, btw) via its web interface or via an harness (e.g opencode)?

    It is very different as models have a “temperature”, which is a parameter setting the “randomness”.
    The web interface of models have a high temperature to have more creative response, but with some hallucinations.
    But when used via a harness (via their API), they have a very low temperature, to be rigorous.

    Also, with a harness, work in the plan mode (preventing to modify any file), and focus on it understanding the docs and writing summaries of them, then an action plan that you can discuss.

    Also, it is very important to give it context, telling him for what version (0.22 or 0.23) are these docs, as it is not prominently stated in them(*), so you must provide it this missing context, otherwise it will mix things up.

    Then only switch to build mode and make it execute the plan.

    (*) I think Zola 0.23 should have been renamed Zola2. Otherwise AI tools from now on will get confused unless users provide them with enough context for each question. For instance, without context, now, AI tools do not think some features are valid, such as YAML frontmatter.

I’m using Codex App and gave it link to the CHANGELOG, and it also requested several times to read source code of Zola 0.23 and Tera v2.

Well I think probably just some very strange situation is happening here. Me myself cannot find where’s wrong either.

Ok let me work out a minimal reproduceable example.

Here’s an example in GitHub - Rratic/zola-test · GitHub

when you run zola build (using Zola 0.23.1), it will say:

Building site...
Failed to build the site
Failed to render page content of '\\?\D:\my-blog\test\content\component.md'
Reason: error: Unknown component `hello`
 --> __tera_one_off:1:3
  |
1 | {{<hello name="World"/>}}
  |

To provide more information, I put the repo in D:\my-blog\test, running through cmd, using Windows 10.0.19045.6466

Strange, your zola-test repo works for me on linux,
both with Zola 0.23.1 and Zola 0.23.2


colas@colas:~/git/zola-test$ zola build
Building site...
-> Creating 1 pages (0 orphan) and 0 sections
Done in 17ms.

colas@colas:~/git/zola-test$ zola -V
zola 0.23.0

# updating zola...

colas@colas:~/git/zola-test$ zola -V
zola 0.23.2
colas@colas:~/git/zola-test$ zola build
Building site...
-> Creating 1 pages (0 orphan) and 0 sections
Done in 238ms.

Nah, LLMs can just be pointed at the docs if needed. Not going to inconvenience human users for AI.

Thanks for the repro i’ll have a look even though I don’t have a Windows machine x). It’s probably due to \\?\D: i’ll try to make a repro in CI

I just tried using 0.23.2 and put the repo on desktop and still can’t work.

Some hints from AI:

The \\?\D: form is not something Zola decides — it's forced by Rust std inside Tera. In tera::load_from_glob (tera/src/globbing.rs:32):
let parent_dir =
    std::fs::canonicalize(parent_dir).unwrap_or_else(|_| PathBuf::from(parent_dir));
std::fs::canonicalize on Windows uses GetFinalPathNameByHandleW(FILE_NAME_NORMALIZED), which always returns the verbatim \\?\D:\... form (there's no registry key, env var, or path style that changes it; it's the only unambiguous canonical form, and Rust deliberately returns it). So no config, zola.toml setting, or environment variable can stop Tera from seeing \\?\D:.
The only way to keep paths non-verbatim is a code change in Tera: after canonicalize, run the path through dunce::simplified() (strips the \\?\ prefix back to D:\), or swap canonicalize for std::path::absolute (no verbatim prefix, but doesn't normalize ./.., so dunce is the right fix). That's upstream Tera work, not a user workaround.
Found it — the CLI canonicalizes the root at /tmp/zola-git/src/main.rs:109:
let cli_dir: PathBuf = cli.root.canonicalize()...
So on Windows root_dir is \\?\D:\my-blog\test and that verbatim form flows into the content path (matching your error) and into Tera's template glob. Let me check the upstream issues — this is a brand-new 0.23.x release, there may be a known report.
%WebFetch https://api.github.com/search/issues?q=repo:getzola/zola+%22Unknown+component%22+OR+%22component+%60%22+windows
%WebFetch https://api.github.com/search/issues?q=repo:getzola/zola+windows+%22templates%22+%22canonicalize%22+OR+%22verbatim%22+OR+%22%5C%5C%3F%5C%22
+ Thought: 32.9s
That's the confirmation — and it matches a documented Zola issue (#1692) with the identical //?/D: symptom and a fix-attempt PR (#1626) titled "Don't canonicalize paths because windows \\? prefix seems to break globbing." Let me verify the exact injection points in the current code.
→Read /tmp/zola-git/src/main.rs [limit=40, offset=100]
+ Thought: 24.2s
Confirmed the injection point at /tmp/zola-git/src/main.rs:109:
let cli_dir: PathBuf = cli.root.canonicalize()...
On Windows, std::fs::canonicalize always returns \\?\D:\.... That canonicalized root then flows into Site::new → load_tera → the template glob, and Tera's load_from_glob (tera/src/globbing.rs:32) canonicalizes again. So the verbatim form is forced by two hardcoded canonicalize() calls — it's not a Zola setting.

It should be fixed in the next branch (Next version by Keats · Pull Request #3222 · getzola/zola · GitHub) if you want to try building it yourself

I had exactly this same problem, but it was not the placement of the components, but the syntax required to invoke them.

For short code I used

{% warning() %}You can only edit a transaction if the following conditions are met:

- The transaction occurred within the **current, open accounting period**.
- **Strict Audit Mode** is turned **off** in the organization's settings.

If these conditions are not met, the "Edit" button will be disabled.
{% end %}

but now for the component the following format is required

{{<warning w="You can only edit a transaction if the following conditions are met:

The transaction occurred within the current, open accounting period.

Strict Audit Mode is turned off in the organization's settings.

If these conditions are not met, the "Edit" button will be disabled."/>}}

This took me ages to work out. The changelogs and docs were no help.

This is not the required format, if you want to take a body:

You can do

  {% <warning> %}
You can only edit a transaction if the following conditions are met:

- The transaction occurred within the **current, open accounting period**.
- **Strict Audit Mode** is turned **off** in the organization's settings.

If these conditions are not met, the "Edit" button will be disabled.
  {% </warning> %}

and print {{ body }} in your component