docs refactor
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 52s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 1m1s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 5m50s

This commit is contained in:
2025-10-09 18:21:23 -04:00
parent c9a3a21f07
commit ad81d7f3db
39 changed files with 12551 additions and 1037 deletions

View File

@ -0,0 +1,558 @@
---
version: "1.0"
date: "2025-01-15"
author: "DWS Foldsite Team"
title: "Template Discovery System"
description: "Understanding how Foldsite finds and chooses templates"
summary: "Deep dive into Foldsite's hierarchical template discovery algorithm - learn exactly how templates are matched to content."
quick_tips:
- "Templates are searched from most specific to most general"
- "First match wins - more specific templates override general ones"
- "Templates cascade down through directory hierarchies"
---
# 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:**
```python
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:**
1. **Exact file match** in current directory
```
templates/blog/my-post.html
```
2. **Type + extension** in current directory
```
templates/blog/__file.md.html
```
3. **Type + category** in current directory (most specific category first)
```
templates/blog/__file.document.html
```
4. **Generic type** in current directory
```
templates/blog/__file.html
```
5. **Move up one directory**, repeat steps 2-4
```
templates/__file.md.html
templates/__file.document.html
templates/__file.html
```
6. **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:**
1. **Exact folder match**
```
templates/photos/vacation/__folder.html
```
2. **Type + category** in current directory
```
templates/photos/__folder.image.html
```
3. **Generic folder** in current directory
```
templates/photos/__folder.html
```
4. **Move up one directory**, repeat steps 2-3
```
templates/__folder.image.html
templates/__folder.html
```
5. **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 template
- `content/blog/news.md` → Level 2 template
- `content/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:
```toml
# 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:
```markdown
---
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:**
```html
<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:**
1. **File name** - Is it exactly right?
2. **Location** - Is it in the right directory?
3. **Extension** - `.html`, not `.htm` or `.jinja`
4. **Debug mode** - What does the console say?
**Debug:**
```bash
# 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:**
1. **Style file exists** in `styles/` directory
2. **Path matches** template expectations
3. **Browser dev tools** - Are styles being requested?
**Remember:** Unlike templates, **all matching styles load**.
## Next Steps
- **[Template System Overview](index.md)** - Basics of templates
- **[Template Helpers](template-helpers.md)** - Functions available in templates
- **[Recipes](../recipes/)** - Working examples
- **[Styles Guide](../styles/)** - CSS cascade system
Understanding template discovery gives you complete control over your site's presentation. Use it wisely!