12 KiB
version, date, author, title, description, summary, quick_tips
version | date | author | title | description | summary | quick_tips | |||
---|---|---|---|---|---|---|---|---|---|
1.0 | 2025-01-15 | DWS Foldsite Team | Template Discovery System | Understanding how Foldsite finds and chooses templates | Deep dive into Foldsite's hierarchical template discovery algorithm - learn exactly how templates are matched to content. |
|
Template Discovery System
Understanding how Foldsite discovers and chooses templates is key to building sophisticated sites. This guide explains the complete template resolution algorithm.
The Discovery Algorithm
When Foldsite renders a page, it follows a hierarchical search pattern to find the best template.
Core Principle
Specificity wins. More specific templates override general ones.
Think of it like CSS specificity:
#specific-id (most specific)
.class-name
element (least specific)
In Foldsite:
my-post.html (most specific - exact file)
__file.md.html (category + extension)
__file.document.html (category only)
__file.html (least specific - any file)
File Type Detection
Before template discovery, Foldsite determines the content type:
For Files
Step 1: Extract extension
blog/my-post.md → extension: "md"
Step 2: Map to categories
"md" → categories: ["document", "md"]
Category mapping:
GENERIC_FILE_MAPPING = {
"document": ["md", "txt", "html"],
"image": ["png", "jpg", "jpeg", "gif", "svg"],
"multimedia": ["mp4", "mp3", "webm"],
"other": [...] # Everything else
}
For Folders
Step 1: Count file types in folder
photos/vacation/
IMG_001.jpg → jpg: 1
IMG_002.jpg → jpg: 2
IMG_003.jpg → jpg: 3
notes.txt → txt: 1
Step 2: Most common type wins
Most common: jpg (3 files)
→ categories: ["image", "jpg"]
Template Search Order
For Files: blog/my-post.md
Given:
- Path:
blog/my-post.md
- Type:
file
- Categories:
["document", "md"]
- Extension:
md
Search order:
-
Exact file match in current directory
templates/blog/my-post.html
-
Type + extension in current directory
templates/blog/__file.md.html
-
Type + category in current directory (most specific category first)
templates/blog/__file.document.html
-
Generic type in current directory
templates/blog/__file.html
-
Move up one directory, repeat steps 2-4
templates/__file.md.html templates/__file.document.html templates/__file.html
-
Default template (if exists)
templates/default.html
First match wins!
For Folders: photos/vacation/
Given:
- Path:
photos/vacation/
- Type:
folder
- Categories:
["image"]
(most files are images)
Search order:
-
Exact folder match
templates/photos/vacation/__folder.html
-
Type + category in current directory
templates/photos/__folder.image.html
-
Generic folder in current directory
templates/photos/__folder.html
-
Move up one directory, repeat steps 2-3
templates/__folder.image.html templates/__folder.html
-
Default template
templates/default.html
Practical Examples
Example 1: Blog Post
Content: content/blog/posts/2024-my-post.md
Template search:
1. templates/blog/posts/2024-my-post.html ✗ Not found
2. templates/blog/posts/__file.md.html ✗ Not found
3. templates/blog/posts/__file.document.html ✗ Not found
4. templates/blog/posts/__file.html ✗ Not found
5. templates/blog/__file.md.html ✓ FOUND!
Result: Uses templates/blog/__file.md.html
Why: Most specific template found in the hierarchy.
Example 2: Homepage
Content: content/index.md
Template search:
1. templates/index.html ✓ FOUND!
Result: Uses templates/index.html
Why: Exact file match (most specific possible).
Example 3: Photo Gallery
Content: content/photos/vacation/
(folder with 50 JPG files)
Categories: ["image"]
Template search:
1. templates/photos/vacation/__folder.html ✗ Not found
2. templates/photos/__folder.image.html ✓ FOUND!
Result: Uses templates/photos/__folder.image.html
Why: Type + category match in parent directory.
Example 4: Deep Nesting
Content: content/docs/guides/advanced/testing.md
Template search:
1. templates/docs/guides/advanced/testing.html ✗ Not found
2. templates/docs/guides/advanced/__file.md.html ✗ Not found
3. templates/docs/guides/__file.md.html ✗ Not found
4. templates/docs/__file.md.html ✓ FOUND!
Result: Uses templates/docs/__file.md.html
Why: Climbs directory tree until finding a match.
Template Cascade
Templates cascade down through directories:
templates/
├── __file.md.html ← Default for ALL markdown
└── blog/
└── __file.md.html ← Override for blog/ only
Rendering content/about.md
:
- Uses
templates/__file.md.html
Rendering content/blog/post.md
:
- Uses
templates/blog/__file.md.html
(more specific)
Multi-Level Cascade
templates/
├── __file.md.html ← Level 1: Site default
├── blog/
│ └── __file.md.html ← Level 2: Blog default
└── blog/
└── tutorials/
└── __file.md.html ← Level 3: Tutorial-specific
Effect:
content/about.md
→ Level 1 templatecontent/blog/news.md
→ Level 2 templatecontent/blog/tutorials/python.md
→ Level 3 template
Category Priority
Files can belong to multiple categories. More specific categories come first.
Category Hierarchy
For my-post.md
:
Categories: ["md", "document"]
↑ ↑
specific general
Search order:
1. __file.md.html ← Most specific
2. __file.document.html ← More general
3. __file.html ← Most general
Debug Mode
Enable debug mode to see template discovery in action:
# config.toml
[server]
debug = true
Console output when visiting a page:
[DEBUG] Template discovery for: blog/my-post.md
[DEBUG] Content type: file
[DEBUG] Categories: ['md', 'document']
[DEBUG] Extension: md
[DEBUG]
[DEBUG] Searching templates:
[DEBUG] 1. templates/blog/my-post.html - NOT FOUND
[DEBUG] 2. templates/blog/__file.md.html - FOUND!
[DEBUG]
[DEBUG] Using template: templates/blog/__file.md.html
Debug Test Page
Create a test page to understand discovery:
---
title: "Template Discovery Test"
---
# Current Template Info
**Current Path:** {{ currentPath }}
**Styles Loaded:**
{% for style in styles %}
- {{ style }}
{% endfor %}
**Metadata:**
{{ metadata }}
Visit this page and check the console to see which template was used.
Edge Cases
No Template Found
If no template matches:
For files:
- Foldsite serves the file directly (download)
- Useful for PDFs, images, etc.
For folders:
- Returns 404 error
- Need at least one
__folder.html
template
Hidden Files
Files/folders starting with ___
are ignored:
content/
├── post.md ✓ Will be rendered
└── ___draft.md ✗ Ignored completely
No template search is performed for hidden content.
Multiple Extensions
Only the last extension is considered:
my-file.tar.gz → extension: "gz"
Not: tar.gz
or tar
Style Discovery
Styles follow similar logic to templates but accumulate instead of first-match:
Style Search for blog/post.md
All matching styles are loaded (in order):
1. /base.css ← Always loaded
2. /blog/__file.md.css ← If exists
3. /blog/__file.document.css ← If exists
4. /__file.md.css ← If exists (from root)
5. /blog/post.md.css ← If exists (specific file)
All found styles are included (not just first match).
Rendering:
<link rel="stylesheet" href="/styles/base.css">
<link rel="stylesheet" href="/styles/blog/__file.md.css">
<link rel="stylesheet" href="/styles/__file.md.css">
Optimization Tips
1. Keep Templates at Appropriate Levels
Good:
templates/
├── __file.md.html ← General template
└── blog/
└── __file.md.html ← Blog-specific customization
Avoid:
templates/
├── post1.html
├── post2.html
├── post3.html ← Repetitive!
└── ...
2. Use Categories Effectively
Good:
templates/
├── __file.md.html ← For markdown
├── __folder.image.html ← For galleries
└── __file.document.html ← For all documents
Avoid:
templates/
├── __file.html ← Too generic
└── (nothing else)
3. Understand the Cascade
Place templates where they make sense:
Project structure:
content/
├── blog/ → Frequent posts, custom layout
├── docs/ → Technical docs, different layout
└── about.md → One-off pages
Template structure:
templates/
├── __file.md.html ← Default for one-off pages
├── blog/
│ └── __file.md.html ← Blog-specific
└── docs/
└── __file.md.html ← Docs-specific
Common Patterns
Pattern: Section-Specific Layouts
Different sections need different layouts:
templates/
├── base.html ← Shared wrapper
├── __file.md.html ← Default content
├── blog/
│ ├── __file.md.html ← Blog posts
│ └── __folder.md.html ← Blog index
├── portfolio/
│ ├── __file.md.html ← Project pages
│ └── __folder.md.html ← Portfolio grid
└── docs/
├── __file.md.html ← Documentation pages
└── __folder.md.html ← Docs index
Pattern: Gradual Specialization
Start general, add specificity as needed:
Phase 1: MVP
templates/
├── base.html
└── __file.md.html
Phase 2: Add Gallery
templates/
├── base.html
├── __file.md.html
└── __folder.image.html ← New!
Phase 3: Custom Blog
templates/
├── base.html
├── __file.md.html
├── __folder.image.html
└── blog/
└── __file.md.html ← New!
Pattern: Override Single Page
Override one specific page:
templates/
├── __file.md.html ← All markdown
└── index.html ← Special homepage
Troubleshooting
Template Not Being Used
Check:
- File name - Is it exactly right?
- Location - Is it in the right directory?
- Extension -
.html
, not.htm
or.jinja
- Debug mode - What does the console say?
Debug:
# Enable debug
[server]
debug = true
# Restart and check console output
Wrong Template Used
Likely cause: More specific template exists
Example:
Want: templates/__file.md.html
Using: templates/blog/__file.md.html ← More specific!
Solution: Update the more specific template, or remove it.
Styles Not Loading
Check:
- Style file exists in
styles/
directory - Path matches template expectations
- Browser dev tools - Are styles being requested?
Remember: Unlike templates, all matching styles load.
Next Steps
- Template System Overview - Basics of templates
- Template Helpers - Functions available in templates
- Recipes - Working examples
- Styles Guide - CSS cascade system
Understanding template discovery gives you complete control over your site's presentation. Use it wisely!