--- 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 ``` ## 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!