Fully migrate from compile-time maud templates to runtime Tera:
- Rewrote main.rs to use TemplateEngine and discover_sections()
- Replaced hardcoded blog/projects with generic section loop
- Added Clone derive to Frontmatter and Content
- Fixed section_type dispatch via Section struct
- Deleted src/templates.rs, removed maud dependency
Users can now add sections without code changes.
Enable generic section processing by adding:
- Section struct with index, name, section_type, path
- Section::collect_items() to gather content in a section
- discover_sections() to find all directories with _index.md
Section type is determined from frontmatter `section_type` field,
falling back to directory name. Includes 5 unit tests.
Lay groundwork for user-editable templates by adding Tera as a
runtime template engine alongside the existing maud templates.
Changes:
- Add tera dependency
- Create TemplateEngine struct with render methods
- Add TemplateLoad/TemplateRender error variants
- Add section_type/template fields to Frontmatter
- Create templates/ directory with base, page, section, and content templates
Dead code warnings are expected; TemplateEngine will be wired
in to replace maud in subsequent commits.
Replace hardcoded "/blog/{slug}.html" URL pattern with dynamic
path derivation using Content.output_path(). This ensures feed
URLs work correctly for any content location, not just blog posts.
Update all template functions to accept nav parameter and iterate
over discovered NavItem slice instead of hardcoded links.
Refactor main.rs:
- Call discover_nav() early in run()
- Thread nav to all template renders
- Replace hardcoded page list with dynamic discovery
Navigation is now fully driven by filesystem structure.
Add NavItem struct and discover_nav() function to scan content
directory and automatically build navigation from:
- Top-level .md files (pages)
- Directories with _index.md (sections)
Navigation is sorted by frontmatter weight, then alphabetically.
Custom nav_label field allows overriding title in nav menu.
Includes 5 unit tests covering page/section discovery, weight
ordering, and nav_label support.
Switch mermaid-rs-renderer from git dependency to crates.io 0.1.
Vendor and patch dagre_rust 0.0.5 to fix upstream panic in
remove_edge_label_proxies() where unwrap() is called on None
when processing edge label proxies without edge references.
This enables sequence diagrams and state diagrams that previously
crashed the build.
Intercept 'mermaid' code blocks in render.rs and call
mermaid::render_diagram() to convert to inline SVG.
- Use catch_unwind to handle upstream dagre_rust panics gracefully
- Graceful fallback: show raw code with mermaid-error class on failure
- Flowcharts render correctly; some diagram types hit upstream bugs
Add src/mermaid.rs with render_diagram() wrapper around
mermaid-rs-renderer for build-time Mermaid-to-SVG conversion.
- Use mermaid-rs-renderer git dependency (SVG-only, no PNG)
- Configure with RenderOptions::modern() theme
- Include unit tests for flowchart and sequence diagrams
Enable ENABLE_MATH in pulldown-cmark options and implement
InlineMath/DisplayMath event handlers in the render pipeline.
- Inline math ($...$) renders via render_math(_, false)
- Display math ($$...$$) wrapped in <div class="math-display">
- Graceful degradation: errors logged to stderr, raw LaTeX shown
with class="math-error" for styling
Add src/math.rs with render_math() wrapper around katex-rs for
build-time LaTeX to HTML conversion. Wire module into main.rs.
- Use KatexContext::default() for standard LaTeX function registry
- Settings: display_mode toggle, throw_on_error=false for graceful
degradation
- Include unit tests for inline/display math rendering
Adapted Helix nix/injections.scm for tree-sitter-highlight:
- Removed Helix-specific predicates
- Recognizes bash in buildPhase/installPhase, python in testScript,
json in fromJSON, etc.
- queries/nix-highlights.scm: Adapted from Helix editor queries.
Properly identifies functions, properties, variable parameters,
escape sequences, and string interpolation. Much richer than
the bundled tree-sitter-nix query (99 lines vs 113 lines).
- src/highlight.rs: Load custom Nix query via include_str!
instead of using bundled HIGHLIGHTS_QUERY.
- static/style.css: Fix variable (#e36209) and punctuation (#586069)
colors to be distinct from text color.
Results: hl-function now appears (6 occurrences), hl-property
visible (17), hl-variable reduced from 43 to 17. Functions like
mkShell now render in purple/blue instead of orange.
- src/highlight.rs: Add 7 new captures to HIGHLIGHT_NAMES:
embedded, escape, function, punctuation.special, string.special,
string.special.path, string.special.uri. Now 27 total captures.
- static/style.css: Add CSS variables and class rules for new
captures in both light and dark themes. escape gets bold
styling, string-special uses distinct color.
These captures are used by tree-sitter-nix but were previously
missing, causing sparse highlighting. Now functions, escapes,
and paths are properly highlighted.
- Cargo.toml: Add tree-sitter grammars for Nix, Python, JavaScript,
TypeScript, Go, C, CSS, HTML, YAML. Upgrade tree-sitter-highlight
to 0.26 for language version 15 compatibility.
- src/highlight.rs: Add Language enum variants and get_config()
match arms for all new languages. Update render() callback for
0.26 API (writes attributes to buffer). Add tests for Nix and
Python highlighting.
TOML excluded due to incompatible API (tree-sitter 0.20 vs 0.26).
- content/about.md: Rewrite with first-person voice, remove
"next-generation" and "craft tools that emphasize" patterns.
Add personality ("probably more than it should").
- content/collab.md: More direct language, remove "find value in"
and "broader community" hedging. Shorter bullet lists.
- AGENTS.md: Remove "state-of-the-art", update architecture tree
to reflect current modules (config, feed, templates), fix
stale config section to show actual site.toml usage.
- netlify.toml: Configure cargo build --release and run compiler.
Publish directory set to public/.
- static/_headers: Add security headers (X-Frame-Options, CSP, etc.)
and cache control for static assets (1 year for css/images,
1 hour for HTML, 1 hour for feed).
- src/feed.rs: New module with generate_atom_feed() that produces
Atom 1.0 XML from blog posts. Uses config.base_url for absolute
entry URLs. Includes xml_escape() helper.
- src/main.rs: Wire mod feed and call generate_feed() after blog
index generation. Outputs to public/feed.xml.
- src/templates.rs: Add <link rel="alternate" type="application/atom+xml">
autodiscovery link to page head using config.base_url.
Feed includes title, author, updated timestamp, and entries with
title, link, id, updated, and summary for each blog post.
- Cargo.toml: Add toml and serde dependencies
- site.toml: New config with title, author, base_url
- src/config.rs: SiteConfig struct with load() function
- src/error.rs: Add Error::Config for parse errors
- src/main.rs: Load site.toml, thread config and page paths
through generators
- src/templates.rs: Use config.title in nav/titles,
config.author in footer, config.base_url for canonical URLs.
All three config fields verified in generated HTML output.
- src/content.rs: output_path() now returns slug.html instead of
slug/index.html for regular content.
- src/templates.rs: All hrefs use explicit .html extension.
Nav links point to index.html, blog.index.html, about.html.
Blog post links use ./slug.html format.
- src/main.rs: Adjust depth values (root=0, blog posts=1).
No more directory-per-page overhead. file:// navigation works
without directory listings. True suckless structure.
- src/templates.rs: Add depth parameter to all template functions.
Add relative_prefix() helper that generates "./", "../", "../..", etc.
All hrefs now use relative paths instead of absolute.
Unit test for relative_prefix() added.
- src/main.rs: Pass depth to templates based on output location.
Root=0, blog index/pages=1, blog posts=2.
Navigation works correctly when viewed via file:// protocol.
Site is now IPFS-compatible.
- Cargo.toml: Add tree-sitter-highlight + grammar crates
(rust, bash, json). TOML dropped due to API incompatibility.
- src/highlight.rs: Language enum, highlight_code() function,
4 unit tests covering parsing and HTML generation.
- Uses static HTML_ATTRS array for zero-allocation rendering.
Add minimal e2e pipeline to transform content → HTML:
- src/error.rs: Custom error types with thiserror
- src/content.rs: YAML frontmatter parsing via gray_matter
- src/render.rs: Markdown → HTML via pulldown-cmark
- src/templates.rs: Maud templates for base layout and posts
- src/main.rs: Pipeline orchestrator
All 15 blog posts successfully rendered to public/blog/*/index.html.
Added thiserror and walkdir dependencies.
Added public/ and DepMap fragment to .gitignore and AGENTS.md.