diff --git a/content/_index.md b/content/_index.md
index 2bf29bd..43738be 100644
--- a/content/_index.md
+++ b/content/_index.md
@@ -1,19 +1,15 @@
+++
-title = "Brains!!!"
+title = "Elf's Notes"
+description = "This is Elf Sternberg's brain dump of notes about various software things he knows. If you find it useful, good! Just be aware that this site is probably a bit random, as it consists of explanations, snippets, and recipes for how I do things. It's meant to be a guide from a past version of myself to explain things to a future version that may have forgotten."
+date = 2025-05-01T18:00:00+00:00
+updated = 2021-05-01T18:00:00+00:00
+template = "index.html"
-# The homepage contents
-[extra]
-lead = "This is Elf Sternberg's brain dump of notes about various software things he knows. If you find it useful, good! Just be aware that this site is probably a bit random, as it consists of explanations, snippets, and recipes for how I do things. It's meant to be a guide from a past version of myself to explain things to a future version that may have forgotten."
-
-# Menu items
-[[extra.menu.main]]
-name = "Blog"
-section = "blog"
-url = "https://elfsternberg.com"
-weight = 20
-
-[[extra.list]]
-title = "Zola"
-url="/docs/zola"
-content = 'This site is hosted with Zola, a static site generator written in Rust.'
+[taxonomies]
+documentation=["Reference"]
+++
+This is Elf Sternberg's brain dump of notes about various software things he
+knows. If you find it useful, good! Just be aware that this site is probably a
+bit random, as it consists of explanations, snippets, and recipes for how I do
+things. It's meant to be a guide from a past version of myself to explain things
+to a future version that may have forgotten.
diff --git a/content/docs/git/_index.md b/content/git/_index.md
similarity index 98%
rename from content/docs/git/_index.md
rename to content/git/_index.md
index 66eb2ae..65d983e 100644
--- a/content/docs/git/_index.md
+++ b/content/git/_index.md
@@ -3,7 +3,7 @@ title = "Git Notes"
description = "Basic documentation of Git"
date = 2022-04-27T18:00:00+00:00
updated = 2022-04-27T18:00:00+00:00
-template = "docs/section.html"
+template = "section.html"
sort_by = "weight"
weight = 6
draft = false
diff --git a/content/docs/zola-cookbook/_index.md b/content/zola-cookbook/_index.md
similarity index 93%
rename from content/docs/zola-cookbook/_index.md
rename to content/zola-cookbook/_index.md
index 2177a31..c3d27d5 100644
--- a/content/docs/zola-cookbook/_index.md
+++ b/content/zola-cookbook/_index.md
@@ -3,7 +3,7 @@ title = "Zola Cookbook"
description = "Snippets I've developed that I want to keep"
date = 2022-04-27T18:00:00+00:00
updated = 2022-04-27T18:00:00+00:00
-template = "docs/section.html"
+template = "section.html"
sort_by = "weight"
weight = 5
draft = false
@@ -62,6 +62,6 @@ Zola shortcode to import the macro template into Markdown and start the render:
Invocation in Markdown file, providing the data source:
```
-{{ definition_list(source="@/docs/zola/definitions.json") }}
+{{ definition_list(source="@/docs/zola/definitions.json") }}
```
diff --git a/content/docs/zola/_index.md b/content/zola/_index.md
similarity index 79%
rename from content/docs/zola/_index.md
rename to content/zola/_index.md
index 6ed528f..c6f3b2c 100644
--- a/content/docs/zola/_index.md
+++ b/content/zola/_index.md
@@ -3,7 +3,7 @@ title = "Zola"
description = "Zola is a static site generator"
date = 2025-05-01T18:00:00+00:00
updated = 2021-05-01T18:00:00+00:00
-template = "docs/section.html"
+template = "section.html"
sort_by = "weight"
weight = 4
draft = false
@@ -13,19 +13,55 @@ categories=["Web Development", "Static Site Generation", "Zola"]
+++
[Zola](https://getzola.org) is a static site generator written in
-[Rust](../rust). It builds an entire web page out of a structured markdown
-collection and a collection of HTML templates. The templating language is called
-[Tera](https://tera.netlify.app).
-
-Zola is a single binary capable of assembling the website out of a collection of
-templates, SASS files, static data (including CSS if you're not into SASS), and
-markdown files. The Markdown files create the structure of the website as a
-series of folders.
+[Rust](../rust). It is a single binary that builds an entire web site out of a
+collection of markdown documents in a folder-structured hierarchy, using a
+corresponding collection of HTML templates, which in turn use a corresponding
+collection of SASS collection and a collection of HTML templates. The templating
+language is called [Tera](https://tera.netlify.app).
If you need anything else (Typescript built into Javascript, templates other
than Zola's internal, static file conversion, etc.), you'll need separate
toolchains for those.
+## Mental Model for Zola
+
+A website built with Zola originates with the `content/` folder. Inside that
+folder, every markdown document and every folder creates a corresponding page in
+the constructed website. There are only *two* models you have to understand
+Zola: *sections* and *pages*.
+
+A *section* is a folder with a file named `_index.md` in it; note the
+underscore, which signifies the section definition file. For these documents, a
+[`Section` model](#section) is the default context object received by the
+template. Each markdown document in the same folder, and each folder immediately
+underneath this folder that has an `index.md` folder (note the lack of
+underscore) is a *page* and receives the [`Page` model](#page) as the default
+context.
+
+Every markdown document has two parts: a frontmatter block, written in TOML, and
+the content, written in Markdown. Whether a `section` or `page` context is
+passed by default, if there is content the `.content` field will be the HTML
+output of the markdown in the document.
+
+Every folder, whether containing an `_index.md` or `index.md` file, can contain
+co-located assets such a images, videos, and even Javascript. These will be
+found in the `.assets` field of the context object (the use of co-located assets
+in why a folder can be a page).
+
+Whether a `Page` or a `Section`, the corresponding context object provides means
+by which every template has access to the metadata (and even the content!) of
+every other markdown document, arranged in the hierarchy described in the
+`content` folder.
+
+### Recommendation
+
+1. Design your document hierarchy first.
+2. Construct your content folder to support that hierarchy.
+3. Build the `Section` template for the home page.
+4. Build the `Section` template for your level two sections
+5. Build the corresponding `Page` templates.
+6. Worry about Sass afterward
+
## Running Zola
Zola has only a few commands:
@@ -66,7 +102,7 @@ underscore prefix) is considered a *page*. This allows content writers to
supply additional assets, such as images or data files, along with the contents
of the page.
-## The Templating Languagae
+## The Templating Language
The Tera templating language looks a lot like Django's, or for that matter any
number of templating languages. Every page generated with Tera receives a
@@ -139,7 +175,7 @@ Conditional statements are managed with `if/is ... else ... endif`
The list of `is` tests that are shipped with Zola are:
-{{ definition_list(source="docs/zola/predicates.json") }}
+{{ definition_list(source="zola/predicates.json") }}
#### `for`
@@ -222,7 +258,7 @@ variable. There are a few basic operations and filters available, however:
**Math And Logic Expressions**:
-{{ definition_list(source="docs/zola/expressions.json") }}
+{{ definition_list(source="zola/expressions.json") }}
**Concatenation**:
@@ -244,31 +280,31 @@ An entire chunk of HTML can be filtered by:
The filters provided are:
-{{ definition_list(source="docs/zola/filters.json") }}
+{{ definition_list(source="zola/filters.json") }}
### Functions
Only a few functions provide ad-hoc expressions in-line with template
interpretation.
-- `range`: Generates an array of numbers.
-- `now`: Generates the current datetime
-- `get_random`: Generates a random number
-- `get_env`: Returns an environment variable
-- `get_page`: Returns a the content of a page in the Zola content folder
-- `get_section`: Returns the content of a Zola section (an `_index.md`) file as an
+- `range(end=n, start=0, [step_by=n])`: Generates an array of numbers.
+- `now(datetime, utc)`: Generates the current datetime.
+- `get_random(end=n, [start=0])`: Generates a random number
+- `get_env(name="s", default="d")`: Returns an environment variable
+- `get_page(path="p")`: Returns a the content of a page in the Zola content folder
+- `get_section(path="p")`: Returns the content of a Zola section (an `_index.md`) file as an
object.
-- `get_taxonomy_url`: Returns the URL of a Zola taxonomy index
-- `get_url`: Gets the generated URL for a document in the Zola content folder
-- `get_image_metadata`: Gets the metadata for an image in Zola's static folder
-- `load_data`: (Zola) Loads static data from a file. Understands TOML, JSON, CSV and
+- `get_taxonomy_url(kind="taxonomy", name=page.taxonomies.category)`: Returns the URL of a Zola taxonomy index
+- `get_url(path="p")`: Gets the generated URL for a document in the Zola content folder
+- `get_image_metadata(path="p")`: Gets the metadata for an image in Zola's static folder
+- `load_data(path="p")`: (Zola) Loads static data from a file. Understands TOML, JSON, CSV and
BibTeX. Takes either `path=` or `url=` (!) as an argument.
-- `resize_image`: (Zola) Takes an image, resizes the image, and provides a link to the
- resized image.
+- `resize_image(path, width, height, op, format, quality)`: (Zola) Takes an
+ image, resizes the image, and provides a link to the resized image.
## Zola Content
-### Sections
+### Sections {#section}
In Zola, every folder under `./content/` (including that folder itself) is
potentially a _section_. Sections are basically Zola's version of the WWW
@@ -315,7 +351,7 @@ available to the template:
- `assets`: An array of assets available in this section.
- `ancestors`: An array of parent paths, with the root being the last one.
-### Pages
+### Pages {#page}
A page is _either_ a markdown file within the same folder as its section, or it
is in a subfolder with a file named `index.md` (note the lack of prefix
@@ -339,7 +375,7 @@ The following items can appear in the TOML header of a page:
- `[taxonomies]`: The taxonomies for this page
- `[extra]`: Your own extra data
-Pages have the following information in their context:
+Pages derive the following information in their context:
- `content`: The markdown content from the page's file
- `title`: The title, if present in the TOML block
diff --git a/content/docs/zola/expressions.json b/content/zola/expressions.json
similarity index 100%
rename from content/docs/zola/expressions.json
rename to content/zola/expressions.json
diff --git a/content/docs/zola/expressions.yaml b/content/zola/expressions.yaml
similarity index 100%
rename from content/docs/zola/expressions.yaml
rename to content/zola/expressions.yaml
diff --git a/content/docs/zola/filters.json b/content/zola/filters.json
similarity index 100%
rename from content/docs/zola/filters.json
rename to content/zola/filters.json
diff --git a/content/docs/zola/filters.yaml b/content/zola/filters.yaml
similarity index 100%
rename from content/docs/zola/filters.yaml
rename to content/zola/filters.yaml
diff --git a/content/docs/zola/predicates.json b/content/zola/predicates.json
similarity index 100%
rename from content/docs/zola/predicates.json
rename to content/zola/predicates.json
diff --git a/content/docs/zola/predicates.yaml b/content/zola/predicates.yaml
similarity index 100%
rename from content/docs/zola/predicates.yaml
rename to content/zola/predicates.yaml
diff --git a/sass/index.scss b/sass/index.scss
new file mode 100644
index 0000000..7d20386
--- /dev/null
+++ b/sass/index.scss
@@ -0,0 +1,226 @@
+@import "design/_normalize";
+@import "design/_scales";
+@import "design/_typography";
+@import "design/fonts/_nunito";
+@import "design/fonts/_sauna_mono";
+
+:root {
+ --default-font-size: var(--step-0);
+ --background-color: #ffffff;
+ --border-color: #e9ecef;
+ --text-color: #1f000d;
+ --header-size: calc(1.5 * var(--step-0) + 2 * var(--space-3xs));
+}
+
+:root {
+ font-size: var(--default-font-size);
+ font-family: "Nunito", sans-serif;
+}
+
+.toggle-dark {
+ display: none;
+}
+
+body {
+ padding-top: var(--header-size);
+ font-size: var(--default-font-size);
+ font-family: "Nunito", sans-serif;
+ font-weight: 400;
+}
+
+@mixin fixed-top {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 1000;
+}
+
+.container {
+ max-width: 1044px;
+ width: 100%;
+ padding: 0 var(--space-xs) 0 var(--space-xs);
+ margin-right: auto;
+ margin-left: auto;
+}
+
+.hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ margin-left: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+.navbar {
+ display: flex;
+ flex-wrap: nowrap;
+ justify-content: flex-start;
+ align-items: center;
+ padding-top: calc(0.5 * var(--space-3xs));
+ padding-bottom: calc(0.5 * var(--space-3xs));
+ background-color: var(--background-color);
+ opacity: 0.95;
+ border-bottom: 1px solid var(--border-color);
+ @include fixed-top();
+
+ .container {
+ display: flex;
+ flex-wrap: inherit;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ .btn {
+ cursor: pointer;
+ display: inline-block;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #1d2d35;
+ text-align: cent er;
+ vertical-align: middle;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ font-size: 1rem;
+ border-radius: 0.25rem;
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,
+ border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+
+ &:focus {
+ box-shadow: none;
+ }
+ }
+
+ .brand {
+ font-size: var(--step-1);
+ margin-right: var(--space-s);
+ font-weight: 700;
+ color: var(--text-color);
+ text-decoration: none;
+
+ &:visited,
+ &:hover {
+ color: var(--text-color);
+ text-decoration: none;
+ }
+ }
+
+ form {
+ font-size: var(--step-0);
+ flex-grow: 1;
+ margin-left: var(--space-2xl);
+ margin-right: var(--space-s);
+
+ input {
+ appearance: none;
+ background-clip: padding-box;
+ background: #f8f9fa;
+ border-radius: 0.25rem;
+ border: 0;
+ color: #1d2d35;
+ line-height: 1.5;
+ padding: var(--space-3xs) var(--space-l) var(--space-3xs) var(--space-3xs);
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ width: 100%;
+ }
+ }
+
+ .navbar-nav {
+ font-size: var(--step-1);
+ align-items: center;
+ display: flex;
+ list-style: none;
+ gap: var(--space-xs);
+ margin-bottom: 0;
+
+ & > * {
+ line-height: 1.5;
+ vertical-align: middle;
+ }
+ }
+}
+
+@mixin toc-sticky {
+ max-width: 100%;
+ position: sticky;
+ top: var(--space-xl);
+ height: calc(100vh - var(--space-xl));
+ z-index: 900;
+
+ &:hover .scrollable-sidebar {
+ scrollbar-color: #e9ecef #fff;
+ }
+
+ .scrollable-sidebar {
+ scrollbar-width: thin;
+ scrollbar-color: #fff #fff;
+ display: block;
+ width: auto;
+ overflow-y: scroll;
+ padding-bottom: 4rem;
+ }
+}
+
+.main {
+ display: flex;
+ position: relative;
+ flex-wrap: nowrap;
+
+ ul {
+ padding-left: 0;
+ padding-bottom: var(--step--1);
+ list-style: none;
+
+ ul {
+ padding-left: var(--space-s);
+ list-style: disc;
+ }
+ }
+
+ .left-sidebar {
+ @include toc-sticky();
+ font-size: 80%;
+ order: 0;
+ flex: 0 1 auto;
+ width: 25%;
+ padding-right: var(--space-2xs);
+ border-right: 1px solid var(--border-color);
+ }
+
+ .docs-toc {
+ @include toc-sticky();
+ font-size: 66.666%;
+ order: 2;
+ flex: 0 0 auto;
+ width: 18.75%;
+ border-left: 1px solid var(--border-color);
+ padding-left: var(--space-2xs);
+
+ nav > ul {
+ & > li:not(:first-child) {
+ margin-top: var(--space-3xs);
+ border-top: 1px dashed #e9ecef;
+ }
+ & > li:not(:first-child) {
+ padding-top: var(--space-3xs);
+ }
+ ul {
+ padding-bottom: 0;
+ }
+ }
+ }
+
+ article {
+ order: 1;
+ padding: 0 var(--space-s) var(--space-m-l) var(--space-s);
+ flex: 0 0 auto;
+ width: 56.25%;
+ }
+}
+
diff --git a/templates/base.html b/templates/base.html
index e975818..5ba5bb9 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -1,26 +1,27 @@
-{%- import 'macros/font_preloads.html' as font_preloads -%}
-{%- import 'macros/stylesheets.html' as stylesheets -%}
-{%- import 'macros/header.html' as header -%}
-{%- import 'macros/footer.html' as footer -%}
-{{ font_preloads::preloads() }}
-{{ stylesheets::stylesheets() }}
+{% block styles %}
+
+{% endblock %}
+
+{% block seo %}{% endblock %}
-{% block body %}{% set page_class="home" %}{% endblock body %}
-
- {% block header %}
- {{ header::header(current_section="/") }}
- {% endblock header %}
+
+ {% block body %}
+ {% include "components/sitebar.html" %}
+ {% block content %}
+ {% block header %}
+ {% endblock header %}
- {% block content %}{% endblock content %}
-
- {% block footer %}
- {{ footer::footer() }}
- {% endblock footer %}
+ {% block main %}
+ {% endblock main %}
+ {% endblock content %}
+ {% block footer %}
+ {% endblock footer %}
+ {% endblock body %}
diff --git a/templates/components/left-sidebar-largedoc.html b/templates/components/left-sidebar-largedoc.html
new file mode 100644
index 0000000..4b21a0d
--- /dev/null
+++ b/templates/components/left-sidebar-largedoc.html
@@ -0,0 +1,39 @@
+{#
+ The left sidebar for large document sections navigation for topics that
+ have child pages. This sidebar contains links to all the pages, and all their
+ level-one headers, for all the content in the section.
+#}
+
+
diff --git a/templates/components/left-sidebar-singleton.html b/templates/components/left-sidebar-singleton.html
new file mode 100644
index 0000000..c632d80
--- /dev/null
+++ b/templates/components/left-sidebar-singleton.html
@@ -0,0 +1,42 @@
+{#
+ The left sidebar for singleton pages provides navigation is for topics that
+ have no child pages. This sidebar contains only links to all the level zero
+ and level one headers for all content in the site. It should only be used for
+ document section that have only a section definition file, `_index.md`.
+#}
+
+
+
+
diff --git a/templates/components/right-sidebar.html b/templates/components/right-sidebar.html
new file mode 100644
index 0000000..bf1299e
--- /dev/null
+++ b/templates/components/right-sidebar.html
@@ -0,0 +1,24 @@
+{% if section %} {% set toc = section.toc %} {% else %} {% set toc = page.toc %} {% endif %}
+
+
+
+
On this page
+
+
+
+
diff --git a/templates/components/sitebar.html b/templates/components/sitebar.html
new file mode 100644
index 0000000..31da7b9
--- /dev/null
+++ b/templates/components/sitebar.html
@@ -0,0 +1,103 @@
+
+