{ "title": "Docs", "date": "2026-07-22T08:54:00-04:00", "toc": true } [TOC] ## Introduction This guide assumes you have either read [The Guide](../guide), or have built a [Hugo](https://gohugo.io) site before. It also assumes you have a basic knowledge of HTML and CSS. ## Features Thor has many features and content processors available. In an effort to provide the best out of the box experience, most of them are enabled by default. Those that aren't are chosen because either: 1. Significant Performance loses. 2. Unexpected behaviour (content mangling) If you feel that an extension is in the wrong category, let is know! [^issues] [^issues]: TODO: Add a link to issues from here. ### Opt-In Features #### Footnotes By default, Thor uses Tufte style margin notes instead of footnotes. However, if you prefer Hugo style footnotes, you can enable them in the [config](#configuration) file. TODO: Explain what tufte style is. #### Syntax Highlighting The highlight extension enables server-side syntax highlighting, powered by TreeSitter. This feature requires downloading a grammar file for each language you want to highlight, and will raise your build times from several milliseconds to over 250 #### Minify If enabled, `minify` will perform simple whitespace removal on all your output `.html` files, and any `.css` files in your `assets` directories. Minifying JavaScript is not supported (yet). Inline CSS will be minified. #### Sections The `sections` extension wraps each of your content sections in a `
` block. Sections are opened just before each heading, and closed before the next heading, or the end the document, whichever comes first. ```markdown ## First Section content ## Second Section content ``` Becomes: ```html

First Section

content

Second Section

content

``` ### Opt-Out Features - emoji - sidenotes/marginnotes - syntax highlighting - heading ids - Table Of Contents Generation - [GitHub style alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) - deflist syntax[^deflist] [^deflist]: This may become opt-in in the future. ## Directories Like Hugo, a Thor project is a collection of specially named directories, plus an optional config file. All directories are optional, but it is recommended to at least have a `content` directory. content : `content` holds your pages and page bundles. If not found, thor will look for content files in the root of your current working directory. See [Content](#content) for more details. assets : `assets` contains any static files for your site (favicon.ico, etc.), as well as files you want to send through the asset pipeline (CSS or JS files). layouts : `layouts` holds your templates and partials. See [Templates](#templates). public : `public` will contain your completed site. All of these names can be remapped in `thor.json`.[^remap] [^remap]: While directories can be remapped at the site level, [modules](#modules) must (currently) adhere to the defaults. ### Assets Currently, there is only one asset processor, and that is [the minifier](#minify), though more are planned (i.e. Image processing). TODO: Expand ## Content ### Pages & Page Bundles Page content can either be defined in a single file (`contact.md`), or in a directory (`contact/index.md` + `contact/our-team.jpg`). Single file pages are preferred to page bundles.[^1] [^1]: That's not you say you shouldn't use bundles, but if you have no additional resources on your page, there's no benefit to using a bundle. Thor currently supports 2 formats for page files: MarkDown (`.md`), and HTML (`.html`). TODO: Content ### Frontmatter TODO: Frontmatter ## Menus TODO: Describe TODO: Don't forget to highlight differences from Hugo. ## Templates Sites are built using one or more template files written with an extended version of [mustache](https://mustache.github.io). The [mustache manual](https://mustache.github.io/mustache.5.html) has great explainations and a lot of examples, but this section should tell you everything you need to know. TODOS: Gotta describe base templates somewhere. (the same way we describe the partials) ### Tags The beauty of Mustache is that there is very little syntax; there are just 10 symbols you need learn: `{{`, `{{&`, `{{^`, `{{>`, `{{<`, `{{#`, `/}}`, `{{$`, `{{!`, and `|`. #### Variables In order to display a scalar (non-list) value in your template, simply wrap it in double curly braces. e.g. `{{ page.title }}`. This content will be HTML escaped (for safety), so if the value you're rendering contains HTML, you'll need to use the raw syntax instead `{{& page.title}}`[^raw] which will output the value without escaping your HTML. Do so at your own risk.[^risk] [^risk]: Or don't, if you don't know why this is dangerous. [^raw]: Mustache also supports raw output through triple brace syntax (`{{{ raw }}}`), but `{{& raw }}` is preferred, as it's easy to accidentily insert too many braces. Leading and trailing whitespace(s) are ignored by the parser, so the folllowing are all equivilent: `{{& title }}`, `{{&title}}`, `{{& title}}`, `{{&title }}`. In most[^most] cases, invalid keys will be silently ignored (nothing between the braces will appear), in keeping with the official mustache spec. [^most]: TODO: in what cases won't it? spelllcheck + strict mode? Also, people don't care about the spec, they care about how the app works. Also maybe mention strict mode here. #### Sections > Sections render blocks of text zero or more times, depending on the value of the key in the current context. Sections allow you to render text conditionally, and also allow you to render lists[^iffor]. They are opened with `{{#key}}` and closed with `{{/key}}`. [^iffor]: These would be your `if` and `for` blocks in a logic-ful language. ```mustache {{og.title}} Shown if OpenGraph title is set! {{/og.title}} ``` #### Inverted Sections All of the syntax we've described so far renders text when its value is *not* empty. Inverted sections render text when the value given to them *is* empty.[^unless] This allows you to display special conent when no values exist, for example. > [!NOTE] > Empty values include `""` (an empty string), `[]` (an empty list), `false` Inverted sections are opened with `{{^key}}` and closed with `{{/key}}`. ```mustache {{^pages}} We don't have anything to show you right now, come back later! {{/pages}} ``` [^unless]: This would be your `if not` or `unless` keyword in a logic-ful template. #### Partials Single file templates have limited functionality. Fortunately, mustache lets you break your documents up into multiple files through the use of partials. To include a partial, you use the `{{>name}}` syntax, where `name` is the path to the partial, relative to the `{{layouts_dir}}/partials` of the module. For example, with the default theme, the `footer` template exists in `{{theme_dir}}/layouts/partials/footer.html`, so you'd include it by adding `{{>footer}}` to you template. See [Partials](#partials-2) for more information. ##### Dynamic Partials #### Blocks TODO: #### Parents TODO: Parents can be used by theme developers to create complex templates with multiple content slots. #### Summary `{{page.title}}` for normal values `{{&page.title}}` for values that contain HTML. `` for list values. `{{#params.is_starred}}{{/params.is_starred}}` for conditional content. `{{^pages}}No pages yet!{{/pages}}` to draw content when the value is empty. ### Block Names When building your own templates, you are of course free to pick whatever names you choose for your partials and content slots. However, sticking to conventions helps create consistency in the ecosystem, and reduces friction when relying on built-in templates. `{{$main}}...{{/main}}` : the `main` section should be used in templates to denote the part of the page that is unique to that page. For the most part, your templates should look like this ```mustache {{

Actual page content goes here

{{&page.content}} {{/main}} {{/base}} ``` ### Context When building your page(s), the following keys are accessible to your template files: `now` : The Current `DateTime`. see [DateTime](#datetimes) `date_format` : The default format to use for dates. Configured in `thor.json:date.format`. `timezone` : The timezone to convert dates to when using `{{ date | format }}`. Configured in `thor.json:date.timezone`. `site` : The site parameters that are usable in templates, see [site](#site). `pages` : Returns all regular pages, sorted by `?`. Regular pages exclude index pages like home and section roots. `posts` : TODO: Section groupings `og` : Contains the [Open Graph](https://ogp.me/) metadata for the current page. `menus` : The site's constructed menus. See [menus](#menus). #### Page `page.content` : The HTML rendered page content `page.url` : The full url to the page. .e.g. `https://example.com/about` `page.rel_url` : The url to the page, minus the `site.base_url`, e.g. `/about`. TODO: write #### Site TODO: Write #### Params `site.params` and `page.params` are an escape hatch to let users inject arbetrary data into their website. The following are some conventional examples theme developers may want to use to ensure a consistent experience across themes. `author` : The author of the current page or site. See [schema.org](https://schema.org/author) for the recommended format. `stylesheets` : A list of paths to css files the users wants to include globally. These are rendered by the `{{> styles }}` partial. TODO: ^^ Bad sentence? ^^ `scripts` : A list of `