+ A minimalist PHP framework that turns folders into websites. No JavaScript, no build tools, just simple files.
+
+
diff --git a/app/default/content/00a-getting-started.md b/app/default/content/00a-getting-started.md
new file mode 100644
index 0000000..8d11e2a
--- /dev/null
+++ b/app/default/content/00a-getting-started.md
@@ -0,0 +1,7 @@
+## Getting Started
+
+This is demo content to help you understand how FolderWeb works. To replace it with your own content:
+
+1. Create a `/content` folder in your project root
+2. Add your content files (`.md`, `.html`, or `.php`)
+3. This demo will automatically disappear
diff --git a/app/default/content/01-core-concepts.md b/app/default/content/01-core-concepts.md
new file mode 100644
index 0000000..de0044f
--- /dev/null
+++ b/app/default/content/01-core-concepts.md
@@ -0,0 +1,15 @@
+## Core Concepts
+
+### File-Based Routing
+
+Drop a file in a folder and it's instantly accessible at a URL matching that path. Your folder structure becomes your URL structure.
+
+### Multiple Content Types
+
+- **Markdown** - Write in `.md` files, automatically converted to HTML
+- **HTML** - Pure HTML files for complete control
+- **PHP** - Dynamic content when you need it
+
+### Multi-File Pages
+
+Any folder without subfolders renders all content files (`.md`, `.html`, `.php`) in alphanumerical order. Mix formats freely!
diff --git a/app/default/content/01-index.md b/app/default/content/01-index.md
deleted file mode 100644
index 145e99a..0000000
--- a/app/default/content/01-index.md
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-## Quick Start
-
-1. **Empty the content folder** β Delete everything in `/content/` to start fresh
-2. **Copy the default folder** β Copy `/app/default/` to `/custom/` (one level up from app/) to create your own theme
-3. **Add your content** β Drop `.md`, `.html`, or `.php` files in `/content/` and they're live
-4. **Customize templates** β Edit files in `/custom/templates/` to change the look
-5. **Style it** β Add CSS in `/custom/styles/styles.css` for global styles
-
-## What Makes FolderWeb Different
-
-**File-based routing** β Your folder structure is your URL structure. No configuration needed.
-
-**No JavaScript** β Fast, simple, accessible websites that work everywhere.
-
-**Modern PHP & CSS** β Clean code using the latest language features and CSS capabilities.
-
-**No build step** β Edit a file, refresh the page. That's it.
-
-**Decade-proof** β Minimal dependencies mean this will work for years without breaking.
-
-## How This Page Works
-
-This frontpage demonstrates how you can **mix different file types** to create dynamic, custom layouts:
-
-- **`hero.php`** β Dynamic PHP component with live stats and styling
-- **`index.md`** β Static markdown content (this section!)
-
-Files in the same directory are rendered alphabetically. Want a different order? Prefix filenames with numbers like `00-hero.php` and `01-content.md`.
-
-## Features Demonstrated Here {#features}
-
-Explore this demo site to see what FolderWeb can do:
-
-- [Examples](/examples/) β Markdown, metadata, dates, and cover images
-- [Multilingual](/multilingual/) β Build sites in multiple languages
-- [Nested Content](/examples/nested/) β Organize content as deep as you need
-
-## Philosophy
-
-**Just enough, nothing more.** This framework uses minimal PHP to enable modern conveniences while remaining maintainable for years or decades.
-
-Read more in `CLAUDE.md` to understand the principles behind FolderWeb.
diff --git a/app/default/content/01-index.no.md b/app/default/content/01-index.no.md
deleted file mode 100644
index dc0a430..0000000
--- a/app/default/content/01-index.no.md
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-## Hurtigstart
-
-1. **TΓΈm innholdsmappen** β Slett alt i `/content/` for Γ₯ starte fra bunnen av
-2. **Kopier standardmappen** β Kopier `/app/default/` til `/custom/` (ett nivΓ₯ opp fra app/) for Γ₯ lage ditt eget tema
-3. **Legg til innhold** β Slipp `.md`, `.html`, eller `.php`-filer i `/content/` og de er live
-4. **Tilpass maler** β Rediger filer i `/custom/templates/` for Γ₯ endre utseendet
-5. **Stil det** β Legg til CSS i `/custom/styles/styles.css` for globale stiler
-
-## Hva gjΓΈr FolderWeb annerledes
-
-**Filbasert routing** β Mappestrukturen din er URL-strukturen din. Ingen konfigurasjon nΓΈdvendig.
-
-**Ingen JavaScript** β Raske, enkle, tilgjengelige nettsteder som fungerer overalt.
-
-**Moderne PHP & CSS** β Ren kode som bruker de nyeste sprΓ₯kfunksjonene og CSS-mulighetene.
-
-**Uten byggesteg** β Rediger en fil, oppdater siden. Det er det.
-
-**TiΓ₯r-sikker** β Minimale avhengigheter betyr at dette vil fungere i Γ₯revis uten Γ₯ gΓ₯ i stykker.
-
-## Hvordan denne siden fungerer
-
-Denne forsiden demonstrerer hvordan du kan **blande forskjellige filtyper** for Γ₯ lage dynamiske, egendefinerte layout:
-
-- **`hero.no.php`** β Dynamisk PHP-komponent med live statistikk og styling
-- **`index.no.md`** β Statisk markdown-innhold (denne seksjonen!)
-
-Filer i samme katalog rendres alfabetisk. Vil du ha en annen rekkefΓΈlge? Prefikser filnavn med tall som `00-hero.php` og `01-innhold.md`.
-
-## Funksjoner demonstrert her {#funksjoner}
-
-Utforsk denne demosiden for Γ₯ se hva FolderWeb kan gjΓΈre:
-
-- [Eksempler](/examples/) β Markdown, metadata, datoer og forsidebilder
-- [FlersprΓ₯klig](/multilingual/) β Bygg nettsteder pΓ₯ flere sprΓ₯k
-- [Nestet innhold](/examples/nested/) β Organiser innhold sΓ₯ dypt du trenger
-
-## Filosofi
-
-**Akkurat nok, ikke mer.** Dette rammeverket bruker minimal PHP for Γ₯ muliggjΓΈre moderne bekvemmeligheter samtidig som det forblir vedlikeholdbart i Γ₯revis eller tiΓ₯r.
-
-Les mer i `CLAUDE.md` for Γ₯ forstΓ₯ prinsippene bak FolderWeb.
diff --git a/app/default/content/02-features.html b/app/default/content/02-features.html
new file mode 100644
index 0000000..b766430
--- /dev/null
+++ b/app/default/content/02-features.html
@@ -0,0 +1,13 @@
+
+
Smart Features
+
+
+
Metadata - Use metadata.ini files for titles, dates, summaries
+
Date extraction - Folder names like 2025-11-01-title automatically show dates
+
Cover images - Add cover.jpg for list view thumbnails
+
Templates - Custom templates in /custom/templates/ override defaults
+
+
+
Explore the Demo
+
Check out the Articles and About pages to see different content types in action.
+
diff --git a/app/default/content/03-this-page-demo.md b/app/default/content/03-this-page-demo.md
new file mode 100644
index 0000000..e5d7cb5
--- /dev/null
+++ b/app/default/content/03-this-page-demo.md
@@ -0,0 +1,11 @@
+## About This Frontpage
+
+**This frontpage demonstrates the multi-file approach!** It's composed of:
+
+1. `00-welcome.php` - Hero header (PHP/HTML)
+2. `00a-getting-started.md` - Getting started guide (Markdown)
+3. `01-core-concepts.md` - Core concepts (Markdown)
+4. `02-features.html` - Features and links (HTML)
+5. `03-this-page-demo.md` - This explanation (Markdown)
+
+All files in the root `/content` folder are rendered together, just like pages in subfolders. Name your files anything you wantβthey'll render in alphanumerical order.
diff --git a/app/default/content/about/00-introduction.md b/app/default/content/about/00-introduction.md
new file mode 100644
index 0000000..470d79f
--- /dev/null
+++ b/app/default/content/about/00-introduction.md
@@ -0,0 +1,15 @@
+# About FolderWeb
+
+FolderWeb is a minimalist PHP framework designed for simplicity, longevity, and maintainability. It's built on a simple philosophy: **just enough, nothing more**.
+
+## Philosophy
+
+Modern web development has become unnecessarily complex. Build tools, package managers, JavaScript frameworks that change every few monthsβit's exhausting and unsustainable.
+
+FolderWeb is different. It's built to:
+
+- **Work for decades** without requiring constant updates
+- **Be understandable** by reading a few hundred lines of code
+- **Stay maintainable** without specialized knowledge
+- **Load fast** with no JavaScript overhead
+- **Just work** without configuration or setup
diff --git a/app/default/content/about/01-design-principles.html b/app/default/content/about/01-design-principles.html
new file mode 100644
index 0000000..fcdd4d7
--- /dev/null
+++ b/app/default/content/about/01-design-principles.html
@@ -0,0 +1,15 @@
+
+
Design Principles
+
+
Minimalism
+
Use only what is strictly necessary. No frameworks, no build tools, no package managers for frontend code. Every line of code must justify its existence.
+
+
File-Based Everything
+
Your folder structure is your URL structure. Drop a file in a folder and it's instantly accessible. No routes to configure, no databases to set up.
+
+
Override, Never Modify
+
Custom templates and styles go in /custom/ and automatically override defaults. The core files in /app/default/ remain untouched and updateable.
+
+
Modern Standards
+
Use modern PHP 8.4+ features (property hooks, readonly classes, modern array functions) and modern CSS capabilities. Avoid JavaScript entirelyβit's not needed for content-focused sites.
PHP 8.4+ - Modern PHP with property hooks, readonly classes, array_find(), and type safety
+
Apache - With mod_rewrite for clean URLs
+
Parsedown - Simple, reliable Markdown parser
+
+
+
Frontend
+
+
HTML5 - Semantic markup following best practices
+
CSS3 - Modern features like Grid, clamp(), OKLCH colors, CSS nesting
+
No JavaScript - By design, for faster loads and simpler maintenance
+
+
+
+
diff --git a/app/default/content/about/03-what-it-is-not.md b/app/default/content/about/03-what-it-is-not.md
new file mode 100644
index 0000000..89ca489
--- /dev/null
+++ b/app/default/content/about/03-what-it-is-not.md
@@ -0,0 +1,19 @@
+## What It's Not
+
+FolderWeb is **not**:
+
+- A CMS with an admin panel
+- A single-page application framework
+- A solution for complex web applications
+- Trying to scale to millions of users
+- Following current trends and fads
+
+## What It Is
+
+FolderWeb **is**:
+
+- A simple way to publish content
+- A foundation that will work for decades
+- A teaching tool for web fundamentals
+- A protest against unnecessary complexity
+- Perfect for documentation, blogs, portfolios, small business sites
diff --git a/app/default/content/about/04-get-started.md b/app/default/content/about/04-get-started.md
new file mode 100644
index 0000000..80c52c8
--- /dev/null
+++ b/app/default/content/about/04-get-started.md
@@ -0,0 +1,21 @@
+## Get Started
+
+Ready to build something simple and lasting?
+
+1. Create a `/content` folder
+2. Add your first `.md` file
+3. That's itβyou're publishing
+
+No build step. No npm install. No configuration files. Just content.
+
+---
+
+**This page demonstrates FolderWeb's multi-file approach.** Notice how this page is built from multiple files that render in alphanumerical order:
+
+- `00-introduction.md` - Markdown content
+- `01-design-principles.html` - Static HTML
+- `02-technology-stack.php` - Dynamic PHP (shows current date)
+- `03-what-it-is-not.md` - More Markdown
+- `04-get-started.md` - This section
+
+Mix file types freely. They all render together seamlessly!
diff --git a/app/default/content/about/metadata.ini b/app/default/content/about/metadata.ini
new file mode 100644
index 0000000..7e73f4a
--- /dev/null
+++ b/app/default/content/about/metadata.ini
@@ -0,0 +1,3 @@
+title = "About FolderWeb"
+menu = true
+menu_order = 2
diff --git a/app/default/content/about/styles.css b/app/default/content/about/styles.css
new file mode 100644
index 0000000..5dbefaa
--- /dev/null
+++ b/app/default/content/about/styles.css
@@ -0,0 +1,19 @@
+/* Page-specific styles for About page */
+
+article {
+ border-left: 4px solid oklch(0.65 0.15 250);
+ padding-left: 1.5rem;
+}
+
+article h2 {
+ color: oklch(0.50 0.12 250);
+ font-size: 1.8rem;
+}
+
+aside {
+ background-color: oklch(0.95 0.02 250);
+ padding: 1.5rem;
+ border-radius: 0.5rem;
+ margin-top: 2rem;
+ border: 2px solid oklch(0.85 0.05 250);
+}
diff --git a/app/default/content/articles/2025-10-15-markdown-guide/article.md b/app/default/content/articles/2025-10-15-markdown-guide/article.md
new file mode 100644
index 0000000..a3bc6d2
--- /dev/null
+++ b/app/default/content/articles/2025-10-15-markdown-guide/article.md
@@ -0,0 +1,206 @@
+# Markdown Guide
+
+Markdown is a lightweight markup language that's easy to write and read. FolderWeb uses [Parsedown](https://parsedown.org/) to convert your Markdown files into beautiful HTML.
+
+## Headings
+
+Use `#` symbols for headings:
+
+```markdown
+# Heading 1
+## Heading 2
+### Heading 3
+#### Heading 4
+##### Heading 5
+###### Heading 6
+```
+
+## Emphasis
+
+Make text **bold** or *italic*:
+
+```markdown
+*italic text* or _italic text_
+**bold text** or __bold text__
+***bold and italic*** or ___bold and italic___
+```
+
+## Lists
+
+### Unordered Lists
+
+```markdown
+- Item one
+- Item two
+- Item three
+ - Nested item
+ - Another nested item
+```
+
+### Ordered Lists
+
+```markdown
+1. First item
+2. Second item
+3. Third item
+ 1. Nested item
+ 2. Another nested item
+```
+
+## Links
+
+```markdown
+[Link text](https://example.com)
+[Link with title](https://example.com "Title text")
+```
+
+Example: [Visit FolderWeb](#)
+
+## Images
+
+```markdown
+
+
+```
+
+## Code
+
+### Inline Code
+
+Use backticks for `inline code`:
+
+```markdown
+Use the `$variable` in your code
+```
+
+### Code Blocks
+
+Use triple backticks for code blocks:
+
+````markdown
+```php
+
+```
+````
+
+Renders as:
+
+```php
+
+```
+
+## Blockquotes
+
+```markdown
+> This is a blockquote.
+> It can span multiple lines.
+>
+> And multiple paragraphs.
+```
+
+Result:
+
+> This is a blockquote.
+> It can span multiple lines.
+
+## Horizontal Rules
+
+Create a horizontal rule with three or more hyphens, asterisks, or underscores:
+
+```markdown
+---
+***
+___
+```
+
+---
+
+## Tables
+
+```markdown
+| Header 1 | Header 2 | Header 3 |
+|----------|----------|----------|
+| Cell 1 | Cell 2 | Cell 3 |
+| Cell 4 | Cell 5 | Cell 6 |
+```
+
+Result:
+
+| Header 1 | Header 2 | Header 3 |
+|----------|----------|----------|
+| Cell 1 | Cell 2 | Cell 3 |
+| Cell 4 | Cell 5 | Cell 6 |
+
+## Best Practices
+
+### Use Semantic Structure
+
+Start with `# H1` for your page title, then use `## H2`, `### H3`, etc. for sections.
+
+### Write Readable Markdown
+
+```markdown
+# Good Example
+
+This paragraph is easy to read with proper spacing.
+
+## Section Heading
+
+- List items are clear
+- Each on its own line
+
+---
+
+# Bad Example
+No spacing makes it hard to read.
+##SectionWithoutSpace
+-ListItemsSmashed-Together
+```
+
+### Links in FolderWeb
+
+Internal links work best with absolute paths:
+
+```markdown
+[About page](/about/)
+[Articles](/articles/)
+[Specific article](/articles/2025-10-15-markdown-guide/)
+```
+
+## Advanced Features
+
+### HTML in Markdown
+
+You can use HTML directly in Markdown when needed:
+
+```markdown
+
+ Custom HTML content
+
+```
+
+### Escaping Characters
+
+Use backslash to escape Markdown characters:
+
+```markdown
+\*This text is not italic\*
+\[This is not a link\]
+```
+
+## Tips for FolderWeb
+
+1. **Use descriptive filenames** - `article.md` is better than `content.md`
+2. **Add metadata** - Use `metadata.ini` for titles, dates, and summaries
+3. **Include images** - Place images in the same directory as your content
+4. **Add cover images** - Use `cover.jpg` for list view thumbnails
+
+## Further Reading
+
+- [Markdown Guide](https://www.markdownguide.org/) - Comprehensive Markdown reference
+- [Parsedown Documentation](https://parsedown.org/) - The parser FolderWeb uses
+- [CommonMark Spec](https://commonmark.org/) - Markdown specification
diff --git a/app/default/content/articles/2025-10-15-markdown-guide/metadata.ini b/app/default/content/articles/2025-10-15-markdown-guide/metadata.ini
new file mode 100644
index 0000000..053268d
--- /dev/null
+++ b/app/default/content/articles/2025-10-15-markdown-guide/metadata.ini
@@ -0,0 +1,3 @@
+title = "Markdown Guide"
+date = "2025-10-15"
+summary = "Master Markdown syntax for beautiful, semantic content in FolderWeb."
diff --git a/app/default/content/articles/2025-10-28-templates-and-customization/article.md b/app/default/content/articles/2025-10-28-templates-and-customization/article.md
new file mode 100644
index 0000000..16c1d0c
--- /dev/null
+++ b/app/default/content/articles/2025-10-28-templates-and-customization/article.md
@@ -0,0 +1,165 @@
+# Templates and Customization
+
+FolderWeb is built on a simple principle: **never modify defaults, always override**. This guide shows you how to customize your site while keeping it maintainable.
+
+## The Override System
+
+FolderWeb checks for custom files before falling back to defaults:
+
+1. Check `/custom/templates/` β Use custom template
+2. Fall back to `/app/default/templates/` β Use default template
+
+This means you can override any part of the system without touching the core files.
+
+## Available Templates
+
+### Base Template
+The main HTML structure with header, navigation, and footer.
+
+**Override**: `/custom/templates/base.php`
+
+### Page Template
+Wraps single pages and articles.
+
+**Override**: `/custom/templates/page.php`
+
+### List Templates
+
+FolderWeb includes multiple list view variants:
+
+- `list.php` - Simple list
+- `list-grid.php` - Grid layout
+- `list-card-grid.php` - Card grid with images
+- `list-faq.php` - Expandable FAQ format
+
+**Select via metadata**:
+
+```ini
+page_template = "list-card-grid"
+```
+
+## Customizing Styles
+
+### Add Your Own CSS
+
+Create `/custom/styles/base.css` and it automatically overrides default styles.
+
+Example custom stylesheet:
+
+```css
+:root {
+ --color-primary: oklch(0.5 0.2 270);
+ --color-background: oklch(0.98 0 0);
+ --font-body: 'Georgia', serif;
+}
+
+article h1 {
+ color: var(--color-primary);
+ font-size: clamp(2rem, 5vw, 3rem);
+}
+```
+
+### Modern CSS Features
+
+FolderWeb's default styles use modern CSS:
+
+- **CSS Nesting** - Scope styles naturally
+- **OKLCH Colors** - Perceptually uniform colors
+- **CSS Grid** - Flexible layouts
+- **Clamp()** - Responsive sizing
+- **Logical Properties** - Better internationalization
+
+## Custom Fonts
+
+1. Place font files in `/custom/fonts/`
+2. Reference them in your custom CSS:
+
+```css
+@font-face {
+ font-family: 'MyFont';
+ src: url('/fonts/myfont.woff2') format('woff2');
+}
+
+body {
+ font-family: 'MyFont', sans-serif;
+}
+```
+
+## Metadata Options
+
+Control content behavior with `metadata.ini` files:
+
+```ini
+; Basic fields
+title = "Page Title"
+date = "2025-10-28"
+summary = "Short description"
+
+; Navigation
+menu = true
+menu_order = 1
+
+; Templates
+page_template = "list-card-grid"
+
+; Redirects
+redirect = "https://example.com"
+
+; Attachments
+pdf = "document.pdf"
+```
+
+## Template Variables
+
+Templates have access to specific variables:
+
+### Base Template
+- `$content` - Page content
+- `$currentLang` - Current language code
+- `$navigation` - Navigation items array
+- `$pageTitle` - Page title
+
+### Page Template
+- `$content` - Article content
+- `$pageMetadata` - Metadata array
+- `$translations` - Translation strings
+
+### List Templates
+- `$items` - Array of subitems
+- `$metadata` - Directory metadata
+- `$pageContent` - Intro text
+- `$translations` - Translation strings
+
+## Creating a Custom Template
+
+Example custom page template:
+
+```php
+
+
+
+
+
+
+ = $content ?>
+
+
+
+```
+
+## Best Practices
+
+1. **Never modify `/app/default/`** - Always create overrides in `/custom/`
+2. **Use metadata** - Keep configuration in `metadata.ini` files
+3. **Leverage CSS variables** - Easy theming without rewriting styles
+4. **Keep it simple** - The less custom code, the easier to maintain
+
+## Next Steps
+
+- Explore default templates in `/app/default/templates/`
+- Study the default CSS in `/app/default/styles/base.css`
+- Check out the [Markdown Guide](/articles/2025-10-15-markdown-guide/) for content formatting
diff --git a/app/default/content/articles/2025-10-28-templates-and-customization/metadata.ini b/app/default/content/articles/2025-10-28-templates-and-customization/metadata.ini
new file mode 100644
index 0000000..b69d0a7
--- /dev/null
+++ b/app/default/content/articles/2025-10-28-templates-and-customization/metadata.ini
@@ -0,0 +1,3 @@
+title = "Templates and Customization"
+date = "2025-10-28"
+summary = "Customize your FolderWeb site with templates, styles, and metadata options."
diff --git a/app/default/content/articles/2025-11-01-getting-started/article.md b/app/default/content/articles/2025-11-01-getting-started/article.md
new file mode 100644
index 0000000..8bc1e00
--- /dev/null
+++ b/app/default/content/articles/2025-11-01-getting-started/article.md
@@ -0,0 +1,79 @@
+# Getting Started with FolderWeb
+
+FolderWeb is designed to be the simplest way to publish content on the web. This guide will walk you through the core concepts and get you publishing in minutes.
+
+## Installation
+
+FolderWeb requires PHP 8.4+ and Apache with `mod_rewrite` enabled.
+
+### Using Docker (Recommended for Development)
+
+```bash
+cd development
+docker compose up
+```
+
+Visit `http://localhost:8080` to see your site.
+
+### Manual Installation
+
+1. Point Apache's document root to the `/content` directory
+2. Ensure the `/app` directory is accessible at the same level
+3. Enable `mod_rewrite` in Apache
+4. That's it!
+
+## Creating Your First Page
+
+The easiest way to understand FolderWeb is to create some content.
+
+### Create a Simple Page
+
+1. Create a new directory: `/content/hello/`
+2. Add a file: `/content/hello/page.md`
+3. Write some Markdown:
+
+```markdown
+# Hello World
+
+This is my first page in FolderWeb!
+```
+
+Your page is now live at `/hello/`
+
+### Create an Article with Metadata
+
+For richer content, add metadata:
+
+1. Create: `/content/articles/2025-11-01-my-article/`
+2. Add metadata: `/content/articles/2025-11-01-my-article/metadata.ini`
+
+```ini
+title = "My First Article"
+date = "2025-11-01"
+summary = "A brief description of my article"
+```
+
+3. Add content: `/content/articles/2025-11-01-my-article/article.md`
+
+The date in the folder name is automatically extracted and displayed.
+
+## File Types
+
+FolderWeb supports three content types:
+
+- **Markdown (`.md`)** - Write in Markdown, rendered as HTML
+- **HTML (`.html`)** - Pure HTML for complete control
+- **PHP (`.php`)** - Dynamic content when needed
+
+## File Naming Conventions
+
+- **Page content**: `page.md`, `page.html`, `page.php`
+- **Articles/posts**: `article.md`, `post.md`, `single.md` (and `.html`/`.php` variants)
+- **Frontpage**: `/content/frontpage.php`
+- **Index override**: `index.php` in any directory takes precedence
+
+## Next Steps
+
+- Read the [Templates Guide](/articles/2025-10-28-templates-and-customization/) to customize your site
+- Learn [Markdown syntax](/articles/2025-10-15-markdown-guide/) for better content
+- Explore the default templates in `/app/default/templates/`
diff --git a/app/default/content/articles/2025-11-01-getting-started/metadata.ini b/app/default/content/articles/2025-11-01-getting-started/metadata.ini
new file mode 100644
index 0000000..977942b
--- /dev/null
+++ b/app/default/content/articles/2025-11-01-getting-started/metadata.ini
@@ -0,0 +1,3 @@
+title = "Getting Started with FolderWeb"
+date = "2025-11-01"
+summary = "Learn the basics of FolderWeb and create your first content in minutes."
diff --git a/app/default/content/articles/2025-11-02-multi-file-content/00-introduction.md b/app/default/content/articles/2025-11-02-multi-file-content/00-introduction.md
new file mode 100644
index 0000000..bf15bdf
--- /dev/null
+++ b/app/default/content/articles/2025-11-02-multi-file-content/00-introduction.md
@@ -0,0 +1,14 @@
+# Multi-File Content Pages
+
+One of FolderWeb's most powerful features is the ability to compose a single page from multiple content files. This gives you flexibility in how you organize and author your content.
+
+## How It Works
+
+When a folder contains **no subdirectories**, FolderWeb treats it as a **page-type folder**. All `.md`, `.html`, and `.php` files in that folder are rendered in **alphanumerical order**.
+
+This means you can:
+
+- Break long content into manageable sections
+- Mix file formats freely (Markdown, HTML, PHP)
+- Reorder sections by renaming files
+- Include dynamic PHP content alongside static content
diff --git a/app/default/content/articles/2025-11-02-multi-file-content/01-examples.md b/app/default/content/articles/2025-11-02-multi-file-content/01-examples.md
new file mode 100644
index 0000000..5633aa1
--- /dev/null
+++ b/app/default/content/articles/2025-11-02-multi-file-content/01-examples.md
@@ -0,0 +1,24 @@
+## File Naming Examples
+
+Here are some example naming patterns:
+
+```
+/my-page/
+ 00-introduction.md
+ 01-getting-started.md
+ 02-advanced-topics.html
+ 03-conclusion.php
+```
+
+Files render in this order:
+1. `00-introduction.md`
+2. `01-getting-started.md`
+3. `02-advanced-topics.html`
+4. `03-conclusion.php`
+
+## Folder Types
+
+FolderWeb automatically determines folder type:
+
+- **Page-type folder**: No subdirectories β Renders all content files as a single page
+- **Article-type folder**: Has subdirectories β Shows list view with links to subdirectories
diff --git a/app/default/content/articles/2025-11-02-multi-file-content/02-use-cases.html b/app/default/content/articles/2025-11-02-multi-file-content/02-use-cases.html
new file mode 100644
index 0000000..547c1ab
--- /dev/null
+++ b/app/default/content/articles/2025-11-02-multi-file-content/02-use-cases.html
@@ -0,0 +1,15 @@
+
+
Use Cases
+
+
Long Documentation
+
Break lengthy documentation into logical sections. Each section gets its own file, making editing and maintenance easier.
+
+
Mixed Content Types
+
Use Markdown for simple text, HTML for complex layouts, and PHP for dynamic contentβall on the same page.
+
+
Collaborative Editing
+
Multiple authors can work on different sections simultaneously without merge conflicts.
+
+
Progressive Enhancement
+
Start with simple Markdown files. Later, enhance specific sections with HTML or PHP without restructuring.
+
+ = htmlspecialchars($translations['read_more'] ?? 'Read more') ?>
+
+
+
+
+
diff --git a/app/default/templates/page.php b/app/default/templates/page.php
index a511e6f..6ed654c 100644
--- a/app/default/templates/page.php
+++ b/app/default/templates/page.php
@@ -1,3 +1,25 @@
-
- = $content ?>
-
+= $content ?>
+
+
+
+
diff --git a/app/docs/language-plugin.md b/app/docs/language-plugin.md
index a8f2fbc..a07492c 100644
--- a/app/docs/language-plugin.md
+++ b/app/docs/language-plugin.md
@@ -490,3 +490,5 @@ content/
## See Also
- [Plugin System Reference](plugin-system.md)
+- [How to Create Multi-Language Sites](../../docs/how-to/multi-language.md)
+- [Configuration Reference](../../docs/reference/configuration.md)
diff --git a/app/plugins/global/languages.php b/app/plugins/global/languages.php
index 8f14978..588a956 100644
--- a/app/plugins/global/languages.php
+++ b/app/plugins/global/languages.php
@@ -46,10 +46,7 @@ Hooks::add(Hook::PROCESS_CONTENT, function(mixed $data, string $dirOrType, strin
// Filter content files by language variant
if (is_array($data) && !empty($data) && isset($data[0]['path'])) {
- error_log("filterFilesByLanguage called with " . count($data) . " files, current lang: $currentLang");
- $filtered = filterFilesByLanguage($data, $dirOrType, $ctx);
- error_log("Filtered to " . count($filtered) . " files");
- return $filtered;
+ return filterFilesByLanguage($data, $dirOrType, $ctx);
}
return $data;
diff --git a/app/router.php b/app/router.php
index 199b9ac..ea17ebc 100644
--- a/app/router.php
+++ b/app/router.php
@@ -24,34 +24,6 @@ if (file_exists($assetPath) && is_file($assetPath)) {
exit;
}
-// Check for assets in content directory (CSS, images, etc.)
-$contentAssetPath = $ctx->contentDir . '/' . $ctx->requestPath;
-if (file_exists($contentAssetPath) && is_file($contentAssetPath)) {
- $ext = pathinfo($contentAssetPath, PATHINFO_EXTENSION);
- // Define MIME types for asset files
- $mimeTypes = [
- 'css' => 'text/css',
- 'jpg' => 'image/jpeg',
- 'jpeg' => 'image/jpeg',
- 'png' => 'image/png',
- 'gif' => 'image/gif',
- 'webp' => 'image/webp',
- 'svg' => 'image/svg+xml',
- 'pdf' => 'application/pdf',
- 'woff' => 'font/woff',
- 'woff2' => 'font/woff2',
- 'ttf' => 'font/ttf',
- 'otf' => 'font/otf',
- ];
-
- $extLower = strtolower($ext);
- if (isset($mimeTypes[$extLower])) {
- header('Content-Type: ' . $mimeTypes[$extLower]);
- readfile($contentAssetPath);
- exit;
- }
-}
-
// Handle frontpage
if (empty($ctx->requestPath)) {
$contentFiles = findAllContentFiles($ctx->contentDir);
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..292e66b
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,211 @@
+# FolderWeb Documentation
+
+Welcome to the FolderWeb documentation! This comprehensive guide covers everything you need to know about building and maintaining websites with FolderWeb.
+
+## π Documentation Organization
+
+This documentation follows the [Diataxis framework](https://diataxis.fr/), organizing content into four distinct types to help you find exactly what you need:
+
+### π Tutorial (Learning-Oriented)
+
+**Purpose**: Learn by doing
+**For**: Newcomers to FolderWeb
+
+- **[Getting Started](tutorial/00-getting-started.md)** - Build your first FolderWeb site from scratch in 10 minutes
+
+Start here if you're new to FolderWeb. This hands-on tutorial walks you through creating a complete website with pages, blog posts, and custom styling.
+
+### π How-To Guides (Task-Oriented)
+
+**Purpose**: Solve specific problems
+**For**: Users with a specific goal
+
+- **[Custom Templates](how-to/custom-templates.md)** - Override default templates with your own designs
+- **[Custom Styles](how-to/custom-styles.md)** - Customize appearance using CSS
+- **[Multi-Language Sites](how-to/multi-language.md)** - Set up and manage multiple languages
+- **[Working with Metadata](how-to/working-with-metadata.md)** - Control content with metadata.ini files
+
+Use these guides when you know what you want to accomplish and need step-by-step instructions.
+
+### π Reference (Information-Oriented)
+
+**Purpose**: Look up technical details
+**For**: Users who need precise information
+
+- **[File Structure](reference/file-structure.md)** - Complete directory layout and file conventions
+- **[Metadata](reference/metadata.md)** - All available metadata fields and their usage
+- **[Templates](reference/templates.md)** - Template types and available variables
+- **[Configuration](reference/configuration.md)** - Configuration options and format
+- **[CSS Variables](reference/css-variables.md)** - All CSS custom properties for styling
+
+Consult these documents when you need to look up specific technical details or API information.
+
+### π‘ Explanation (Understanding-Oriented)
+
+**Purpose**: Understand concepts and design decisions
+**For**: Users who want to understand the "why"
+
+- **[Philosophy](explanation/philosophy.md)** - Design principles and thinking behind FolderWeb
+- **[Architecture](explanation/architecture.md)** - How FolderWeb works under the hood
+
+Read these to gain deeper understanding of FolderWeb's design and architecture.
+
+## π Quick Start
+
+```bash
+# 1. Create project directory
+mkdir my-website && cd my-website
+
+# 2. Copy framework files
+cp -r /path/to/folderweb/app ./app
+
+# 3. Create your first page
+mkdir content
+echo "# Welcome" > content/index.md
+
+# 4. Start development server
+php -S localhost:8000 -t . app/router.php
+
+# 5. Open http://localhost:8000
+```
+
+**Next**: Follow the complete [Getting Started Tutorial](tutorial/00-getting-started.md)
+
+## π― Common Tasks
+
+Quick links to frequently needed guides:
+
+| Task | Guide |
+|------|-------|
+| Create a custom template | [Custom Templates](how-to/custom-templates.md) |
+| Change colors and fonts | [Custom Styles](how-to/custom-styles.md) |
+| Add multiple languages | [Multi-Language Sites](how-to/multi-language.md) |
+| Configure page metadata | [Working with Metadata](how-to/working-with-metadata.md) |
+| Look up all metadata fields | [Metadata Reference](reference/metadata.md) |
+| Find template variables | [Templates Reference](reference/templates.md) |
+| Understand file organization | [File Structure Reference](reference/file-structure.md) |
+
+## π‘ Key Concepts
+
+- **File-based routing**: Your folder structure defines your URL structure
+- **Template fallback**: Custom templates automatically override defaults
+- **Content types**: Single-file pages, multi-file pages, or list views
+- **Language support**: Built-in multi-language with URL prefixes
+- **Metadata control**: Configure behavior with simple INI files
+- **No build process**: Save and refresh - see changes immediately
+
+## π Requirements
+
+- **PHP**: 8.4 or higher
+- **Web server**: Apache, Nginx, or PHP's built-in server
+- **Extensions**: Standard PHP (no special extensions required)
+
+## ποΈ Documentation Files
+
+### Complete File List
+
+```
+docs/
+βββ README.md # This file
+βββ index.md # Documentation homepage
+β
+βββ tutorial/
+β βββ 00-getting-started.md # Step-by-step tutorial
+β
+βββ how-to/
+β βββ custom-templates.md # Override templates
+β βββ custom-styles.md # Customize CSS
+β βββ multi-language.md # Multi-language setup
+β βββ working-with-metadata.md # Metadata usage
+β
+βββ reference/
+β βββ file-structure.md # Directory layout
+β βββ metadata.md # Metadata fields
+β βββ templates.md # Template reference
+β βββ configuration.md # Config options
+β βββ css-variables.md # CSS customization
+β
+βββ explanation/
+ βββ philosophy.md # Design principles
+ βββ architecture.md # Technical architecture
+```
+
+## π Reading Paths
+
+Choose your path based on your needs:
+
+### Path 1: Complete Beginner
+
+1. [Getting Started Tutorial](tutorial/00-getting-started.md)
+2. [Custom Styles](how-to/custom-styles.md)
+3. [Working with Metadata](how-to/working-with-metadata.md)
+4. [Philosophy](explanation/philosophy.md)
+
+### Path 2: Experienced Developer
+
+1. [Philosophy](explanation/philosophy.md)
+2. [Architecture](explanation/architecture.md)
+3. [File Structure Reference](reference/file-structure.md)
+4. Browse How-To Guides as needed
+
+### Path 3: Specific Task
+
+1. Find your task in [How-To Guides](how-to/)
+2. Consult [Reference](reference/) for details
+3. Return to task completion
+
+## π€ Getting Help
+
+### Documentation Not Enough?
+
+1. **Check the code**: FolderWeb is deliberately simple - reading the source is encouraged
+2. **Review examples**: Look at the demo content in `/app/default/content/`
+3. **Test locally**: Experiment with a test site to understand behavior
+
+### Common Issues
+
+| Problem | Solution |
+|---------|----------|
+| Styles not loading | Hard refresh browser (Ctrl+Shift+R) |
+| 404 errors | Verify folder exists with content files |
+| Language not working | Check `available` in config.ini |
+| Metadata not showing | Validate INI syntax with PHP parser |
+| Custom template ignored | Ensure file is in `/custom/templates/` |
+
+## π Philosophy Highlights
+
+FolderWeb embraces:
+
+- **Simplicity**: Just enough, nothing more
+- **Longevity**: Works today, works in 2035
+- **Transparency**: Readable code, clear behavior
+- **Files**: Your content, fully portable
+- **No build**: Save and refresh workflow
+
+Read the complete [Philosophy](explanation/philosophy.md) to understand FolderWeb's design principles.
+
+## π Contributing to Documentation
+
+Documentation improvements are welcome:
+
+- Fix typos or unclear explanations
+- Add missing examples
+- Improve existing guides
+- Suggest new how-to guides
+
+Keep documentation:
+- Clear and concise
+- Accurate and tested
+- Organized according to Diataxis principles
+
+## π External Resources
+
+- [Diataxis Framework](https://diataxis.fr/) - Documentation organization system
+- [PHP 8.4 Documentation](https://www.php.net/manual/en/) - PHP reference
+- [Markdown Guide](https://www.markdownguide.org/) - Markdown syntax
+- [MDN Web Docs](https://developer.mozilla.org/) - HTML and CSS reference
+
+---
+
+**Start here**: [Getting Started Tutorial](tutorial/00-getting-started.md)
+**Main index**: [Documentation Index](index.md)
diff --git a/docs/explanation/architecture.md b/docs/explanation/architecture.md
new file mode 100644
index 0000000..08809d8
--- /dev/null
+++ b/docs/explanation/architecture.md
@@ -0,0 +1,739 @@
+# Architecture
+
+Understanding how FolderWeb works under the hood.
+
+## High-Level Overview
+
+FolderWeb follows a simple request-response flow:
+
+```
+HTTP Request
+ β
+router.php (entry point)
+ β
+Parse request path
+ β
+Find content files
+ β
+Determine content type (page/list/file)
+ β
+Render content
+ β
+Wrap in templates
+ β
+HTTP Response
+```
+
+## Core Components
+
+### 1. Router (`app/router.php`)
+
+**Purpose**: Entry point for all requests, determines what to serve
+
+**Responsibilities**:
+- Receive HTTP requests
+- Check for root-level assets (`/custom/assets/`)
+- Parse request path
+- Dispatch to appropriate renderer
+- Handle redirects (trailing slashes)
+- Serve 404 for missing content
+
+**Key Flow**:
+```php
+// 1. Check for root-level assets
+if (file_exists("/custom/assets/$path")) {
+ serve_static_file();
+}
+
+// 2. Empty path = home page (render all root content files)
+if (empty($path)) {
+ render_all_files_in_root();
+}
+
+// 3. Parse request path
+$result = parseRequestPath($ctx);
+
+// 4. Handle based on type
+match($result['type']) {
+ 'page' => renderMultipleFiles(...),
+ 'file' => renderFile(...),
+ 'directory' => renderListView(...),
+ 'not_found' => show_404()
+};
+```
+
+**Location**: `/app/router.php` (lines 1-100+)
+
+### 2. Content Discovery (`app/content.php`)
+
+**Purpose**: Find and parse content files and directories
+
+**Key Functions**:
+
+#### `parseRequestPath($ctx)`
+Analyzes request path and determines content type.
+
+**Returns**:
+```php
+[
+ 'type' => 'page' | 'file' | 'directory' | 'not_found',
+ 'path' => '/full/system/path',
+ 'files' => [...], // For page type
+ // ... other data
+]
+```
+
+**Logic**:
+1. Resolve translated slugs to real paths
+2. Check if path exists
+3. If directory:
+ - Has subdirectories? β `type: 'directory'` (list view)
+ - Has content files only? β `type: 'page'` (multi-file)
+4. If matches file? β `type: 'file'`
+5. Otherwise β `type: 'not_found'`
+
+#### `findAllContentFiles($dir, $lang, $defaultLang, $availableLangs)`
+Scans directory for content files.
+
+**Process**:
+1. Read directory contents
+2. Filter for valid extensions (`.md`, `.html`, `.php`)
+3. Parse filenames for language suffix
+4. Filter by current language:
+ - Show `.{lang}.ext` files for that language
+ - Show default files (no suffix) only if no language variant
+5. Sort alphanumerically
+6. Return array of file paths
+
+**Example**:
+```php
+// Directory contains:
+// - index.md
+// - index.no.md
+// - about.md
+
+// English request (lang=en, default=en):
+findAllContentFiles() β ['index.md', 'about.md']
+
+// Norwegian request (lang=no):
+findAllContentFiles() β ['index.no.md', 'about.md']
+```
+
+#### `loadMetadata($dirPath, $lang, $defaultLang)`
+Loads and merges metadata for a directory.
+
+**Process**:
+1. Check for `metadata.ini` in directory
+2. Parse INI file with sections
+3. Start with base values
+4. Override with language-specific section if exists
+5. Return merged array
+
+**Example**:
+```ini
+title = "About"
+summary = "Learn about us"
+
+[no]
+title = "Om"
+summary = "Lær om oss"
+```
+
+For Norwegian request:
+```php
+loadMetadata(..., 'no', 'en') β [
+ 'title' => 'Om', // Overridden
+ 'summary' => 'Lær om oss' // Overridden
+]
+```
+
+#### `resolveTranslatedPath($ctx, $requestPath)`
+Maps translated slugs back to real directory names.
+
+**Example**:
+```ini
+; In content/about/metadata.ini:
+[no]
+slug = "om-oss"
+```
+
+Request to `/no/om-oss/` resolves to `content/about/`.
+
+**Process**:
+1. Split path into segments
+2. For each segment:
+ - Load metadata of parent directory
+ - Check if any subdirectory has matching translated slug
+ - Replace segment with real directory name
+3. Return resolved path
+
+### 3. Rendering Engine (`app/rendering.php`)
+
+**Purpose**: Convert content to HTML and wrap in templates
+
+**Key Functions**:
+
+#### `renderContentFile($filePath)`
+Converts a single content file to HTML.
+
+**Process**:
+```php
+switch (extension) {
+ case 'md':
+ return Parsedown->text(file_contents);
+ case 'html':
+ return file_contents;
+ case 'php':
+ ob_start();
+ include $filePath; // $ctx available
+ return ob_get_clean();
+}
+```
+
+#### `renderFile($ctx, $filePath)`
+Renders single file wrapped in templates.
+
+**Process**:
+1. Convert file to HTML
+2. Load metadata
+3. Wrap in page template
+4. Wrap in base template
+5. Return HTML
+
+#### `renderMultipleFiles($ctx, $filePaths, $pageDir)`
+Renders multiple files as single page.
+
+**Process**:
+1. Convert each file to HTML
+2. Concatenate HTML (in order)
+3. Load metadata
+4. Wrap in page template
+5. Wrap in base template
+6. Return HTML
+
+**Used for**: Multi-file pages (documentation, long articles)
+
+#### `renderTemplate($ctx, $content, $statusCode = 200)`
+Wraps content in base template.
+
+**Process**:
+1. Extract variables for template
+2. Set HTTP status code
+3. Include base template
+4. Return HTML
+
+**Variables provided**:
+- `$content` - Rendered HTML
+- `$ctx` - Context object
+- `$currentLang`, `$navigation`, `$homeLabel`, etc.
+
+### 4. Context Object (`app/context.php`)
+
+**Purpose**: Immutable request context with computed properties
+
+**Implementation**:
+```php
+readonly class Context {
+ public function __construct(
+ public private(set) string $contentDir,
+ public private(set) string $currentLang,
+ // ... other properties
+ ) {}
+
+ // Computed property (PHP 8.4 hook)
+ public string $langPrefix {
+ get => $this->currentLang !== $this->defaultLang
+ ? "/{$this->currentLang}"
+ : '';
+ }
+
+ // Lazy-loaded computed property
+ public array $navigation {
+ get => buildNavigation($this);
+ }
+}
+```
+
+**Benefits**:
+- **Immutability**: Cannot be changed after creation
+- **Type safety**: All properties typed
+- **Computed values**: Calculated on-demand
+- **No globals**: Passed explicitly
+
+**Creation**:
+```php
+$ctx = createContext();
+```
+
+This function:
+1. Loads configuration
+2. Extracts language from URL
+3. Determines content directory
+4. Resolves template paths
+5. Returns readonly Context object
+
+### 5. Configuration (`app/config.php`)
+
+**Purpose**: Load and merge configuration
+
+**Process**:
+1. Parse `/app/config.ini` (defaults)
+2. Parse `/custom/config.ini` if exists
+3. Merge arrays (custom overrides defaults)
+4. Extract language settings
+5. Validate configuration
+
+**Configuration Used**:
+```ini
+[languages]
+default = "en"
+available = "en,no,fr"
+```
+
+### 6. Helper Functions (`app/helpers.php`)
+
+**Purpose**: Utility functions used throughout
+
+**Key Helpers**:
+
+| Function | Purpose |
+|----------|---------|
+| `resolveTemplate($name, $type)` | Find custom or default template |
+| `getSubdirectories($dir)` | List subdirectories only |
+| `extractTitle($filePath, $lang, $defaultLang)` | Extract H1 from content |
+| `formatNorwegianDate($date)` | Format date as "2. november 2025" |
+| `extractDateFromFolder($name)` | Parse date from folder name |
+| `findCoverImage($dir)` | Locate cover image |
+| `findPdfFile($dir)` | Find first PDF |
+
+### 7. Static File Server (`app/static.php`)
+
+**Purpose**: Serve CSS, fonts, and other static assets
+
+**Process**:
+1. Validate path (prevent directory traversal)
+2. Resolve real path
+3. Check file exists and is readable
+4. Determine MIME type
+5. Set headers
+6. Output file contents
+
+**Routes**:
+- `/app/styles/base.css` β Custom or default CSS
+- `/app/default-styles/base.css` β Default CSS
+- `/custom/fonts/*` β Custom fonts
+
+## Data Flow
+
+### Request Flow Diagram
+
+```
+1. HTTP Request: /blog/2025-11-02-post/
+ β
+2. router.php receives request
+ β
+3. createContext()
+ ββ Load config
+ ββ Extract language from URL
+ ββ Determine content directory
+ ββ Return Context object
+ β
+4. parseRequestPath($ctx)
+ ββ resolveTranslatedPath() - map slug to real path
+ ββ Check path exists
+ ββ findAllContentFiles() - scan for content
+ ββ Return ['type' => 'file', 'path' => '...']
+ β
+5. renderFile($ctx, $filePath)
+ ββ renderContentFile() - convert to HTML
+ ββ loadMetadata() - get metadata
+ ββ Apply page template
+ ββ Apply base template
+ β
+6. HTTP Response: HTML
+```
+
+### List View Flow
+
+```
+1. Request: /blog/
+ β
+2. parseRequestPath() β type: 'directory'
+ β
+3. Load directory metadata
+ ββ Get page_template setting
+ ββ Get other directory metadata
+ β
+4. getSubdirectories() - find all subdirs
+ β
+5. For each subdirectory:
+ ββ loadMetadata() - get title, date, summary
+ ββ findCoverImage() - locate cover
+ ββ findPdfFile() - locate PDF
+ ββ Build item array
+ β
+6. Render list template with $items
+ β
+7. Wrap in base template
+ β
+8. Return HTML
+```
+
+## File Organization
+
+### Separation of Concerns
+
+```
+app/
+βββ router.php # Entry point, request handling
+βββ content.php # Content discovery, parsing
+βββ rendering.php # HTML generation, templates
+βββ context.php # Request context
+βββ config.php # Configuration loading
+βββ helpers.php # Utility functions
+βββ constants.php # Constants (extensions)
+βββ static.php # Static file serving
+```
+
+Each file has a single responsibility.
+
+### Template Resolution
+
+Templates use fallback chain:
+
+```
+1. /custom/templates/{name}.php
+ β (if not found)
+2. /app/default/templates/{name}.php
+```
+
+**Implementation**:
+```php
+function resolveTemplate($name, $type = 'templates') {
+ $custom = __DIR__ . "/../custom/$type/$name";
+ $default = __DIR__ . "/default/$type/$name";
+ return file_exists($custom) ? $custom : $default;
+}
+```
+
+This pattern applies to:
+- Templates
+- Styles
+- Languages
+- Any overridable resource
+
+## Language Handling
+
+### URL Structure
+
+```
+/ β Default language
+/no/ β Norwegian
+/fr/page/ β French page
+```
+
+### Language Extraction
+
+From URL path:
+```php
+// Request: /no/blog/post/
+$segments = explode('/', trim($path, '/'));
+$firstSegment = $segments[0] ?? '';
+
+if (in_array($firstSegment, $availableLangs)) {
+ $currentLang = $firstSegment;
+ $pathWithoutLang = implode('/', array_slice($segments, 1));
+} else {
+ $currentLang = $defaultLang;
+ $pathWithoutLang = $path;
+}
+```
+
+### Content Filtering
+
+Files with language suffixes (`.{lang}.ext`) are filtered:
+
+```php
+// Parse filename
+$parts = explode('.', $filename);
+$lastPart = $parts[count($parts) - 2] ?? null;
+
+// Check if second-to-last part is a language
+if (in_array($lastPart, $availableLangs)) {
+ $fileLang = $lastPart;
+} else {
+ $fileLang = $defaultLang;
+}
+
+// Include file if:
+// - It matches current language, OR
+// - It's default language AND no specific variant exists
+```
+
+## Navigation Building
+
+### Process
+
+```php
+function buildNavigation($ctx) {
+ $items = [];
+
+ // 1. Scan content root for directories
+ $dirs = getSubdirectories($ctx->contentDir);
+
+ // 2. For each directory
+ foreach ($dirs as $dir) {
+ // Load metadata
+ $metadata = loadMetadata($dir, $ctx->currentLang, $ctx->defaultLang);
+
+ // Skip if menu = false
+ if (!($metadata['menu'] ?? false)) continue;
+
+ // Build item
+ $items[] = [
+ 'title' => $metadata['title'] ?? basename($dir),
+ 'url' => $ctx->langPrefix . '/' . basename($dir) . '/',
+ 'order' => $metadata['menu_order'] ?? 999
+ ];
+ }
+
+ // 3. Sort by menu_order
+ usort($items, fn($a, $b) => $a['order'] <=> $b['order']);
+
+ return $items;
+}
+```
+
+### Caching
+
+Navigation is a computed property, calculated once per request:
+
+```php
+public array $navigation {
+ get => buildNavigation($this);
+}
+```
+
+PHP memoizes the result automatically.
+
+## Performance Characteristics
+
+### Time Complexity
+
+| Operation | Complexity | Notes |
+|-----------|------------|-------|
+| Route resolution | O(1) | Direct file checks |
+| Content file scan | O(n) | n = files in directory |
+| Metadata loading | O(1) | Single file read |
+| Template rendering | O(m) | m = content size |
+| Navigation build | O(d) | d = top-level directories |
+
+### Space Complexity
+
+- **Memory**: O(c) where c = content size
+- **No caching**: Each request independent
+- **Stateless**: No session storage
+
+### Optimization Points
+
+1. **OPcache**: PHP bytecode caching (biggest impact)
+2. **Web server cache**: Serve cached HTML
+3. **Reverse proxy**: Varnish, Cloudflare
+4. **Minimize file reads**: Context created once per request
+
+## Security Architecture
+
+### Path Validation
+
+Multiple layers prevent directory traversal:
+
+```php
+// 1. Remove .. segments
+$path = str_replace('..', '', $path);
+
+// 2. Resolve to real path
+$realPath = realpath($path);
+
+// 3. Ensure within content directory
+if (!str_starts_with($realPath, $contentDir)) {
+ return 404;
+}
+
+// 4. Check readable
+if (!is_readable($realPath)) {
+ return 404;
+}
+```
+
+### Output Escaping
+
+All user-generated content escaped:
+
+```php
+= htmlspecialchars($metadata['title']) ?>
+```
+
+This prevents XSS attacks.
+
+### MIME Type Validation
+
+Static files served with correct MIME types:
+
+```php
+$mimeTypes = [
+ 'css' => 'text/css',
+ 'woff2' => 'font/woff2',
+ 'jpg' => 'image/jpeg',
+ // ...
+];
+
+header('Content-Type: ' . $mimeTypes[$extension]);
+```
+
+## Error Handling
+
+### HTTP Status Codes
+
+- **200 OK**: Successful content render
+- **301 Moved Permanently**: Missing trailing slash
+- **404 Not Found**: Content doesn't exist
+
+### 404 Handling
+
+When content not found:
+
+```php
+renderTemplate($ctx, '
404 Not Found
', 404);
+```
+
+Base template rendered with 404 status.
+
+## Extension Points
+
+### Custom Templates
+
+Override any template:
+
+```php
+// Framework checks:
+$custom = '/custom/templates/list-my-custom.php';
+if (file_exists($custom)) {
+ include $custom;
+} else {
+ include '/app/default/templates/list.php';
+}
+```
+
+### Custom Functions
+
+Add your own in `/custom/functions.php`:
+
+```php
+
+
+# Dynamic Content
+
+Current time: = $currentTime ?>
+
+The language is: = $ctx->currentLang ?>
+```
+
+## Testing Architecture
+
+### Manual Testing
+
+1. Create test content
+2. Start dev server: `php -S localhost:8000 -t . app/router.php`
+3. Visit URLs, verify output
+4. Check different languages
+5. Test edge cases (missing files, invalid paths)
+
+### Automated Testing (Future)
+
+Possible test structure:
+
+```php
+// tests/RouterTest.php
+test('renders home page', function() {
+ $response = request('/');
+ expect($response->status)->toBe(200);
+ expect($response->body)->toContain('
');
+});
+
+test('handles 404', function() {
+ $response = request('/nonexistent/');
+ expect($response->status)->toBe(404);
+});
+```
+
+## Deployment Architecture
+
+### Simple Deployment
+
+```bash
+# 1. Clone repository
+git clone https://github.com/you/your-site
+
+# 2. Point web server to directory
+# Document root: /path/to/site
+# Rewrite all requests to: /app/router.php
+
+# 3. Done
+```
+
+### With Build Step (Optional)
+
+```bash
+# 1. Clone and build
+git clone ...
+cd site
+
+# 2. Process custom styles (optional)
+# E.g., PostCSS, autoprefixer
+
+# 3. Deploy
+rsync -av . server:/var/www/site/
+```
+
+### Zero-Downtime Deployment
+
+```bash
+# 1. Deploy to new directory
+rsync -av . server:/var/www/site-new/
+
+# 2. Symlink switch
+ln -sfn /var/www/site-new /var/www/site-current
+
+# 3. Web server serves from /var/www/site-current
+```
+
+## Related
+
+- [Philosophy](philosophy.md)
+- [Getting Started Tutorial](../tutorial/00-getting-started.md)
+- [File Structure Reference](../reference/file-structure.md)
+- [Template Reference](../reference/templates.md)
diff --git a/docs/explanation/philosophy.md b/docs/explanation/philosophy.md
new file mode 100644
index 0000000..cace2af
--- /dev/null
+++ b/docs/explanation/philosophy.md
@@ -0,0 +1,496 @@
+# Philosophy
+
+Understanding the principles and thinking behind FolderWeb.
+
+## Core Idea
+
+**Your file system is your content management system.**
+
+FolderWeb embraces the simplest possible approach to web publishing: create a folder structure that mirrors your site hierarchy, drop files into folders, and they immediately become pages. No database, no admin panel, no build process.
+
+## Design Principles
+
+### 1. Just Enough, Nothing More
+
+FolderWeb applies minimal PHP to enable modern conveniences while remaining maintainable for years or decades. Every feature must justify its existence by solving a real problem without creating new complexity.
+
+**What this means:**
+- No frameworks that might be abandoned
+- No build tools that need maintenance
+- No package managers introducing dependencies
+- No abstractions unless they provide lasting value
+
+**Example**: Instead of using a routing library, FolderWeb uses PHP's native file functions to map folders to URLs. This will work identically in 2025 and 2035.
+
+### 2. Longevity Over Novelty
+
+Code should outlive trends. FolderWeb prioritizes stability and backward compatibility over cutting-edge features.
+
+**What this means:**
+- Standard PHP (no exotic extensions)
+- Plain HTML and CSS (no JavaScript required)
+- Simple file formats (Markdown, INI)
+- Conventions over configuration
+
+**Why it matters**: A site built today should still work in 10 years without updates. The web's foundational technologies (HTML, CSS, PHP) change slowly and maintain backward compatibility.
+
+### 3. Transparent and Readable
+
+You should be able to open any file and immediately understand what it does. No magic, no hidden behavior.
+
+**What this means:**
+- Sparse, meaningful comments
+- Descriptive function names
+- Simple control flow
+- Minimal abstraction layers
+
+**Example**: Want to know how templates work? Open `app/rendering.php` and read 100 lines of straightforward PHP. No framework documentation needed.
+
+### 4. Files Are Content
+
+Your content lives in plain text files you can edit with any text editor. You own your content completely.
+
+**What this means:**
+- Content is portable (copy files, migrate easily)
+- Version control friendly (Git tracks changes)
+- No lock-in (files work without FolderWeb)
+- Backup-friendly (copy a folder)
+
+**Example**: Your entire site is a folder structure. Zip it, move it to another server, extract it, and it works. No database export/import, no migration scripts.
+
+## What FolderWeb Is
+
+### A File-Based Router
+
+FolderWeb maps your folder structure to URLs:
+```
+content/blog/2025-11-02-post/ β yoursite.com/blog/2025-11-02-post/
+```
+
+That's it. No route definitions, no controllers, no configuration.
+
+### A Content Renderer
+
+FolderWeb converts Markdown to HTML, wraps it in templates, and serves it. Three steps:
+1. Find content files
+2. Convert to HTML
+3. Wrap in template
+
+### A Minimal Template System
+
+FolderWeb provides just enough templating to avoid repetition:
+- Base template for site structure
+- Page template for content wrapper
+- List templates for directory views
+
+All using plain PHP includes. No template language to learn.
+
+### A Convention Framework
+
+FolderWeb establishes conventions that eliminate configuration:
+- `metadata.ini` for structured data
+- `cover.jpg` for images
+- `YYYY-MM-DD-slug` for dates
+- `filename.lang.ext` for translations
+
+Learn the conventions once, apply them everywhere.
+
+## What FolderWeb Is Not
+
+### Not a CMS
+
+No admin panel. Edit files directly with your text editor, commit to Git, deploy.
+
+**Why**: Admin panels add complexity, require maintenance, create security risks, and limit what you can do. Text files are simpler and more powerful.
+
+### Not a Static Site Generator
+
+FolderWeb renders pages on request, not at build time.
+
+**Why**: No build step means immediate feedback. Save a file, refresh your browser, see changes. No waiting for builds, no deployment pipelines required (though you can add them).
+
+### Not a JavaScript Framework
+
+Zero JavaScript in the framework. HTML and CSS only.
+
+**Why**: JavaScript adds complexity, breaks without it, requires builds/transpilation, and changes rapidly. HTML and CSS are stable and sufficient for content sites.
+
+### Not Opinionated About Design
+
+FolderWeb provides minimal default styles. Your design is your own.
+
+**Why**: Design trends change. FolderWeb gives you a clean foundation and gets out of the way. Override everything in `/custom/`.
+
+## Design Decisions Explained
+
+### Why PHP 8.4+?
+
+**Modern features without complexity.**
+
+PHP 8.4 provides:
+- Readonly classes (immutability)
+- Property hooks (computed properties)
+- Arrow functions (concise code)
+- Modern array functions
+- Asymmetric visibility (controlled access)
+
+These features make code clearer without adding dependencies or build steps. PHP 8.4 will be supported for years.
+
+**Tradeoff**: Requires newer PHP, but gains clarity and performance.
+
+### Why No Database?
+
+**Files are simpler.**
+
+Databases add:
+- Setup complexity
+- Backup complexity
+- Migration complexity
+- Performance tuning
+- Additional failure points
+
+For content sites, files provide:
+- Version control integration
+- Simple backups (copy folder)
+- Portability
+- Transparent storage
+- No setup required
+
+**When you might need a database**: User-generated content, real-time updates, complex queries, thousands of pages. For those cases, use a different tool.
+
+### Why INI Files for Metadata?
+
+**Simple, readable, PHP-native.**
+
+INI format:
+- No parsing library needed (built into PHP)
+- Human-readable and editable
+- Supports sections for languages
+- Familiar format
+
+**Alternatives considered**:
+- **YAML**: Requires library, complex syntax
+- **JSON**: Not as human-friendly, no comments
+- **TOML**: Requires library, less familiar
+- **Frontmatter**: Mixes content and metadata
+
+### Why Markdown?
+
+**Readable as plain text, converts to HTML.**
+
+Markdown is:
+- Easy to learn (15 minutes)
+- Readable without rendering
+- Widely supported
+- Future-proof (plain text)
+- Version control friendly
+
+**Alternatives supported**: HTML (for complex layouts), PHP (for dynamic content).
+
+### Why No Build Tools?
+
+**Immediate feedback, zero setup.**
+
+Build tools add:
+- Installation steps
+- Configuration files
+- Waiting for builds
+- Build failures to debug
+- Another thing that can break
+
+Without builds:
+- Save file β refresh browser β see result
+- No setup (just PHP)
+- Nothing to configure
+- Nothing to break
+
+**Tradeoff**: Can't use Sass, TypeScript, etc. But you can use modern CSS, which is very capable.
+
+### Why Trailing Slashes?
+
+**Consistency and clarity.**
+
+```
+/blog/ # Directory (list view)
+/blog # Redirects to /blog/
+```
+
+Trailing slashes clarify that URLs represent directories, not files. Consistent URLs prevent duplicate content and simplify routing.
+
+### Why Language Prefixes?
+
+**Clear, hackable URLs.**
+
+```
+yoursite.com/en/about/ # English
+yoursite.com/no/about/ # Norwegian
+```
+
+Language in URL:
+- User sees current language
+- Can manually change URL
+- Bookmarkable per language
+- SEO-friendly (clear language signal)
+
+**Default language has no prefix** (shorter, cleaner URLs for primary audience).
+
+## Architectural Patterns
+
+### Immutable Context
+
+The `Context` object is readonly (PHP 8.4):
+```php
+readonly class Context {
+ public function __construct(
+ public private(set) string $contentDir,
+ public private(set) string $currentLang,
+ // ...
+ ) {}
+}
+```
+
+**Why**: Prevents accidental mutation, makes code predictable, enables safe sharing of state.
+
+### Computed Properties
+
+Properties calculate values on-demand:
+```php
+public string $langPrefix {
+ get => $this->currentLang !== $this->defaultLang
+ ? "/{$this->currentLang}"
+ : '';
+}
+```
+
+**Why**: Keeps related logic together, avoids storing derived data, updates automatically.
+
+### Function-Based API
+
+Core functionality exposed as functions, not classes:
+```php
+renderFile($ctx, $filePath);
+findAllContentFiles($dir, $lang, $defaultLang, $availableLangs);
+```
+
+**Why**: Simple to understand, easy to test, no object lifecycle to manage.
+
+### Template Fallback
+
+Check custom, fall back to default:
+```php
+$custom = "/custom/templates/$name.php";
+$default = "/app/default/templates/$name.php";
+return file_exists($custom) ? $custom : $default;
+```
+
+**Why**: Never modify defaults, always override. Clean separation between framework and customization.
+
+## Performance Philosophy
+
+### Performance Through Simplicity
+
+FolderWeb is fast because it does less:
+- No database queries
+- No heavy frameworks
+- No JavaScript parsing
+- Minimal file reads
+- Direct PHP includes
+
+**Measured performance**: Page load time displayed in footer. Pride in speed through simplicity.
+
+### Caching Strategy
+
+FolderWeb doesn't implement caching. Instead:
+- Use OPcache (PHP bytecode cache)
+- Use web server caching (Apache/Nginx)
+- Use reverse proxy (Varnish, Cloudflare)
+- CSS versioned automatically (MD5 hash)
+
+**Why**: Let specialized tools handle caching. FolderWeb focuses on core functionality.
+
+### Optimization Priorities
+
+1. **Avoid work**: Don't render what's not needed
+2. **Use native functions**: PHP's file functions are optimized
+3. **Minimal abstraction**: Fewer layers = less overhead
+
+## Security Philosophy
+
+### Defense in Depth
+
+Multiple security layers:
+- Path validation (prevent directory traversal)
+- Realpath checks (resolve symlinks, verify paths)
+- Content root enforcement (files must be in document root)
+- Output escaping (prevent XSS)
+- MIME type validation (proper content types)
+
+### Simplicity Is Security
+
+Less code = smaller attack surface:
+- No database (no SQL injection)
+- No user input rendering (no XSS in content)
+- No file uploads (no upload vulnerabilities)
+- No authentication (no auth bypasses)
+
+**For user-generated content**: Use a different tool. FolderWeb is for static content you control.
+
+## Maintenance Philosophy
+
+### Code Should Age Gracefully
+
+FolderWeb aims to require zero maintenance:
+- Standard PHP (no exotic dependencies)
+- Minimal third-party code (one library: Parsedown)
+- Stable APIs (PHP doesn't break backward compatibility)
+- No framework upgrades needed
+
+**Goal**: Deploy once, forget about it. Check in years later, it still works.
+
+### Convention Over Configuration
+
+Fewer configuration options = less to maintain:
+- File conventions replace config
+- Sensible defaults for everything
+- Only configure what's necessary (languages)
+
+### Documentation Is Core
+
+Documentation is part of the project:
+- Comprehensive reference
+- Clear examples
+- Explanation of decisions
+- How-to guides for common tasks
+
+**Why**: Future you (or someone else) will thank present you.
+
+## When to Use FolderWeb
+
+### Ideal For
+
+- **Blogs**: Write Markdown, publish immediately
+- **Documentation**: Multi-file pages, clear structure
+- **Portfolios**: Grid layouts, cover images
+- **Marketing sites**: Static content, fast loading
+- **Personal sites**: Simple, maintainable
+- **Long-term projects**: Will work for decades
+
+### Not Ideal For
+
+- **User-generated content**: No database, no auth
+- **E-commerce**: Needs dynamic inventory, checkout
+- **Social networks**: Real-time updates, complex data
+- **SPAs**: JavaScript-heavy, API-driven
+- **Large-scale sites**: Thousands of pages (consider static generation)
+
+### Perfect Fit Scenario
+
+You want a blog or content site that:
+- You control all content
+- Loads fast
+- Requires minimal maintenance
+- Will work for years without updates
+- Integrates with Git workflow
+- Gives you complete control
+
+## Comparison to Alternatives
+
+### vs WordPress
+
+**WordPress**: Full-featured CMS, database-driven, plugin ecosystem, admin panel, requires regular updates
+
+**FolderWeb**: File-based, no database, no plugins, no admin, zero maintenance
+
+**Choose WordPress if**: You need plugins, non-technical editors, or a proven ecosystem
+
+**Choose FolderWeb if**: You want simplicity, longevity, and complete control
+
+### vs Jekyll/Hugo (Static Generators)
+
+**Static Generators**: Build at deploy time, generate HTML files, fast serving, requires builds
+
+**FolderWeb**: Renders on request, no build step, immediate feedback, simpler workflow
+
+**Choose Static Generator if**: You want maximum performance, have build infrastructure
+
+**Choose FolderWeb if**: You want immediate feedback, simpler deployment, dynamic capabilities
+
+### vs Laravel/Symfony (PHP Frameworks)
+
+**Frameworks**: Full-stack, MVC architecture, ORM, routing, complex features
+
+**FolderWeb**: Minimal, file-based routing, no ORM, single purpose
+
+**Choose Framework if**: You're building a complex web application
+
+**Choose FolderWeb if**: You're publishing content and want simplicity
+
+## Future Direction
+
+### Stability Over Features
+
+FolderWeb aims to reach "done" status:
+- Core functionality complete
+- No major features needed
+- Focus on documentation and examples
+- Bug fixes and security updates only
+
+### Possible Additions
+
+Only if they maintain simplicity:
+- More template examples
+- Additional default styles (opt-in)
+- Performance optimizations
+- Better error messages
+
+### Will Never Add
+
+Features that contradict philosophy:
+- JavaScript requirement
+- Database integration
+- Build process
+- Admin panel
+- User authentication
+- Complex plugin system
+
+## Contributing to FolderWeb
+
+### Align With Philosophy
+
+Proposed changes should:
+- Maintain simplicity
+- Avoid new dependencies
+- Work with PHP 8.4+
+- Be maintainable long-term
+- Solve real problems
+
+### Ideal Contributions
+
+- Bug fixes
+- Performance improvements
+- Better documentation
+- Example templates
+- Test cases
+- Clarification of existing code
+
+### Before Adding Features
+
+Ask:
+1. Can this be solved in userland (custom templates/code)?
+2. Does this add complexity for all users?
+3. Will this need maintenance in 5 years?
+4. Is this truly necessary?
+
+## Conclusion
+
+FolderWeb is deliberately simple. It does one thingβpublishes content from filesβand does it well. It resists feature creep, embraces constraints, and prioritizes longevity.
+
+This isn't the right tool for every project. But for content sites that value simplicity, maintainability, and longevity, it might be perfect.
+
+The code you write today should work in 2035. FolderWeb is built on that principle.
+
+## Related
+
+- [Getting Started Tutorial](../tutorial/00-getting-started.md)
+- [Architecture Overview](architecture.md)
+- [File Structure Reference](../reference/file-structure.md)
diff --git a/docs/how-to/custom-styles.md b/docs/how-to/custom-styles.md
new file mode 100644
index 0000000..761de27
--- /dev/null
+++ b/docs/how-to/custom-styles.md
@@ -0,0 +1,398 @@
+# How to Customize Styles
+
+This guide shows you how to override the default styles with your own CSS.
+
+## Overview
+
+FolderWeb uses a fallback system for styles:
+1. Check `/custom/styles/base.css`
+2. Fall back to `/app/default/styles/base.css`
+
+The framework automatically versions CSS files with MD5 hashes for cache busting.
+
+## Quick Start
+
+### Step 1: Create Custom Stylesheet
+
+```bash
+mkdir -p custom/styles
+touch custom/styles/base.css
+```
+
+### Step 2: Override CSS Variables
+
+The easiest way to customize is to override CSS custom properties:
+
+```css
+:root {
+ --color-primary: oklch(0.65 0.20 30); /* Orange */
+ --color-secondary: oklch(0.50 0.18 30); /* Dark orange */
+ --color-light: oklch(0.98 0.01 30); /* Warm white */
+ --color-grey: oklch(0.40 0 0); /* Grey */
+
+ --font-body: "Helvetica Neue", Arial, sans-serif;
+ --font-heading: "Georgia", serif;
+
+ --spacing-unit: 1.5rem;
+ --border-radius: 8px;
+}
+```
+
+### Step 3: Test Your Changes
+
+Refresh your browser. If changes don't appear, do a hard refresh (Ctrl+Shift+R or Cmd+Shift+R).
+
+## Available CSS Variables
+
+### Colors
+
+```css
+--color-primary: oklch(0.65 0.15 250); /* Primary blue */
+--color-secondary: oklch(0.50 0.12 250); /* Dark blue */
+--color-light: oklch(0.97 0.01 250); /* Off-white */
+--color-grey: oklch(0.37 0 0); /* Dark grey */
+```
+
+**Note**: FolderWeb uses OKLCH colors for perceptually uniform color spaces. You can also use hex, rgb, or hsl if preferred.
+
+### Typography
+
+```css
+--font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+--font-heading: Georgia, "Times New Roman", serif;
+
+--font-size-base: 1.125rem; /* 18px */
+--font-size-small: 0.875rem; /* 14px */
+--line-height-base: 1.6;
+--line-height-heading: 1.2;
+```
+
+### Spacing
+
+```css
+--spacing-unit: 1.5rem; /* Base spacing (24px) */
+--spacing-small: 0.75rem; /* 12px */
+--spacing-large: 3rem; /* 48px */
+```
+
+### Layout
+
+```css
+--max-width: 70rem; /* Content max-width */
+--border-radius: 4px; /* Corner rounding */
+```
+
+## Adding Custom Fonts
+
+### Step 1: Add Font Files
+
+```bash
+mkdir -p custom/fonts
+# Copy your .woff2 files here
+cp ~/Downloads/MyFont-Regular.woff2 custom/fonts/
+cp ~/Downloads/MyFont-Bold.woff2 custom/fonts/
+```
+
+### Step 2: Declare Font Faces
+
+In `custom/styles/base.css`:
+
+```css
+@font-face {
+ font-family: 'MyFont';
+ src: url('/custom/fonts/MyFont-Regular.woff2') format('woff2');
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'MyFont';
+ src: url('/custom/fonts/MyFont-Bold.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+:root {
+ --font-body: 'MyFont', sans-serif;
+}
+```
+
+**Note**: Font files are automatically served by FolderWeb's static file handler.
+
+## Page-Specific Styling
+
+FolderWeb adds dynamic CSS classes to the `` element:
+
+```html
+
+```
+
+Use these for targeted styling:
+
+```css
+/* Style all blog pages */
+.section-blog {
+ --color-primary: oklch(0.60 0.15 150); /* Green for blog */
+}
+
+/* Style a specific page */
+.page-about {
+ font-size: 1.25rem;
+}
+
+/* Combine for precision */
+.section-docs.page-installation {
+ background: var(--color-light);
+}
+```
+
+## Responsive Design
+
+FolderWeb uses modern CSS features for responsiveness. Use `clamp()` for fluid typography:
+
+```css
+:root {
+ --font-size-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
+ --spacing-unit: clamp(1rem, 0.8rem + 1vw, 2rem);
+}
+
+h1 {
+ font-size: clamp(2rem, 1.5rem + 2vw, 3.5rem);
+}
+```
+
+Use container queries for component responsiveness:
+
+```css
+.card-grid {
+ container-type: inline-size;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+ gap: var(--spacing-unit);
+}
+
+@container (min-width: 600px) {
+ .card {
+ padding: var(--spacing-large);
+ }
+}
+```
+
+## Dark Mode
+
+Add a dark mode using CSS custom properties and media queries:
+
+```css
+:root {
+ --color-bg: oklch(0.97 0.01 250);
+ --color-text: oklch(0.20 0 0);
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-bg: oklch(0.20 0 0);
+ --color-text: oklch(0.95 0 0);
+ --color-light: oklch(0.25 0 0);
+ --color-primary: oklch(0.70 0.15 250);
+ }
+}
+
+body {
+ background: var(--color-bg);
+ color: var(--color-text);
+}
+```
+
+## List Template Styling
+
+Style the different list templates:
+
+### Grid Layout
+
+```css
+.list-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: var(--spacing-unit);
+}
+
+.list-grid article {
+ border: 1px solid var(--color-light);
+ border-radius: var(--border-radius);
+ overflow: hidden;
+}
+
+.list-grid img {
+ aspect-ratio: 16 / 9;
+ object-fit: cover;
+ width: 100%;
+}
+```
+
+### Card Grid
+
+```css
+.card-grid .card {
+ background: var(--color-light);
+ padding: var(--spacing-unit);
+ border-radius: var(--border-radius);
+ transition: transform 0.2s ease;
+}
+
+.card-grid .card:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
+}
+```
+
+### FAQ Layout
+
+```css
+.faq details {
+ border: 1px solid var(--color-light);
+ border-radius: var(--border-radius);
+ padding: var(--spacing-unit);
+ margin-block-end: var(--spacing-small);
+}
+
+.faq summary {
+ cursor: pointer;
+ font-weight: 700;
+ user-select: none;
+}
+
+.faq summary:hover {
+ color: var(--color-primary);
+}
+```
+
+## Modern CSS Features
+
+FolderWeb encourages use of modern CSS:
+
+### CSS Nesting
+
+```css
+.article {
+ padding: var(--spacing-unit);
+
+ & h2 {
+ color: var(--color-primary);
+ margin-block-start: var(--spacing-large);
+ }
+
+ & a {
+ color: var(--color-secondary);
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+}
+```
+
+### Logical Properties
+
+Use logical properties for internationalization:
+
+```css
+/* Instead of: margin-left, margin-right */
+article {
+ margin-inline: auto;
+ padding-inline: var(--spacing-unit);
+ padding-block: var(--spacing-large);
+}
+
+/* Instead of: text-align: left */
+.content {
+ text-align: start;
+}
+```
+
+### Modern Color Functions
+
+```css
+:root {
+ /* OKLCH: lightness, chroma, hue */
+ --primary: oklch(0.65 0.15 250);
+
+ /* Adjust lightness for hover */
+ --primary-hover: oklch(0.55 0.15 250);
+
+ /* Or use color-mix */
+ --primary-light: color-mix(in oklch, var(--primary), white 20%);
+}
+```
+
+## Performance Tips
+
+### Minimize Custom Styles
+
+Override only what's necessary. The default stylesheet is already optimized.
+
+### Use CSS Variables
+
+Variables reduce repetition and improve maintainability:
+
+```css
+/* Good */
+:root {
+ --card-padding: var(--spacing-unit);
+}
+
+.card { padding: var(--card-padding); }
+.box { padding: var(--card-padding); }
+
+/* Less maintainable */
+.card { padding: 1.5rem; }
+.box { padding: 1.5rem; }
+```
+
+### Avoid `!important`
+
+FolderWeb uses low-specificity selectors, so you shouldn't need `!important`.
+
+## Debugging Styles
+
+### Check Which Stylesheet is Loaded
+
+View source and look for:
+
+```html
+
+```
+
+If you see `/app/styles/`, your custom stylesheet is being used.
+If you see `/app/default-styles/`, the default is being used.
+
+### Browser DevTools
+
+1. Right-click element β Inspect
+2. Check "Computed" tab to see which properties are applied
+3. Check "Sources" tab to verify your CSS file is loaded
+4. Use "Network" tab to ensure CSS isn't cached with old version
+
+### Hard Refresh
+
+Always do a hard refresh after CSS changes:
+- **Chrome/Firefox**: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac)
+- **Safari**: Cmd+Option+R
+
+## Complete Override
+
+If you want complete control, you can replace the entire stylesheet. Copy the default:
+
+```bash
+cp app/default/styles/base.css custom/styles/base.css
+```
+
+Then edit freely. Remember: you're responsible for all styles when you do this.
+
+## Related
+
+- [Custom Templates](custom-templates.md)
+- [CSS Reference](../reference/css-variables.md)
+- [File Structure Reference](../reference/file-structure.md)
diff --git a/docs/how-to/custom-templates.md b/docs/how-to/custom-templates.md
new file mode 100644
index 0000000..9aaec69
--- /dev/null
+++ b/docs/how-to/custom-templates.md
@@ -0,0 +1,288 @@
+# How to Create Custom Templates
+
+This guide shows you how to override default templates with your own custom designs.
+
+## Overview
+
+FolderWeb uses a template fallback system:
+1. Check `/custom/templates/` for custom version
+2. Fall back to `/app/default/templates/` if not found
+
+**Important**: Never modify files in `/app/default/` β always create custom versions in `/custom/`.
+
+## Available Templates
+
+- **base.php** - HTML wrapper (header, navigation, footer)
+- **page.php** - Single page/article wrapper
+- **list.php** - Simple list view (default)
+- **list-grid.php** - Grid layout with images
+- **list-card-grid.php** - Card grid (supports PDFs, external links)
+- **list-faq.php** - Expandable FAQ/Q&A format
+
+## Customizing the Base Template
+
+The base template controls your entire site layout.
+
+### Step 1: Copy the Default
+
+```bash
+mkdir -p custom/templates
+cp app/default/templates/base.php custom/templates/base.php
+```
+
+### Step 2: Edit Your Copy
+
+The base template has access to these variables:
+
+```php
+$content // The rendered page content (HTML)
+$currentLang // Current language code (e.g., "en", "no")
+$navigation // Array of navigation items
+$homeLabel // Site title
+$translations // Translation strings
+$pageTitle // Current page title
+$dirName // Parent directory name (for CSS classes)
+$pageName // Current page name (for CSS classes)
+```
+
+### Example: Add a Custom Header
+
+```php
+
+