diff --git a/app/default/content/00-hero.no.php b/app/default/content/00-hero.no.php new file mode 100644 index 0000000..22e2f5d --- /dev/null +++ b/app/default/content/00-hero.no.php @@ -0,0 +1,50 @@ + 'πŸ“', 'title' => 'Filbasert', 'description' => 'Mapper blir URL-er automatisk', 'url' => '/examples/file-based-routing/'], + ['icon' => '⚑', 'title' => 'Uten byggesteg', 'description' => 'Rediger og oppdaterβ€”det er alt', 'url' => '/examples/no-build-step/'], + ['icon' => '🎨', 'title' => 'Bland formater', 'description' => 'Kombiner .md, .html og .php', 'url' => '/examples/mix-formats/'], + ['icon' => '🌍', 'title' => 'FlersprΓ₯klig', 'description' => 'Innebygd i18n-stΓΈtte', 'url' => '/multilingual/'], + ['icon' => 'πŸ“', 'title' => 'Markdown', 'description' => 'Skriv innhold i markdown', 'url' => '/examples/2024-12-15-markdown-demo/'], + ['icon' => '🎭', 'title' => 'Maler', 'description' => 'Egendefinerte layout og stiler', 'url' => '/examples/templates-demo/'], +]; + +$stats = [ + 'files' => count(glob(__DIR__ . '/**/*', GLOB_BRACE)) ?: 0, + 'generated' => number_format((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2) . 'ms', + 'php_version' => PHP_VERSION, +]; +?> + +
+

FolderWeb

+

+ Slipp filer i mapper. De rendres umiddelbart. + Ingen konfigurasjon, ingen byggesteg, ingen kompleksitet. +

+ +
+ + + +

+

+
+ +
+ +
+
+ + Filer i innhold +
+
+ + Side generert +
+
+ PHP + Runtime +
+
+
diff --git a/app/default/content/00-hero.php b/app/default/content/00-hero.php new file mode 100644 index 0000000..13d8567 --- /dev/null +++ b/app/default/content/00-hero.php @@ -0,0 +1,50 @@ + 'πŸ“', 'title' => 'File-Based', 'description' => 'Folders become URLs automatically', 'url' => '/examples/file-based-routing/'], + ['icon' => '⚑', 'title' => 'No Build Step', 'description' => 'Edit and refreshβ€”that\'s it', 'url' => '/examples/no-build-step/'], + ['icon' => '🎨', 'title' => 'Mix Formats', 'description' => 'Combine .md, .html, and .php', 'url' => '/examples/mix-formats/'], + ['icon' => '🌍', 'title' => 'Multilingual', 'description' => 'Built-in i18n support', 'url' => '/multilingual/'], + ['icon' => 'πŸ“', 'title' => 'Markdown', 'description' => 'Write content in markdown', 'url' => '/examples/2024-12-15-markdown-demo/'], + ['icon' => '🎭', 'title' => 'Templates', 'description' => 'Custom layouts and styles', 'url' => '/examples/templates-demo/'], +]; + +$stats = [ + 'files' => count(glob(__DIR__ . '/**/*', GLOB_BRACE)) ?: 0, + 'generated' => number_format((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2) . 'ms', + 'php_version' => PHP_VERSION, +]; +?> + +
+

FolderWeb

+

+ Drop files in folders. They render immediately. + No configuration, no build step, no complexity. +

+ +
+ + + +

+

+
+ +
+ +
+
+ + Files in content +
+
+ + Page generated +
+
+ PHP + Runtime +
+
+
diff --git a/app/default/content/00-welcome.php b/app/default/content/00-welcome.php deleted file mode 100644 index c59e257..0000000 --- a/app/default/content/00-welcome.php +++ /dev/null @@ -1,6 +0,0 @@ -
-

Welcome to FolderWeb

-

- 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 deleted file mode 100644 index 8d11e2a..0000000 --- a/app/default/content/00a-getting-started.md +++ /dev/null @@ -1,7 +0,0 @@ -## 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 deleted file mode 100644 index de0044f..0000000 --- a/app/default/content/01-core-concepts.md +++ /dev/null @@ -1,15 +0,0 @@ -## 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 new file mode 100644 index 0000000..145e99a --- /dev/null +++ b/app/default/content/01-index.md @@ -0,0 +1,45 @@ + + + +## 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 new file mode 100644 index 0000000..dc0a430 --- /dev/null +++ b/app/default/content/01-index.no.md @@ -0,0 +1,45 @@ + + + +## 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 deleted file mode 100644 index b766430..0000000 --- a/app/default/content/02-features.html +++ /dev/null @@ -1,13 +0,0 @@ -
-

Smart Features

- - - -

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 deleted file mode 100644 index e5d7cb5..0000000 --- a/app/default/content/03-this-page-demo.md +++ /dev/null @@ -1,11 +0,0 @@ -## 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 deleted file mode 100644 index 470d79f..0000000 --- a/app/default/content/about/00-introduction.md +++ /dev/null @@ -1,15 +0,0 @@ -# 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 deleted file mode 100644 index fcdd4d7..0000000 --- a/app/default/content/about/01-design-principles.html +++ /dev/null @@ -1,15 +0,0 @@ -
-

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.

-
diff --git a/app/default/content/about/02-technology-stack.php b/app/default/content/about/02-technology-stack.php deleted file mode 100644 index a2b5292..0000000 --- a/app/default/content/about/02-technology-stack.php +++ /dev/null @@ -1,21 +0,0 @@ -
-

Technology Stack

- -

Backend

- - -

Frontend

- - - -
diff --git a/app/default/content/about/03-what-it-is-not.md b/app/default/content/about/03-what-it-is-not.md deleted file mode 100644 index 89ca489..0000000 --- a/app/default/content/about/03-what-it-is-not.md +++ /dev/null @@ -1,19 +0,0 @@ -## 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 deleted file mode 100644 index 80c52c8..0000000 --- a/app/default/content/about/04-get-started.md +++ /dev/null @@ -1,21 +0,0 @@ -## 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 deleted file mode 100644 index 7e73f4a..0000000 --- a/app/default/content/about/metadata.ini +++ /dev/null @@ -1,3 +0,0 @@ -title = "About FolderWeb" -menu = true -menu_order = 2 diff --git a/app/default/content/about/styles.css b/app/default/content/about/styles.css deleted file mode 100644 index 5dbefaa..0000000 --- a/app/default/content/about/styles.css +++ /dev/null @@ -1,19 +0,0 @@ -/* 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 deleted file mode 100644 index a3bc6d2..0000000 --- a/app/default/content/articles/2025-10-15-markdown-guide/article.md +++ /dev/null @@ -1,206 +0,0 @@ -# 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 -![Alt text](image.jpg) -![Alt text with title](image.jpg "Image title") -``` - -## 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 deleted file mode 100644 index 053268d..0000000 --- a/app/default/content/articles/2025-10-15-markdown-guide/metadata.ini +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 16c1d0c..0000000 --- a/app/default/content/articles/2025-10-28-templates-and-customization/article.md +++ /dev/null @@ -1,165 +0,0 @@ -# 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 - -
- - - - - - - -
-``` - -## 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 deleted file mode 100644 index b69d0a7..0000000 --- a/app/default/content/articles/2025-10-28-templates-and-customization/metadata.ini +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 8bc1e00..0000000 --- a/app/default/content/articles/2025-11-01-getting-started/article.md +++ /dev/null @@ -1,79 +0,0 @@ -# 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 deleted file mode 100644 index 977942b..0000000 --- a/app/default/content/articles/2025-11-01-getting-started/metadata.ini +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index bf15bdf..0000000 --- a/app/default/content/articles/2025-11-02-multi-file-content/00-introduction.md +++ /dev/null @@ -1,14 +0,0 @@ -# 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 deleted file mode 100644 index 5633aa1..0000000 --- a/app/default/content/articles/2025-11-02-multi-file-content/01-examples.md +++ /dev/null @@ -1,24 +0,0 @@ -## 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 deleted file mode 100644 index 547c1ab..0000000 --- a/app/default/content/articles/2025-11-02-multi-file-content/02-use-cases.html +++ /dev/null @@ -1,15 +0,0 @@ -
-

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.

-
diff --git a/app/default/content/articles/2025-11-02-multi-file-content/03-dynamic-demo.php b/app/default/content/articles/2025-11-02-multi-file-content/03-dynamic-demo.php deleted file mode 100644 index 5c49108..0000000 --- a/app/default/content/articles/2025-11-02-multi-file-content/03-dynamic-demo.php +++ /dev/null @@ -1,16 +0,0 @@ -
-

Dynamic Content Example

- -

This section is a PHP file that generates dynamic content. Here are some examples:

- -
-

Server Information

- -
- -

PHP files can access all the same variables and functions available throughout FolderWeb, making it easy to create dynamic, data-driven content.

-
diff --git a/app/default/content/articles/2025-11-02-multi-file-content/04-best-practices.md b/app/default/content/articles/2025-11-02-multi-file-content/04-best-practices.md deleted file mode 100644 index ded8a89..0000000 --- a/app/default/content/articles/2025-11-02-multi-file-content/04-best-practices.md +++ /dev/null @@ -1,23 +0,0 @@ -## Best Practices - -### Use Descriptive Prefixes - -Number your files with two-digit prefixes (`00-`, `01-`, `02-`) to maintain clear ordering: - -- Allows up to 100 sections before needing three digits -- Keeps files sorted in file managers -- Makes reordering easy (just rename) - -### Choose the Right Format - -- **Markdown (`.md`)** - For most content. Simple, clean, readable. -- **HTML (`.html`)** - For complex layouts or embedded media. -- **PHP (`.php`)** - For dynamic content, calculations, or data display. - -### Keep It Simple - -Don't overcomplicate. If your page works well as a single file, keep it that way. Use multiple files when they genuinely make maintenance easier. - ---- - -**This article itself demonstrates the multi-file approach.** View the source folder to see how it's structured! diff --git a/app/default/content/articles/2025-11-02-multi-file-content/metadata.ini b/app/default/content/articles/2025-11-02-multi-file-content/metadata.ini deleted file mode 100644 index ac44f1d..0000000 --- a/app/default/content/articles/2025-11-02-multi-file-content/metadata.ini +++ /dev/null @@ -1,3 +0,0 @@ -title = "Multi-File Content Pages" -date = "2025-11-02" -summary = "Learn how to create pages from multiple content files in any format" diff --git a/app/default/content/articles/metadata.ini b/app/default/content/articles/metadata.ini deleted file mode 100644 index 6c3ca7f..0000000 --- a/app/default/content/articles/metadata.ini +++ /dev/null @@ -1,4 +0,0 @@ -title = "Articles" -menu = true -menu_order = 1 -page_template = "list" diff --git a/app/default/content/articles/page.md b/app/default/content/articles/page.md deleted file mode 100644 index 9594a48..0000000 --- a/app/default/content/articles/page.md +++ /dev/null @@ -1,3 +0,0 @@ -# Articles - -A collection of guides and tutorials to help you get the most out of FolderWeb. diff --git a/app/default/content/articles/styles.css b/app/default/content/articles/styles.css deleted file mode 100644 index 99cbd5b..0000000 --- a/app/default/content/articles/styles.css +++ /dev/null @@ -1,22 +0,0 @@ -/* Page-specific styles for Articles list */ - -.list-item { - border: 2px solid oklch(0.85 0.05 250); - transition: border-color 0.3s ease; -} - -.list-item:hover { - border-color: oklch(0.65 0.15 250); -} - -.list-item h2 a { - color: oklch(0.50 0.12 250); -} - -.list-item .date { - background-color: oklch(0.95 0.02 250); - padding: 0.25rem 0.75rem; - border-radius: 1rem; - font-size: 0.85rem; - display: inline-block; -} diff --git a/app/default/content/examples/2024-10-05-cover-image-demo/cover.svg b/app/default/content/examples/2024-10-05-cover-image-demo/cover.svg new file mode 100644 index 0000000..31e832f --- /dev/null +++ b/app/default/content/examples/2024-10-05-cover-image-demo/cover.svg @@ -0,0 +1,5 @@ + + + + Cover Image Example + diff --git a/app/default/content/examples/2024-10-05-cover-image-demo/index.md b/app/default/content/examples/2024-10-05-cover-image-demo/index.md new file mode 100644 index 0000000..78e749c --- /dev/null +++ b/app/default/content/examples/2024-10-05-cover-image-demo/index.md @@ -0,0 +1,39 @@ +# Cover Images and Assets + +FolderWeb automatically detects and uses cover images for social sharing and list views. + +## How Cover Images Work + +Place an image named `cover.jpg`, `cover.png`, or `cover.webp` in your content folder and it's automatically: + +- Used as the Open Graph image for social media +- Displayed in list views (when using templates that support it) +- Available at the same URL as your content + +## Supported Formats + +- `cover.jpg` or `cover.jpeg` +- `cover.png` +- `cover.webp` +- `cover.gif` + +The system checks for these in order and uses the first one found. + +## Other Assets + +Any file in your content folder is accessible at the same URL path: + +- Images: `photo.jpg`, `diagram.png` +- Documents: `download.pdf`, `report.docx` +- Data: `data.json`, `spreadsheet.csv` + +Just reference them in your markdown: + +```markdown +![Diagram](diagram.png) +[Download PDF](report.pdf) +``` + +## This Folder + +This folder includes a simple SVG as the cover image. Check the folder structure to see how it's organized. diff --git a/app/default/content/examples/2024-10-05-cover-image-demo/metadata.ini b/app/default/content/examples/2024-10-05-cover-image-demo/metadata.ini new file mode 100644 index 0000000..a305d97 --- /dev/null +++ b/app/default/content/examples/2024-10-05-cover-image-demo/metadata.ini @@ -0,0 +1,2 @@ +title = "Cover Images and Assets" +summary = "Learn how cover images and static assets work in FolderWeb" diff --git a/app/default/content/examples/2024-11-20-metadata-example/index.md b/app/default/content/examples/2024-11-20-metadata-example/index.md new file mode 100644 index 0000000..c3bcae9 --- /dev/null +++ b/app/default/content/examples/2024-11-20-metadata-example/index.md @@ -0,0 +1,53 @@ +# Working with Metadata + +Metadata provides structured information about your pages and controls how they display. + +## What is metadata.ini? + +Every folder can have a `metadata.ini` file that defines: + +- Title (overrides automatic title extraction) +- Date (overrides folder-based date detection) +- Summary (appears in list views) +- Custom template selection +- Other custom fields + +## Example metadata.ini + +```ini +title = "My Custom Title" +date = "2024-11-20" +summary = "A brief description that appears in lists" + +[settings] +page_template = "list-grid" +show_date = false +``` + +## Common Use Cases + +**Override automatic titles** – If you want a title different from the folder name. + +**Set explicit dates** – When the folder name doesn't include a date. + +**Add summaries** – Give context in list views without showing full content. + +**Choose templates** – Different sections can use different list templates. + +**Hide metadata** – Set `show_date = false` to hide dates in lists. + +## Custom Fields + +You can add any fields you want: + +```ini +author = "Jane Doe" +category = "Tutorial" +tags = "metadata, configuration, tutorial" +``` + +Then access them in custom templates via `$metadata['author']`. + +## This Page's Metadata + +Check out `metadata.ini` in this folder to see how the title, date, and summary are defined. diff --git a/app/default/content/examples/2024-11-20-metadata-example/metadata.ini b/app/default/content/examples/2024-11-20-metadata-example/metadata.ini new file mode 100644 index 0000000..060c614 --- /dev/null +++ b/app/default/content/examples/2024-11-20-metadata-example/metadata.ini @@ -0,0 +1,3 @@ +title = "Working with Metadata" +date = "2024-11-20" +summary = "Learn how to use metadata.ini files to control page information and behavior" diff --git a/app/default/content/examples/2024-12-15-markdown-demo/index.md b/app/default/content/examples/2024-12-15-markdown-demo/index.md new file mode 100644 index 0000000..949972c --- /dev/null +++ b/app/default/content/examples/2024-12-15-markdown-demo/index.md @@ -0,0 +1,74 @@ +# Markdown Demonstration + +This page shows the full range of Markdown formatting available through Parsedown. + +## Text Formatting + +You can use **bold text**, *italic text*, and even ***bold italic***. + +Use `inline code` for technical terms or file paths like `/app/default/templates/`. + +## Lists + +Unordered lists: + +- First item +- Second item + - Nested item + - Another nested item +- Third item + +Ordered lists: + +1. Step one +2. Step two +3. Step three + +## Links and Images + +Here's a [link to the homepage](/). + +Images work too (when you add them to the folder): + +![Example image](placeholder.jpg) + +## Code Blocks + +```php + This is a blockquote. Perfect for highlighting important information or quotes from other sources. +> +> It can span multiple paragraphs. + +## Tables + +| Feature | Status | +|---------|--------| +| Markdown | βœ“ | +| HTML | βœ“ | +| PHP | βœ“ | +| JavaScript | βœ— | + +## Horizontal Rules + +--- + +That line above is a horizontal rule, useful for separating sections. + +## What You Can Do + +- Write content in simple Markdown +- Mix HTML when needed +- Include images stored alongside your content +- Use all standard Markdown features + +The file for this page is just `index.md` in a dated folder. The date is automatically extracted and displayed. diff --git a/app/default/content/examples/2024-12-15-markdown-demo/index.no.md b/app/default/content/examples/2024-12-15-markdown-demo/index.no.md new file mode 100644 index 0000000..e7edd3a --- /dev/null +++ b/app/default/content/examples/2024-12-15-markdown-demo/index.no.md @@ -0,0 +1,74 @@ +# Markdown-demonstrasjon + +Denne siden viser hele utvalget av Markdown-formatering tilgjengelig gjennom Parsedown. + +## Tekstformatering + +Du kan bruke **fet tekst**, *kursiv tekst*, og til og med ***fet kursiv***. + +Bruk `inline kode` for tekniske termer eller filstier som `/app/default/templates/`. + +## Lister + +Uspesifiserte lister: + +- FΓΈrste element +- Andre element + - Nestet element + - Enda et nestet element +- Tredje element + +Ordnede lister: + +1. Steg Γ©n +2. Steg to +3. Steg tre + +## Lenker og bilder + +Her er en [lenke til forsiden](/). + +Bilder fungerer ogsΓ₯ (nΓ₯r du legger dem til i mappen): + +![Eksempelbilde](placeholder.jpg) + +## Kodeblokker + +```php + Dette er et blokksitat. Perfekt for Γ₯ fremheve viktig informasjon eller sitater fra andre kilder. +> +> Det kan spenne over flere avsnitt. + +## Tabeller + +| Funksjon | Status | +|---------|--------| +| Markdown | βœ“ | +| HTML | βœ“ | +| PHP | βœ“ | +| JavaScript | βœ— | + +## Horisontale linjer + +--- + +Linjen over er en horisontal linje, nyttig for Γ₯ skille seksjoner. + +## Hva du kan gjΓΈre + +- Skriv innhold i enkel Markdown +- Bland inn HTML nΓ₯r det trengs +- Inkluder bilder lagret sammen med innholdet ditt +- Bruk alle standard Markdown-funksjoner + +Filen for denne siden er bare `index.no.md` i en datert mappe. Datoen blir automatisk hentet ut og vist. diff --git a/app/default/content/examples/2024-12-15-markdown-demo/metadata.ini b/app/default/content/examples/2024-12-15-markdown-demo/metadata.ini new file mode 100644 index 0000000..94e5c22 --- /dev/null +++ b/app/default/content/examples/2024-12-15-markdown-demo/metadata.ini @@ -0,0 +1,2 @@ +title = "Markdown Demonstration" +summary = "Shows all the Markdown formatting features available through Parsedown" diff --git a/app/default/content/examples/file-based-routing/index.md b/app/default/content/examples/file-based-routing/index.md new file mode 100644 index 0000000..a1c51bf --- /dev/null +++ b/app/default/content/examples/file-based-routing/index.md @@ -0,0 +1,52 @@ +# File-Based Routing + +FolderWeb's routing is beautifully simple: **your folder structure is your URL structure**. No configuration files, no route definitions, no magic strings. + +## How It Works + +When you visit a URL, FolderWeb looks for matching folders and files: + +``` +/content/ +β”œβ”€β”€ index.md β†’ / +β”œβ”€β”€ about/ +β”‚ └── index.md β†’ /about/ +└── blog/ + β”œβ”€β”€ 2024-11-01-post/ + β”‚ └── index.md β†’ /blog/post/ + └── index.md β†’ /blog/ +``` + +## Automatic Features + +**Folder names become URLs** – Create a folder called `projects` and it's instantly available at `/projects/` + +**Date prefixes are stripped** – `2024-11-01-my-post` becomes `/my-post/` in the URL + +**Custom slugs via metadata** – Override the default URL with `slug = "custom-url"` in `metadata.ini` + +**Trailing slashes** – Directories always redirect to include trailing slashes for consistency + +## Example + +This very page demonstrates file-based routing! The path is: + +``` +app/default/content/examples/file-based-routing/index.md +``` + +Which renders at: + +``` +/examples/file-based-routing/ +``` + +No routes to define. No configuration to update. Just files and folders. + +## Benefits + +- **Intuitive** – If you can navigate folders, you understand the routing +- **Refactor-friendly** – Moving content means moving folders +- **No broken links** – URLs match the filesystem +- **Fast** – No route matching overhead, direct file lookup +- **Predictable** – What you see is what you get diff --git a/app/default/content/examples/file-based-routing/index.no.md b/app/default/content/examples/file-based-routing/index.no.md new file mode 100644 index 0000000..73387e1 --- /dev/null +++ b/app/default/content/examples/file-based-routing/index.no.md @@ -0,0 +1,52 @@ +# Filbasert routing + +FolderWebs routing er vakkert enkelt: **mappestrukturen din er URL-strukturen din**. Ingen konfigurasjonsfiler, ingen rutedefinisjon, ingen magiske strenger. + +## Hvordan det fungerer + +NΓ₯r du besΓΈker en URL, ser FolderWeb etter matchende mapper og filer: + +``` +/content/ +β”œβ”€β”€ index.md β†’ / +β”œβ”€β”€ om/ +β”‚ └── index.md β†’ /om/ +└── blogg/ + β”œβ”€β”€ 2024-11-01-innlegg/ + β”‚ └── index.md β†’ /blogg/innlegg/ + └── index.md β†’ /blogg/ +``` + +## Automatiske funksjoner + +**Mappenavn blir URL-er** – Lag en mappe kalt `prosjekter` og den er umiddelbart tilgjengelig pΓ₯ `/prosjekter/` + +**Datoprefikser fjernes** – `2024-11-01-mitt-innlegg` blir `/mitt-innlegg/` i URL-en + +**Egendefinerte slugs via metadata** – Overstyr standard URL med `slug = "egendefinert-url"` i `metadata.ini` + +**Avsluttende skrΓ₯strek** – Kataloger omdirigerer alltid til Γ₯ inkludere avsluttende skrΓ₯strek for konsistens + +## Eksempel + +Denne siden demonstrerer filbasert routing! Stien er: + +``` +app/default/content/examples/file-based-routing/index.no.md +``` + +Som rendres pΓ₯: + +``` +/examples/file-based-routing/ +``` + +Ingen ruter Γ₯ definere. Ingen konfigurasjon Γ₯ oppdatere. Bare filer og mapper. + +## Fordeler + +- **Intuitivt** – Hvis du kan navigere mapper, forstΓ₯r du routingen +- **Refaktorvennlig** – Γ… flytte innhold betyr Γ₯ flytte mapper +- **Ingen ΓΈdelagte lenker** – URL-er matcher filsystemet +- **Rask** – Ingen rutematching overhead, direkte filoppslag +- **Forutsigbar** – Det du ser er det du fΓ₯r diff --git a/app/default/content/examples/file-based-routing/metadata.ini b/app/default/content/examples/file-based-routing/metadata.ini new file mode 100644 index 0000000..54fe86d --- /dev/null +++ b/app/default/content/examples/file-based-routing/metadata.ini @@ -0,0 +1,3 @@ +title = "File-Based Routing" +summary = "Your folder structure is your URL structureβ€”no configuration needed" +date = "2024-11-26" diff --git a/app/default/content/examples/index.md b/app/default/content/examples/index.md new file mode 100644 index 0000000..4690055 --- /dev/null +++ b/app/default/content/examples/index.md @@ -0,0 +1,5 @@ +# Examples + +This section demonstrates different content types and features you can use in FolderWeb. + +Each example below shows a different capability. Click through to see the source and how it works. diff --git a/app/default/content/examples/mix-formats/00-intro.md b/app/default/content/examples/mix-formats/00-intro.md new file mode 100644 index 0000000..26c34f3 --- /dev/null +++ b/app/default/content/examples/mix-formats/00-intro.md @@ -0,0 +1,11 @@ +# Mix Formats + +FolderWeb lets you **combine different file types** in the same directory. Markdown, HTML, and PHP files can coexist and render together on a single page. + +## Supported Formats + +- **`.md`** – Markdown for content (this file!) +- **`.html`** – Static HTML snippets +- **`.php`** – Dynamic PHP components + +All files in the same directory are rendered in **alphabetical order**. Use number prefixes (like `00-`, `01-`, `02-`) to control the sequence. diff --git a/app/default/content/examples/mix-formats/00-intro.no.md b/app/default/content/examples/mix-formats/00-intro.no.md new file mode 100644 index 0000000..358eb64 --- /dev/null +++ b/app/default/content/examples/mix-formats/00-intro.no.md @@ -0,0 +1,11 @@ +# Bland formater + +FolderWeb lar deg **kombinere forskjellige filtyper** i samme katalog. Markdown, HTML og PHP-filer kan eksistere side om side og rendres sammen pΓ₯ en enkelt side. + +## StΓΈttede formater + +- **`.md`** – Markdown for innhold (denne filen!) +- **`.html`** – Statiske HTML-snippets +- **`.php`** – Dynamiske PHP-komponenter + +Alle filer i samme katalog rendres i **alfabetisk rekkefΓΈlge**. Bruk talprefikser (som `00-`, `01-`, `02-`) for Γ₯ kontrollere sekvensen. diff --git a/app/default/content/examples/mix-formats/01-html-example.html b/app/default/content/examples/mix-formats/01-html-example.html new file mode 100644 index 0000000..7324c01 --- /dev/null +++ b/app/default/content/examples/mix-formats/01-html-example.html @@ -0,0 +1,11 @@ +
+

HTML Component

+

This section is rendered from 01-html-example.html – a static HTML file with inline styles.

+

HTML files are perfect for:

+ +
diff --git a/app/default/content/examples/mix-formats/01-html-example.no.html b/app/default/content/examples/mix-formats/01-html-example.no.html new file mode 100644 index 0000000..32142f6 --- /dev/null +++ b/app/default/content/examples/mix-formats/01-html-example.no.html @@ -0,0 +1,11 @@ +
+

HTML-komponent

+

Denne seksjonen rendres fra 01-html-example.no.html – en statisk HTML-fil med inline stiler.

+

HTML-filer er perfekte for:

+ +
diff --git a/app/default/content/examples/mix-formats/02-dynamic.no.php b/app/default/content/examples/mix-formats/02-dynamic.no.php new file mode 100644 index 0000000..28277f7 --- /dev/null +++ b/app/default/content/examples/mix-formats/02-dynamic.no.php @@ -0,0 +1,41 @@ + PHP_VERSION, + 'Servertid' => $currentTime, + 'Filer i denne katalogen' => count(glob(__DIR__ . '/*')), +]; +?> + +
+

PHP-komponent

+

Denne seksjonen rendres fra 02-dynamic.no.php – en dynamisk PHP-fil som kjΓΈrer pΓ₯ serversiden.

+ + + + + + + + + + $value): ?> + + + + + + +
EgenskapVerdi
+ +

PHP-filer kan:

+ + +

Last inn denne siden pΓ₯ nytt for Γ₯ se servertiden oppdatere seg!

+
diff --git a/app/default/content/examples/mix-formats/02-dynamic.php b/app/default/content/examples/mix-formats/02-dynamic.php new file mode 100644 index 0000000..7c0e989 --- /dev/null +++ b/app/default/content/examples/mix-formats/02-dynamic.php @@ -0,0 +1,41 @@ + PHP_VERSION, + 'Server Time' => $currentTime, + 'Files in this directory' => count(glob(__DIR__ . '/*')), +]; +?> + +
+

PHP Component

+

This section is rendered from 02-dynamic.php – a dynamic PHP file that executes server-side.

+ + + + + + + + + + $value): ?> + + + + + + +
PropertyValue
+ +

PHP files can:

+ + +

Refresh this page to see the server time update!

+
diff --git a/app/default/content/examples/mix-formats/03-conclusion.md b/app/default/content/examples/mix-formats/03-conclusion.md new file mode 100644 index 0000000..00f04f6 --- /dev/null +++ b/app/default/content/examples/mix-formats/03-conclusion.md @@ -0,0 +1,38 @@ +## Why Mix Formats? + +Different content types have different needs: + +**Markdown** – Fast authoring, readable source, perfect for articles and documentation + +**HTML** – Full control over structure, ideal for custom layouts and embedded media + +**PHP** – Dynamic content, server-side logic, database queries, real-time data + +By mixing them freely, you get the best of all worlds. Write most content in Markdown for speed, add HTML for custom sections, and use PHP when you need dynamic behavior. + +## This Page's Structure + +This very page demonstrates format mixing: + +``` +/examples/mix-formats/ +β”œβ”€β”€ 00-intro.md (Markdown introduction) +β”œβ”€β”€ 01-html-example.html (Static HTML component) +β”œβ”€β”€ 02-dynamic.php (Dynamic PHP component) +β”œβ”€β”€ 03-conclusion.md (Markdown conclusion) +└── metadata.ini (Page metadata) +``` + +All four content files render seamlessly as one cohesive page. The numbered prefixes ensure they appear in the intended order. + +## Use Cases + +**Blog with special sections** – Markdown posts with custom HTML callouts or PHP-generated stats + +**Documentation with demos** – Markdown explanations with live PHP examples + +**Landing pages** – Mix markdown content with custom HTML heroes and PHP dynamic elements + +**Portfolio sites** – Markdown project descriptions with HTML galleries and PHP filtering + +The flexibility is yours. diff --git a/app/default/content/examples/mix-formats/03-conclusion.no.md b/app/default/content/examples/mix-formats/03-conclusion.no.md new file mode 100644 index 0000000..833aaba --- /dev/null +++ b/app/default/content/examples/mix-formats/03-conclusion.no.md @@ -0,0 +1,38 @@ +## Hvorfor blande formater? + +Forskjellige innholdstyper har forskjellige behov: + +**Markdown** – Rask redigering, lesbar kilde, perfekt for artikler og dokumentasjon + +**HTML** – Full kontroll over struktur, ideelt for egendefinerte layout og innebygde medier + +**PHP** – Dynamisk innhold, server-side logikk, databasespΓΈrringer, sanntidsdata + +Ved Γ₯ blande dem fritt, fΓ₯r du det beste fra alle verdener. Skriv mesteparten av innholdet i Markdown for hastighet, legg til HTML for egendefinerte seksjoner, og bruk PHP nΓ₯r du trenger dynamisk oppfΓΈrsel. + +## Denne sidens struktur + +Denne siden demonstrerer formatblanding: + +``` +/examples/mix-formats/ +β”œβ”€β”€ 00-intro.no.md (Markdown-introduksjon) +β”œβ”€β”€ 01-html-example.no.html (Statisk HTML-komponent) +β”œβ”€β”€ 02-dynamic.no.php (Dynamisk PHP-komponent) +β”œβ”€β”€ 03-conclusion.no.md (Markdown-konklusjon) +└── metadata.ini (Sidemetadata) +``` + +Alle fire innholdsfilene rendres sΓΈmlΓΈst som Γ©n sammenhengende side. De nummererte prefiksene sikrer at de vises i ΓΈnsket rekkefΓΈlge. + +## BruksomrΓ₯der + +**Blogg med spesialseksjoner** – Markdown-innlegg med egendefinerte HTML-callouts eller PHP-generert statistikk + +**Dokumentasjon med demoer** – Markdown-forklaringer med live PHP-eksempler + +**Landingssider** – Bland markdown-innhold med egendefinerte HTML-heroer og PHP-dynamiske elementer + +**PortefΓΈljesider** – Markdown-prosjektbeskrivelser med HTML-gallerier og PHP-filtrering + +Fleksibiliteten er din. diff --git a/app/default/content/examples/mix-formats/metadata.ini b/app/default/content/examples/mix-formats/metadata.ini new file mode 100644 index 0000000..29e9702 --- /dev/null +++ b/app/default/content/examples/mix-formats/metadata.ini @@ -0,0 +1,3 @@ +title = "Mix Formats" +summary = "Combine Markdown, HTML, and PHP files to create rich, dynamic pages" +date = "2024-11-26" diff --git a/app/default/content/examples/nested/index.md b/app/default/content/examples/nested/index.md new file mode 100644 index 0000000..33718dd --- /dev/null +++ b/app/default/content/examples/nested/index.md @@ -0,0 +1,5 @@ +# Nested Content + +FolderWeb supports content nested as deep as you need. Your folder structure is your URL structure. + +This section demonstrates multi-level nesting. Explore the subdirectories to see how it works. diff --git a/app/default/content/examples/nested/level-two/index.md b/app/default/content/examples/nested/level-two/index.md new file mode 100644 index 0000000..8766f2b --- /dev/null +++ b/app/default/content/examples/nested/level-two/index.md @@ -0,0 +1,5 @@ +# Level Two + +This is two levels deep: `/examples/nested/level-two/` + +You can organize content in hierarchies that make sense for your site structure. diff --git a/app/default/content/examples/nested/level-two/level-three/index.md b/app/default/content/examples/nested/level-two/level-three/index.md new file mode 100644 index 0000000..a9a3114 --- /dev/null +++ b/app/default/content/examples/nested/level-two/level-three/index.md @@ -0,0 +1,5 @@ +# Level Three + +This is three levels deep: `/examples/nested/level-two/level-three/` + +The URL structure automatically follows your folder organization. No routing configuration needed. diff --git a/app/default/content/examples/nested/level-two/level-three/level-four/index.md b/app/default/content/examples/nested/level-two/level-three/level-four/index.md new file mode 100644 index 0000000..a2904b0 --- /dev/null +++ b/app/default/content/examples/nested/level-two/level-three/level-four/index.md @@ -0,0 +1,29 @@ +# Level Four + +Four levels deep: `/examples/nested/level-two/level-three/level-four/` + +## How Deep Can You Go? + +As deep as your filesystem allows. Each folder can contain: + +- Content files (`.md`, `.html`, `.php`) +- Subdirectories (which become sub-URLs) +- Assets (images, PDFs, etc.) +- A `metadata.ini` file +- A `styles.css` file for page-specific styles + +## Navigation + +There's no automatic breadcrumb generation in the default theme, but you can add it in a custom template by parsing the URL path. + +## Use Cases + +**Documentation sites** – Organize by category/subcategory/topic + +**Photo galleries** – Year/month/album/photo + +**Course content** – Course/module/lesson/exercise + +**Product catalogs** – Category/subcategory/product + +The simplicity of file-based routing means your content organization is transparent and portable. diff --git a/app/default/content/examples/no-build-step/index.md b/app/default/content/examples/no-build-step/index.md new file mode 100644 index 0000000..69caba1 --- /dev/null +++ b/app/default/content/examples/no-build-step/index.md @@ -0,0 +1,47 @@ +# No Build Step + +Modern web development often involves complex build pipelines: transpilers, bundlers, minifiers, watchers, and more. FolderWeb takes a different approach: **edit a file, refresh the page, see the result**. + +## What This Means + +**No npm install** – No package.json, no node_modules folder, no dependency hell + +**No compilation** – Write PHP, HTML, CSS, and Markdown directly + +**No watching** – No background processes monitoring file changes + +**No bundling** – Files are served as-is, leveraging HTTP/2 multiplexing + +**No transpiling** – Modern PHP 8.4+ and CSS work in all browsers + +## The Development Flow + +Traditional workflow: +``` +Edit file β†’ Save β†’ Wait for build β†’ Reload β†’ See changes +``` + +FolderWeb workflow: +``` +Edit file β†’ Save β†’ Reload β†’ See changes +``` + +That's it. No waiting. No build errors. No cache invalidation headaches. + +## But What About... + +**Performance?** – PHP is fast. No JavaScript means pages load instantly. CSS is cacheable with MD5 versioning. + +**Minification?** – HTTP/2 compression handles this. Serve from behind a CDN if needed. + +**Modern CSS?** – CSS nesting, custom properties, oklch() colors, gridβ€”all native, all supported. + +**Development speed?** – Instant feedback loop beats any hot reload system. + +## Why This Matters + +Build steps add complexity. Every dependency is a potential breaking change. Every tool is another thing to learn, configure, and maintain. + +FolderWeb will work the same way in 5 years, 10 years, even 20 years. Your content is just files. Your templates are just PHP. Your styles are just CSS. + +**Simple lasts.** diff --git a/app/default/content/examples/no-build-step/index.no.md b/app/default/content/examples/no-build-step/index.no.md new file mode 100644 index 0000000..675a87a --- /dev/null +++ b/app/default/content/examples/no-build-step/index.no.md @@ -0,0 +1,47 @@ +# Uten byggesteg + +Moderne webutvikling involverer ofte komplekse byggepipelines: transpilere, bundlere, minifisere, overvΓ₯kere og mer. FolderWeb tar en annen tilnΓ¦rming: **rediger en fil, oppdater siden, se resultatet**. + +## Hva dette betyr + +**Ingen npm install** – Ingen package.json, ingen node_modules-mappe, ingen avhengighetshelvete + +**Ingen kompilering** – Skriv PHP, HTML, CSS og Markdown direkte + +**Ingen overvΓ₯kning** – Ingen bakgrunnsprosesser som overvΓ₯ker filendringer + +**Ingen bundling** – Filer serveres som de er, ved Γ₯ utnytte HTTP/2-multipleksing + +**Ingen transpilering** – Moderne PHP 8.4+ og CSS fungerer i alle nettlesere + +## Utviklingsflyten + +Tradisjonell arbeidsflyt: +``` +Rediger fil β†’ Lagre β†’ Vent pΓ₯ bygg β†’ Last inn pΓ₯ nytt β†’ Se endringer +``` + +FolderWeb-arbeidsflyt: +``` +Rediger fil β†’ Lagre β†’ Last inn pΓ₯ nytt β†’ Se endringer +``` + +Det er det. Ingen venting. Ingen byggefeil. Ingen cache-invalideringshodebryet. + +## Men hva med... + +**Ytelse?** – PHP er rask. Ingen JavaScript betyr at sider lastes ΓΈyeblikkelig. CSS er cachebar med MD5-versjonering. + +**Minifisering?** – HTTP/2-kompresjon hΓ₯ndterer dette. Server fra bak en CDN om nΓΈdvendig. + +**Moderne CSS?** – CSS-nesting, custom properties, oklch()-farger, gridβ€”alt native, alt stΓΈttet. + +**Utviklingshastighet?** – Øyeblikkelig tilbakemeldingsslΓΈyfe slΓ₯r ethvert hot reload-system. + +## Hvorfor dette betyr noe + +Byggesteg legger til kompleksitet. Hver avhengighet er en potensiell breaking change. Hvert verktΓΈy er noe nytt Γ₯ lΓ¦re, konfigurere og vedlikeholde. + +FolderWeb vil fungere pΓ₯ samme mΓ₯te om 5 Γ₯r, 10 Γ₯r, til og med 20 Γ₯r. Innholdet ditt er bare filer. Malene dine er bare PHP. Stilene dine er bare CSS. + +**Enkelt varer.** diff --git a/app/default/content/examples/no-build-step/metadata.ini b/app/default/content/examples/no-build-step/metadata.ini new file mode 100644 index 0000000..aeef2e9 --- /dev/null +++ b/app/default/content/examples/no-build-step/metadata.ini @@ -0,0 +1,3 @@ +title = "No Build Step" +summary = "Edit, save, refreshβ€”that's it. No compilation, no bundling, no waiting" +date = "2024-11-26" diff --git a/app/default/content/examples/templates-demo/compact-example/2024-10-10-oldest-post/index.md b/app/default/content/examples/templates-demo/compact-example/2024-10-10-oldest-post/index.md new file mode 100644 index 0000000..0269bef --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/2024-10-10-oldest-post/index.md @@ -0,0 +1,3 @@ +# Oldest Post + +The oldest post in this compact list. diff --git a/app/default/content/examples/templates-demo/compact-example/2024-11-15-older-post/index.md b/app/default/content/examples/templates-demo/compact-example/2024-11-15-older-post/index.md new file mode 100644 index 0000000..634aeb5 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/2024-11-15-older-post/index.md @@ -0,0 +1,3 @@ +# Older Post + +An older post showing date ordering. diff --git a/app/default/content/examples/templates-demo/compact-example/2024-12-01-recent-post/index.md b/app/default/content/examples/templates-demo/compact-example/2024-12-01-recent-post/index.md new file mode 100644 index 0000000..70d8cc0 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/2024-12-01-recent-post/index.md @@ -0,0 +1,3 @@ +# Recent Post + +A recent example post. diff --git a/app/default/content/examples/templates-demo/compact-example/index.md b/app/default/content/examples/templates-demo/compact-example/index.md new file mode 100644 index 0000000..552ee94 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/index.md @@ -0,0 +1,3 @@ +# Compact Template + +This section uses `list-compact.php` for a minimal, clean list view. diff --git a/app/default/content/examples/templates-demo/compact-example/metadata.ini b/app/default/content/examples/templates-demo/compact-example/metadata.ini new file mode 100644 index 0000000..a98e845 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/metadata.ini @@ -0,0 +1,4 @@ +title = "Compact Template Example" + +[settings] +page_template = "list-compact" diff --git a/app/default/content/examples/templates-demo/grid-example/index.md b/app/default/content/examples/templates-demo/grid-example/index.md new file mode 100644 index 0000000..33a8ba9 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/index.md @@ -0,0 +1,3 @@ +# Grid Template + +This section uses `list-grid.php` to display items in a responsive grid with cards. diff --git a/app/default/content/examples/templates-demo/grid-example/item-one/index.md b/app/default/content/examples/templates-demo/grid-example/item-one/index.md new file mode 100644 index 0000000..91c74d9 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-one/index.md @@ -0,0 +1,3 @@ +# Grid Item One + +This is an example item in the grid layout. diff --git a/app/default/content/examples/templates-demo/grid-example/item-one/metadata.ini b/app/default/content/examples/templates-demo/grid-example/item-one/metadata.ini new file mode 100644 index 0000000..39293ad --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-one/metadata.ini @@ -0,0 +1 @@ +summary = "First item demonstrating grid layout" diff --git a/app/default/content/examples/templates-demo/grid-example/item-three/index.md b/app/default/content/examples/templates-demo/grid-example/item-three/index.md new file mode 100644 index 0000000..5e945e1 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-three/index.md @@ -0,0 +1,3 @@ +# Grid Item Three + +A third item to show the grid layout with multiple items. diff --git a/app/default/content/examples/templates-demo/grid-example/item-three/metadata.ini b/app/default/content/examples/templates-demo/grid-example/item-three/metadata.ini new file mode 100644 index 0000000..db23a37 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-three/metadata.ini @@ -0,0 +1 @@ +summary = "Third grid item" diff --git a/app/default/content/examples/templates-demo/grid-example/item-two/index.md b/app/default/content/examples/templates-demo/grid-example/item-two/index.md new file mode 100644 index 0000000..bf06247 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-two/index.md @@ -0,0 +1,3 @@ +# Grid Item Two + +Another example showing how items appear in the grid. diff --git a/app/default/content/examples/templates-demo/grid-example/item-two/metadata.ini b/app/default/content/examples/templates-demo/grid-example/item-two/metadata.ini new file mode 100644 index 0000000..d32da37 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-two/metadata.ini @@ -0,0 +1 @@ +summary = "Second item in the grid" diff --git a/app/default/content/examples/templates-demo/grid-example/metadata.ini b/app/default/content/examples/templates-demo/grid-example/metadata.ini new file mode 100644 index 0000000..958c6a0 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/metadata.ini @@ -0,0 +1,4 @@ +title = "Grid Template Example" + +[settings] +page_template = "list-grid" diff --git a/app/default/content/examples/templates-demo/index.md b/app/default/content/examples/templates-demo/index.md new file mode 100644 index 0000000..e6a777d --- /dev/null +++ b/app/default/content/examples/templates-demo/index.md @@ -0,0 +1,24 @@ +# List Templates + +FolderWeb includes several list templates you can use for different presentation styles. + +This section demonstrates the different templates by using subdirectories. Each subdirectory below uses a different template via `metadata.ini`. + +## Available Templates + +**list.php** – Default linear list with optional cover images + +**list-grid.php** – Grid layout with cards, great for galleries or portfolios + +**list-compact.php** – Minimal list showing just titles and dates + +## Choosing a Template + +In any folder's `metadata.ini`, add: + +```ini +[settings] +page_template = "list-grid" +``` + +The three subdirectories below each use a different template. Compare them to see which fits your content best. diff --git a/app/default/content/multilingual/index.en.md b/app/default/content/multilingual/index.en.md new file mode 100644 index 0000000..0fa5c7b --- /dev/null +++ b/app/default/content/multilingual/index.en.md @@ -0,0 +1,53 @@ +# Multilingual Support + +**Currently viewing: English (EN)** + +This page demonstrates FolderWeb's built-in language support. Use the language switcher in the header to toggle between **EN** and **NO** - the page content will change to match your selected language. + +## How It Works + +Creating multilingual content is straightforward: + +1. **Add language codes to filenames** – Create `index.en.md` and `index.no.md` +2. **Language switcher appears automatically** – When multiple versions exist +3. **URLs get language prefixes** – Non-default languages use `/en/page/`, `/no/page/`, etc. +4. **Share metadata** – One `metadata.ini` file per directory works for all languages + +## File Structure Example + +``` +/content/about/ +β”œβ”€β”€ index.en.md # English version +β”œβ”€β”€ index.no.md # Norwegian version +└── metadata.ini # Shared metadata +``` + +## Configuration + +Enable languages in `/app/default/config.ini`: + +```ini +[languages] +default = "en" +available = "en,no" +``` + +## Translation Strings + +UI text comes from language files in `/app/default/languages/`: + +```ini +; en.ini +home = "Home" +read_more = "Read more" + +; no.ini +home = "Hjem" +read_more = "Les mer" +``` + +Translation strings are optionalβ€”templates fall back to sensible defaults if missing. + +## Try It + +Use the language switcher in the header to toggle between English and Norwegian versions of this page. The content stays the same, just translated. diff --git a/app/default/content/multilingual/index.no.md b/app/default/content/multilingual/index.no.md new file mode 100644 index 0000000..a610b23 --- /dev/null +++ b/app/default/content/multilingual/index.no.md @@ -0,0 +1,53 @@ +# FlersprΓ₯klig stΓΈtte + +**Viser nΓ₯: Norsk (NO)** + +Denne siden demonstrerer FolderWebs innebygde sprΓ₯kstΓΈtte. Bruk sprΓ₯kvelgeren i headeren for Γ₯ bytte mellom **EN** og **NO** - sideinnholdet vil endre seg til Γ₯ matche det valgte sprΓ₯ket. + +## Slik fungerer det + +Γ… opprette flersprΓ₯klig innhold er enkelt: + +1. **Legg til sprΓ₯kkoder i filnavn** – Opprett `index.en.md` og `index.no.md` +2. **SprΓ₯kvelgeren vises automatisk** – NΓ₯r flere versjoner finnes +3. **URL-er fΓ₯r sprΓ₯kprefikser** – Ikke-standardsprΓ₯k bruker `/en/side/`, `/no/side/`, osv. +4. **Del metadata** – Γ‰n `metadata.ini`-fil per katalog fungerer for alle sprΓ₯k + +## Eksempel pΓ₯ filstruktur + +``` +/content/om/ +β”œβ”€β”€ index.en.md # Engelsk versjon +β”œβ”€β”€ index.no.md # Norsk versjon +└── metadata.ini # Delt metadata +``` + +## Konfigurasjon + +Aktiver sprΓ₯k i `/app/default/config.ini`: + +```ini +[languages] +default = "en" +available = "en,no" +``` + +## Oversettelsesstrenger + +UI-tekst kommer fra sprΓ₯kfiler i `/app/default/languages/`: + +```ini +; en.ini +home = "Home" +read_more = "Read more" + +; no.ini +home = "Hjem" +read_more = "Les mer" +``` + +Oversettelsesstrenger er valgfrieβ€”maler faller tilbake til fornuftige standardverdier hvis de mangler. + +## PrΓΈv det + +Bruk sprΓ₯kvelgeren i headeren for Γ₯ bytte mellom engelske og norske versjoner av denne siden. Innholdet forblir det samme, bare oversatt. diff --git a/app/default/content/multilingual/metadata.ini b/app/default/content/multilingual/metadata.ini new file mode 100644 index 0000000..66a04f1 --- /dev/null +++ b/app/default/content/multilingual/metadata.ini @@ -0,0 +1,2 @@ +title = "Multilingual Support" +summary = "Learn how to create content in multiple languages" diff --git a/app/default/content/styles.css b/app/default/content/styles.css index c4fd295..0abceb8 100644 --- a/app/default/content/styles.css +++ b/app/default/content/styles.css @@ -1,34 +1,112 @@ -/* Page-specific styles for homepage */ - +/* Hero section for frontpage */ .hero { - display: flex; - flex-direction: column; - justify-content: flex-end; - padding: 1rem .4rem; - background-color: oklch(0.85 0.05 250); - min-height: 40vh; - text-align: center; + background: linear-gradient(135deg, oklch(95% 0.05 250) 0%, oklch(98% 0.02 250) 100%); + border-radius: 0.75rem; + padding: var(--space-m); + margin-block: var(--space-s); + text-align: center; + + & .hero-title { + font-size: clamp(2rem, 5vw, 2.5rem); + margin-block: 0 var(--space-xs); + background: linear-gradient(135deg, oklch(40% 0.15 250), oklch(30% 0.2 280)); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-weight: 900; + } + + & .hero-subtitle { + font-size: clamp(1rem, 2vw, 1.125rem); + color: var(--color-muted); + margin-block-end: var(--space-m); + max-width: 32rem; + margin-inline: auto; + } + + & .cta-button { + display: inline-block; + background: var(--color-accent); + color: white; + padding: var(--space-xs) var(--space-m); + border-radius: 0.5rem; + text-decoration: none; + font-weight: 600; + margin-block-start: var(--space-xs); + + &:hover { + background: oklch(45% 0.15 250); + color: white; + } + } } -.hero h1 { - font-size: clamp(2.5rem, 6vw, 4rem); - margin: 0; +.features { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); + gap: var(--space-s); + margin-block: var(--space-m); + + & .feature-card { + background: var(--color-background); + padding: var(--space-s); + border-radius: 0.5rem; + border: 1px solid var(--color-border); + text-align: center; + transition: transform 0.2s, box-shadow 0.2s; + text-decoration: none; + color: inherit; + display: block; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px oklch(0% 0 0 / 0.1); + border-color: var(--color-accent); + } + + & .feature-icon { + font-size: 2rem; + display: block; + margin-block-end: var(--space-xs); + } + + & .feature-title { + font-weight: bold; + margin-block: var(--space-xs); + color: var(--color-text); + font-size: 0.9rem; + } + + & .feature-description { + font-size: 0.85rem; + color: var(--color-muted); + margin: 0; + } + } } -.cta-section { - background: linear-gradient(135deg, oklch(0.65 0.15 250), oklch(0.50 0.12 250)); - padding: 2rem 1rem; - margin-top: 3rem; - text-align: center; - color: white; -} - -.cta-section p { - color: white; - font-size: clamp(1.1rem, 3vw, 1.3rem); -} - -.cta-content { - max-width: 42rem; - margin: 0 auto; +.stats { + display: flex; + justify-content: center; + gap: var(--space-m); + flex-wrap: wrap; + margin-block-start: var(--space-m); + padding-block-start: var(--space-s); + border-block-start: 1px solid var(--color-border); + + & .stat { + text-align: center; + + & .stat-value { + display: block; + font-size: 1.25rem; + font-weight: bold; + color: var(--color-accent); + } + + & .stat-label { + font-size: 0.8rem; + color: var(--color-muted); + } + } } diff --git a/app/default/languages/en.ini b/app/default/languages/en.ini index db8f040..c21972d 100644 --- a/app/default/languages/en.ini +++ b/app/default/languages/en.ini @@ -1,13 +1,13 @@ ; English translations +; These strings are used in templates and can be customized +; If a string is missing, the key name will be used as fallback + home = "Home" categories = "Categories" tags = "Tags" read_more = "Read more" read_article = "Read article" -read_full_answer = "Read full answer" -download_pdf = "Download PDF" summary = "Summary" -footer_text = "Footer content goes here" -footer_handcoded = "This page was generated in" +footer_handcoded = "Generated in" footer_page_time = "ms" months = "January,February,March,April,May,June,July,August,September,October,November,December" diff --git a/app/default/languages/no.ini b/app/default/languages/no.ini index cd7c114..b64f9df 100644 --- a/app/default/languages/no.ini +++ b/app/default/languages/no.ini @@ -1,13 +1,13 @@ ; Norwegian translations +; These strings are used in templates and can be customized +; If a string is missing, English fallback will be used + home = "Hjem" categories = "Kategorier" -tags = "Stikkord" +tags = "Emneknagger" read_more = "Les mer" read_article = "Les artikkel" -read_full_answer = "Les hele svaret" -download_pdf = "Last ned PDF" -summary = "Oppsummering" -footer_text = "Bunntekst her" -footer_handcoded = "Denne siden ble generert pΓ₯" +summary = "Sammendrag" +footer_handcoded = "Generert pΓ₯" footer_page_time = "ms" months = "januar,februar,mars,april,mai,juni,juli,august,september,oktober,november,desember" diff --git a/app/default/styles/base.css b/app/default/styles/base.css deleted file mode 100644 index 7f67bc8..0000000 --- a/app/default/styles/base.css +++ /dev/null @@ -1,191 +0,0 @@ -/* MINIMAL CSS RESET*/ -* { margin-bottom: 0; } - -/* VARIABLES */ -:root { - --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; - --font-heading: Georgia, "Times New Roman", serif; - --color-primary: #4a90e2; - --color-primary: oklch(0.65 0.15 250); - --color-secondary: #2c5aa0; - --color-secondary: oklch(0.50 0.12 250); - --color-light: #f0f4f8; - --color-light: oklch(0.97 0.01 250); - --color-grey: #404040; - --color-grey: oklch(0.37 0 0); -} - -/* GLOBAL */ -html { font-family: var(--font-body); font-size: clamp(16px, 2.3vw, 20px); scroll-behavior: smooth; } -body { margin: 0; color: var(--color-grey) } -p, ul, ol, aside { line-height: 1.5em; hyphens: auto } -img { max-width: 100%; height: auto; } -h1 { color: var(--color-primary); font-size: 2.3rem } -h1, h2, h3, h4, h5, h6 { - font-family: var(--font-heading); - font-weight: 400; - line-height: 1.3em; - margin-top: 1.3em; - text-wrap: pretty; -} -a { - color: var(--color-primary); - text-decoration: none; - &:hover { color: var(--color-secondary) } -} - -.grid-container { - display: grid; - grid-template-rows: auto 1fr auto; - grid-template-columns: 1fr; - grid-template-areas: "header" "main" "footer"; - height: 100%; - width: 100%; - justify-content: center; - min-height: 100vh; - align-items: stretch; -} - -.contain, :where(main>article, main>aside, main>section) { - display: grid; - grid-template-columns: minmax(.4rem, 1fr) minmax(0, 42rem) minmax(.3rem, 1fr); - > * { - grid-column: 2; - } -} - -.escape { - grid-column: 1 / -1 !important; -} - -/* HEADER */ -header { - border-bottom: 3px #00000022 solid; - grid-area: header; - > div { - padding-bottom: .2rem; - display: flex; - .logo { - margin-right: .3rem; - svg { - width: 7rem; - height: 100%; - color: var(--color-primary); - } - } - - nav { - display:flex; - align-items: center; - justify-content:flex-end; - flex: 1; - ul { - display: flex; - list-style: none; - flex-wrap: wrap; - margin-top: .4rem; - padding: 0; - justify-content: flex-end; - li { - margin-left:0.4rem; - margin-top:0.4rem; - } - } - } - } -} - -/* MAIN */ -main { - grid-area: main; - background-color: var(--color-light); - padding-bottom: 2rem; - - aside { margin-top: 1.3em } - article { - .intro { - font-size: 1.2rem; - line-height: 1.35em; - } - } - .button { - margin-top: 1.3rem; - justify-self: start; - } -} - -/* BUTTONS */ -.button { - display: inline-block; - text-decoration: none; - border-radius: 2rem; - padding: 0.35rem 1rem; - background-color: transparent; - color: var(--color-grey); - outline: 0.08rem var(--color-grey) solid; - - &:hover { - background-color: var(--color-grey); - color: white; - outline: none; - } - - &:active, &.active { - background-color: var(--color-primary); - color: white; - outline: none; - } - - &:focus { - background-color: var(--color-primary); - color: white; - outline: none; - } - - &.inverted { - background-color: transparent; - color: white; - outline: 0.08rem white solid; - - &:hover { - background-color: white; - color: var(--color-primary); - outline: none; - } - - &:active, &.active { - background-color: var(--color-light); - color: var(--color-primary); - outline: none; - } - - &:focus { - color: white; - background-color: var(--color-grey); - outline: none; - } -} - - &.bigger { - font-size: 1.2em; - padding: calc(0.35rem * 1.2) calc(1rem * 1.2); - border-radius: calc(1rem * 1.2); - } -} - -/* FOOTER */ - -footer { - color: var(--color-light); - a { - color: var(--color-light); - &:hover { color: white; text-decoration: underline } - } - background-color: var(--color-secondary); - grid-area: footer; - > div { - margin: 1rem 0; - text-align: center; - .generated { font-size: .6rem } - } -} diff --git a/app/default/templates/base.php b/app/default/templates/base.php index 9611239..ccf18d6 100644 --- a/app/default/templates/base.php +++ b/app/default/templates/base.php @@ -1,69 +1,55 @@ - - - - - - - - - - - - - - <?= htmlspecialchars($pageTitle ?? 'Site Title') ?> + + + <?= htmlspecialchars($pageTitle ?? 'FolderWeb') ?> + + + + + + + + + + + +
+ + 1): ?> + + +
- -
-
-
- - -
-
+
+ +
-
- -
- - -
+ diff --git a/app/default/templates/list-card-grid.php b/app/default/templates/list-card-grid.php deleted file mode 100644 index ec5f1dd..0000000 --- a/app/default/templates/list-card-grid.php +++ /dev/null @@ -1,82 +0,0 @@ - -
- -
- - -
-
- -
- - - <?= htmlspecialchars($item['title']) ?> - - -

- - - -

- -

- - -

- -
- - - - - - - - -
-
- -
-
- - diff --git a/app/default/templates/list-compact.php b/app/default/templates/list-compact.php new file mode 100644 index 0000000..f556df5 --- /dev/null +++ b/app/default/templates/list-compact.php @@ -0,0 +1,61 @@ + +
+ +
+ + + + + diff --git a/app/default/templates/list-faq.php b/app/default/templates/list-faq.php deleted file mode 100644 index e2791dd..0000000 --- a/app/default/templates/list-faq.php +++ /dev/null @@ -1,141 +0,0 @@ - -
- -
- - -
-
- -
- -

- -
-
- -

:

- - -
-
- -
-
- - diff --git a/app/default/templates/list-grid.php b/app/default/templates/list-grid.php index 0aad44c..43af018 100644 --- a/app/default/templates/list-grid.php +++ b/app/default/templates/list-grid.php @@ -1,94 +1,48 @@ -
- -
+
+ +
-
-
- - - -
-
+
+ +
+ + + + +

+ + + + + + +

+ +
+ +
diff --git a/app/default/templates/list.php b/app/default/templates/list.php index 8d7ab48..ed28f1d 100644 --- a/app/default/templates/list.php +++ b/app/default/templates/list.php @@ -1,55 +1,25 @@ -
- -
+
+ +
-
- -
- - - <?= htmlspecialchars($item['title']) ?> - - -

- - - -

- -

- - -

- - -
- -
- - +
+ +
+ + + + +

+ + + + + + +

+ +
+ +
diff --git a/app/default/templates/page.php b/app/default/templates/page.php index 6ed654c..a511e6f 100644 --- a/app/default/templates/page.php +++ b/app/default/templates/page.php @@ -1,25 +1,3 @@ - - - - - +
+ +
diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 292e66b..0000000 --- a/docs/README.md +++ /dev/null @@ -1,211 +0,0 @@ -# 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 deleted file mode 100644 index 08809d8..0000000 --- a/docs/explanation/architecture.md +++ /dev/null @@ -1,739 +0,0 @@ -# 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 - -``` - -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: - -The language is: 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 deleted file mode 100644 index cace2af..0000000 --- a/docs/explanation/philosophy.md +++ /dev/null @@ -1,496 +0,0 @@ -# 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 deleted file mode 100644 index 761de27..0000000 --- a/docs/how-to/custom-styles.md +++ /dev/null @@ -1,398 +0,0 @@ -# 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 deleted file mode 100644 index 9aaec69..0000000 --- a/docs/how-to/custom-templates.md +++ /dev/null @@ -1,288 +0,0 @@ -# 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 - -``` - -## Customizing the Page Template - -The page template wraps individual articles and pages. - -### Step 1: Copy the Default - -```bash -cp app/default/templates/page.php custom/templates/page.php -``` - -### Step 2: Customize - -Available variables: - -```php -$content // Main content HTML -$pageMetadata // Array of metadata (tags, categories, etc.) -$translations // Translation strings -``` - -### Example: Add Author Information - -```php -
- -
-

Written by

-
- - - - - -
- : - - - -
- -
-``` - -## Creating a Custom List Template - -List templates control how directories with subdirectories are displayed. - -### Step 1: Create Your Template - -```bash -touch custom/templates/list-custom.php -``` - -### Step 2: Use List Template Variables - -All list templates receive: - -```php -$items // Array of subdirectories -$metadata // Directory metadata -$pageContent // Optional intro content -$translations // Translation strings -``` - -Each item in `$items` has: - -```php -[ - 'title' => 'Post Title', - 'date' => '2. november 2025', - 'url' => '/blog/2025-11-02-post/', - 'cover' => '/blog/2025-11-02-post/cover.jpg', - 'summary' => 'Brief description', - 'pdf' => '/blog/2025-11-02-post/document.pdf', - 'redirect' => 'https://external-site.com' -] -``` - -### Example: Timeline Template - -```php - -
- -
- - -
- -
- -

- -

- -

- -
- -
-``` - -### Step 3: Apply Your Template - -Create a `metadata.ini` in the directory: - -```ini -page_template = "list-custom" -``` - -## Template Best Practices - -### Always Escape Output - -Prevent XSS attacks by escaping user-generated content: - -```php - -``` - -### Use Short Echo Tags - -FolderWeb uses modern PHP, so short tags are always available: - -```php - // Good - // Also works, but verbose -``` - -### Check Before Using - -Always check if variables exist: - -```php - - - -``` - -### Leverage CSS Classes - -The base template adds dynamic classes to ``: - -```php - -``` - -Use these for page-specific styling without JavaScript. - -## Advanced: Accessing the Context Object - -Templates can access the full context object `$ctx`: - -```php -contentDir // Path to content directory -$ctx->currentLang // Current language -$ctx->defaultLang // Default language -$ctx->availableLangs // Array of available languages -$ctx->langPrefix // URL prefix (e.g., "/en" or "") -$ctx->requestPath // Current request path -$ctx->hasTrailingSlash // Boolean -$ctx->navigation // Navigation array (computed property) -$ctx->homeLabel // Site title (computed property) -$ctx->translations // Translation array (computed property) -?> -``` - -## Example: Breadcrumb Navigation - -Add breadcrumbs to your page template: - -```php - -``` - -## Testing Your Templates - -1. Clear your browser cache -2. Reload the page -3. Check browser console for errors -4. Validate HTML with W3C validator - -## Reverting Changes - -To revert to default templates, simply delete your custom version: - -```bash -rm custom/templates/base.php -``` - -FolderWeb will automatically fall back to the default. - -## Related - -- [Customizing Styles](custom-styles.md) -- [Template Reference](../reference/templates.md) -- [Metadata Reference](../reference/metadata.md) diff --git a/docs/how-to/multi-language.md b/docs/how-to/multi-language.md deleted file mode 100644 index 4464c8b..0000000 --- a/docs/how-to/multi-language.md +++ /dev/null @@ -1,425 +0,0 @@ -# How to Create a Multi-Language Site - -This guide shows you how to set up and manage a multi-language website with FolderWeb. - -## Overview - -FolderWeb supports multiple languages through: -- Language prefixes in URLs -- Language-specific content files -- Translated slugs and metadata -- Translation files for UI strings - -## Configuration - -### Step 1: Configure Available Languages - -Create or edit `custom/config.ini`: - -```ini -[languages] -default = "en" -available = "en,no,fr" -``` - -- **default**: The primary language (no URL prefix) -- **available**: Comma-separated list of all supported languages - -### Step 2: Create Translation Files - -Create translation files for each language in `custom/languages/`: - -```bash -mkdir -p custom/languages -``` - -**English** (`custom/languages/en.ini`): -```ini -home = "Home" -read_more = "Read more" -categories = "Categories" -tags = "Tags" -footer_text = "Made with FolderWeb" -footer_handcoded = "Generated in" -footer_page_time = "ms" -``` - -**Norwegian** (`custom/languages/no.ini`): -```ini -home = "Hjem" -read_more = "Les mer" -categories = "Kategorier" -tags = "Stikkord" -footer_text = "Laget med FolderWeb" -footer_handcoded = "Generert pΓ₯" -footer_page_time = "ms" -``` - -**French** (`custom/languages/fr.ini`): -```ini -home = "Accueil" -read_more = "Lire la suite" -categories = "CatΓ©gories" -tags = "Γ‰tiquettes" -footer_text = "Créé avec FolderWeb" -footer_handcoded = "GΓ©nΓ©rΓ© en" -footer_page_time = "ms" -``` - -## URL Structure - -With the configuration above: - -- **English** (default): `yoursite.com/about/` -- **Norwegian**: `yoursite.com/no/about/` -- **French**: `yoursite.com/fr/about/` - -The default language never has a URL prefix. - -## Creating Language-Specific Content - -### Method 1: Separate Files Per Language - -Use language suffixes in filenames: `filename.{lang}.ext` - -**Example structure**: -``` -content/about/ -β”œβ”€β”€ index.md # Default language (English) -β”œβ”€β”€ index.no.md # Norwegian version -└── index.fr.md # French version -``` - -**Rules**: -- Language-specific files (`.lang.ext`) show only for that language -- Default files (no language suffix) show only if no language variant exists -- Files are automatically filtered based on current language - -### Example Content - -**content/about/index.md** (English): -```markdown -# About Us - -We are a company dedicated to simplicity. -``` - -**content/about/index.no.md** (Norwegian): -```markdown -# Om Oss - -Vi er et selskap dedikert til enkelhet. -``` - -**content/about/index.fr.md** (French): -```markdown -# Γ€ Propos - -Nous sommes une entreprise dΓ©diΓ©e Γ  la simplicitΓ©. -``` - -Now when users visit: -- `/about/` β†’ Shows English (index.md) -- `/no/about/` β†’ Shows Norwegian (index.no.md) -- `/fr/about/` β†’ Shows French (index.fr.md) - -### Method 2: Language-Specific Folders - -For blog posts and articles, you can create separate folders: - -``` -content/blog/ -β”œβ”€β”€ 2025-11-01-english-post/ -β”‚ └── index.md -β”œβ”€β”€ 2025-11-01-norsk-innlegg/ -β”‚ └── index.no.md -└── 2025-11-01-article-francais/ - └── index.fr.md -``` - -## Translated Slugs and Titles - -Use `metadata.ini` to provide translated slugs and metadata: - -**content/about/metadata.ini**: -```ini -; Default (English) -title = "About Us" -slug = "about" - -[no] -title = "Om Oss" -slug = "om-oss" - -[fr] -title = "Γ€ Propos" -slug = "a-propos" -``` - -Now URLs become: -- English: `/about/` -- Norwegian: `/no/om-oss/` -- French: `/fr/a-propos/` - -The actual folder is still named `about/`, but FolderWeb maps the translated slug to the real folder. - -## Blog Posts with Translations - -**Structure**: -``` -content/blog/ -└── 2025-11-02-my-post/ - β”œβ”€β”€ index.md - β”œβ”€β”€ index.no.md - β”œβ”€β”€ index.fr.md - β”œβ”€β”€ cover.jpg - └── metadata.ini -``` - -**metadata.ini**: -```ini -; Default language -title = "My First Post" -summary = "An introduction to multilingual blogging." -date = "2025-11-02" - -[no] -title = "Mitt FΓΈrste Innlegg" -summary = "En introduksjon til flersprΓ₯klig blogging." - -[fr] -title = "Mon Premier Article" -summary = "Une introduction au blogging multilingue." -``` - -**Important**: Date is global, cover image is shared across languages. - -## Navigation and Menus - -Navigation is automatically built with translations. In `metadata.ini` for each top-level directory: - -**content/blog/metadata.ini**: -```ini -menu = true -menu_order = 1 - -title = "Blog" -[no] -title = "Blogg" -[fr] -title = "Blog" -``` - -**content/about/metadata.ini**: -```ini -menu = true -menu_order = 2 - -title = "About" -[no] -title = "Om" -[fr] -title = "Γ€ Propos" -``` - -Navigation automatically includes language prefix in URLs. - -## Using Translations in Templates - -### In Default Templates - -Translations are automatically available as `$translations` array: - -```php - - - - -

-``` - -### In Custom Templates - -Access translations the same way: - -```php - -``` - -### Access Current Language - -```php -currentLang === 'no'): ?> -

Dette er norsk innhold.

- -

This is English content.

- -``` - -## Language Switcher - -Create a language switcher in your custom base template: - -```php - -``` - -Style it: - -```css -.language-switcher { - display: flex; - gap: 0.5rem; -} - -.language-switcher a { - padding: 0.25rem 0.75rem; - border-radius: var(--border-radius); - text-decoration: none; -} - -.language-switcher a.active { - background: var(--color-primary); - color: white; -} -``` - -## List Views with Multiple Languages - -When displaying blog listings, FolderWeb automatically filters items by language: - -``` -content/blog/ -β”œβ”€β”€ 2025-11-01-english-article/ -β”‚ └── index.md # Shows in English -β”œβ”€β”€ 2025-11-02-norsk-artikkel/ -β”‚ └── index.no.md # Shows only in Norwegian -└── 2025-11-03-universal/ - β”œβ”€β”€ index.md # Shows in English - β”œβ”€β”€ index.no.md # Shows in Norwegian - └── index.fr.md # Shows in French -``` - -When viewing `/blog/`: -- Shows "english-article" and "universal" - -When viewing `/no/blog/`: -- Shows "norsk-artikkel" and "universal" - -When viewing `/fr/blog/`: -- Shows only "universal" - -## Handling Missing Translations - -### Default Fallback - -If a translation is missing, FolderWeb uses the default language automatically. - -### Show Different Content - -You can use PHP in your content files: - -```php -currentLang === 'en'): ?> -# Welcome -This page is only in English. - -# Under Construction -This page is not yet translated. - -``` - -## SEO Considerations - -### Add hreflang Tags - -In your custom base template: - -```php - - - - availableLangs as $lang): ?> - defaultLang - ? 'https://yoursite.com/' . trim($ctx->requestPath, '/') - : 'https://yoursite.com/' . $lang . '/' . trim($ctx->requestPath, '/'); - ?> - - - - - -``` - -### Language-Specific Metadata - -Add language attributes: - -```php - -``` - -## Testing Your Multi-Language Site - -1. **Visit default language**: `http://localhost:8000/about/` -2. **Visit Norwegian**: `http://localhost:8000/no/about/` -3. **Visit French**: `http://localhost:8000/fr/about/` -4. **Check navigation**: Ensure links include language prefix -5. **Test translation strings**: Verify UI text changes per language -6. **Check blog listings**: Confirm language-specific posts appear correctly - -## Common Patterns - -### Blog in Multiple Languages - -Structure: -``` -content/blog/ -β”œβ”€β”€ metadata.ini # List template config -└── [date]-[slug]/ - β”œβ”€β”€ index.{lang}.md # One file per language - β”œβ”€β”€ cover.jpg # Shared assets - └── metadata.ini # Translated metadata -``` - -### Documentation in Multiple Languages - -Structure: -``` -content/docs/ -β”œβ”€β”€ metadata.ini # Template config -β”œβ”€β”€ 00-intro.md # Default language -β”œβ”€β”€ 00-intro.no.md # Norwegian -β”œβ”€β”€ 01-setup.md -β”œβ”€β”€ 01-setup.no.md -└── ... -``` - -### Mixed Content Strategy - -Not everything needs translation. You can have: -- English-only blog posts (no language suffix) -- Multi-language main pages (with language suffixes) -- Shared images and assets - -## Related - -- [Metadata Reference](../reference/metadata.md) -- [Configuration Reference](../reference/configuration.md) -- [Template Variables Reference](../reference/templates.md) diff --git a/docs/how-to/working-with-metadata.md b/docs/how-to/working-with-metadata.md deleted file mode 100644 index ad224b5..0000000 --- a/docs/how-to/working-with-metadata.md +++ /dev/null @@ -1,481 +0,0 @@ -# How to Work with Metadata - -This guide shows you how to use `metadata.ini` files to control page behavior, appearance, and content. - -## What is Metadata? - -Metadata provides structured information about your content directories without cluttering your content files. It's stored in `metadata.ini` files using the INI format. - -## Basic Metadata File - -Create `metadata.ini` in any content directory: - -```ini -title = "My Page Title" -date = "2025-11-02" -summary = "A brief description of this page." -``` - -## Common Metadata Fields - -### Title - -Controls the displayed title (overrides automatic title extraction): - -```ini -title = "Custom Page Title" -``` - -If not provided, FolderWeb extracts the title from: -1. First H1 heading in content (`# Title` in Markdown) -2. Folder name (as fallback) - -### Date - -Set an explicit date (overrides folder name date extraction): - -```ini -date = "2025-11-02" -``` - -Format: `YYYY-MM-DD` - -FolderWeb automatically formats this in Norwegian style: "2. november 2025" - -### Summary - -Add a summary for list views: - -```ini -summary = "This appears in blog listings and card grids." -``` - -Summaries are displayed in: -- List views -- Grid layouts -- Card grids - -## Navigation Control - -### Adding to Menu - -```ini -menu = true -menu_order = 1 -``` - -- **menu**: Set to `true` to include in site navigation -- **menu_order**: Controls order (lower numbers appear first) - -**Example** - Setting up main navigation: - -**content/blog/metadata.ini**: -```ini -menu = true -menu_order = 1 -title = "Blog" -``` - -**content/about/metadata.ini**: -```ini -menu = true -menu_order = 2 -title = "About" -``` - -**content/contact/metadata.ini**: -```ini -menu = true -menu_order = 3 -title = "Contact" -``` - -Result: Navigation shows "Blog", "About", "Contact" in that order. - -## Template Control - -### Choosing List Template - -For directories with subdirectories, control which list template is used: - -```ini -page_template = "list-grid" -``` - -Available templates: -- `list` - Simple list (default) -- `list-grid` - Grid with cover images -- `list-card-grid` - Card-style grid (supports PDFs, external links) -- `list-faq` - Expandable FAQ format - -**Example** - Blog with grid layout: - -**content/blog/metadata.ini**: -```ini -title = "Blog" -page_template = "list-grid" -``` - -## External Redirects - -Make a directory item link externally (used with `list-card-grid`): - -```ini -redirect = "https://example.com" -``` - -**Example** - Portfolio with external links: - -**content/portfolio/project-live-site/metadata.ini**: -```ini -title = "Visit Live Site" -summary = "Check out the deployed project." -redirect = "https://myproject.com" -``` - -When using the `list-card-grid` template, this creates a card that links to the external URL instead of an internal page. - -## Multi-Language Metadata - -Use sections for language-specific overrides: - -```ini -; Default language values -title = "About Us" -summary = "Learn more about our company." - -[no] -title = "Om Oss" -summary = "LΓ¦r mer om vΓ₯rt selskap." -slug = "om-oss" - -[fr] -title = "Γ€ Propos" -summary = "DΓ©couvrez notre entreprise." -slug = "a-propos" -``` - -Language sections override base values for that language. - -### Translated Slugs - -The `slug` field in language sections changes the URL: - -```ini -[no] -slug = "om-oss" -``` - -Now the Norwegian version is accessible at `/no/om-oss/` instead of `/no/about/`. - -## Custom Metadata Fields - -You can add any custom fields you need: - -```ini -title = "Article Title" -author = "Jane Doe" -reading_time = "5 min" -difficulty = "intermediate" -featured = true -``` - -Access these in custom templates: - -```php - -

By

- - - - - -``` - -## Arrays in Metadata - -INI format supports arrays using repeated keys: - -```ini -tags[] = "PHP" -tags[] = "Web Development" -tags[] = "Tutorial" - -categories[] = "Programming" -categories[] = "Backend" -``` - -Access in templates: - -```php - -
- - - -
- -``` - -## Boolean Values - -Use `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off`: - -```ini -menu = true -featured = yes -draft = false -``` - -## Comments - -Add comments with `;` or `#`: - -```ini -; This is a comment -title = "My Page" - -# This is also a comment -date = "2025-11-02" -``` - -## Metadata Inheritance - -Metadata does **not** inherit from parent directories. Each directory needs its own `metadata.ini`. - -## Metadata for List Items - -When a directory is displayed in a list view, FolderWeb loads its metadata: - -**content/blog/2025-11-01-first-post/metadata.ini**: -```ini -title = "My First Blog Post" -date = "2025-11-01" -summary = "An introduction to blogging with FolderWeb." -``` - -This metadata appears in the blog listing at `/blog/`. - -## Complete Example: Blog Setup - -### Blog Directory Metadata - -**content/blog/metadata.ini**: -```ini -title = "Blog" -menu = true -menu_order = 1 -page_template = "list-grid" - -[no] -title = "Blogg" -slug = "blogg" -``` - -### Individual Post Metadata - -**content/blog/2025-11-02-web-performance/metadata.ini**: -```ini -title = "Optimizing Web Performance" -date = "2025-11-02" -summary = "Learn techniques to make your website faster." -author = "Jane Developer" -reading_time = "8 min" - -tags[] = "Performance" -tags[] = "Web Development" -tags[] = "Optimization" - -categories[] = "Technical" -categories[] = "Tutorial" - -[no] -title = "Optimalisering av Nettsideytelse" -summary = "LΓ¦r teknikker for Γ₯ gjΓΈre nettsiden din raskere." -``` - -## Accessing Metadata in Templates - -### In Page Templates - -```php - - -
-
-

-

By

-
- - - - -
- - - -
- -
-``` - -### In List Templates - -Each item in `$items` includes its metadata: - -```php - -
-

- - - -

- - - - - - -

- - - - - - - - Download PDF - - - - - Visit External Link - - -
- -``` - -## Debugging Metadata - -### Check if Metadata is Loaded - -In your template, dump the metadata: - -```php -
-``` - -Or for list items: - -```php -
-``` - -### Verify INI Syntax - -Use PHP to test your INI file: - -```bash -php -r "print_r(parse_ini_file('content/blog/metadata.ini', true));" -``` - -This shows parsed values and helps identify syntax errors. - -## Best Practices - -### Use Consistent Field Names - -Stick to standard fields for common data: -- `title` for titles -- `date` for dates -- `summary` for summaries -- `author` for authors - -### Escape Output - -Always escape metadata in templates: - -```php - -``` - -### Provide Defaults - -Use null coalescing for missing fields: - -```php -$author = $metadata['author'] ?? 'Anonymous'; -$date = $metadata['date'] ?? 'Unknown date'; -``` - -### Keep It Simple - -Only add metadata fields you actually use. Don't over-engineer. - -### Use Comments - -Document non-obvious metadata: - -```ini -; Featured articles appear at the top of the homepage -featured = true - -; Legacy field kept for backwards compatibility -old_url = "/blog/old-slug/" -``` - -## Common Patterns - -### Blog Post - -```ini -title = "Post Title" -date = "2025-11-02" -summary = "Brief description" -author = "Author Name" -tags[] = "tag1" -tags[] = "tag2" -``` - -### Documentation Page - -```ini -title = "API Reference" -menu = true -menu_order = 3 -page_template = "list" -``` - -### Portfolio Item - -```ini -title = "Project Name" -date = "2025-11-02" -summary = "Project description" -redirect = "https://live-demo.com" -``` - -### FAQ Section - -```ini -title = "Frequently Asked Questions" -menu = true -menu_order = 4 -page_template = "list-faq" -``` - -## Related - -- [Multi-Language Guide](multi-language.md) -- [Custom Templates](custom-templates.md) -- [Metadata Reference](../reference/metadata.md) -- [Template Variables Reference](../reference/templates.md) diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 2a0e5b2..0000000 --- a/docs/index.md +++ /dev/null @@ -1,309 +0,0 @@ -# FolderWeb Documentation - -Complete documentation for FolderWeb, a minimalist file-based PHP framework for content websites. - -## What is FolderWeb? - -FolderWeb is a file-based content publishing framework. Drop Markdown files in folders, and they become pages. No database, no build process, no JavaScript required. Just PHP, HTML, and CSS. - -**Core principle**: Your file system is your content management system. - -## Documentation Structure - -This documentation follows the [Diataxis framework](https://diataxis.fr/), organizing content into four types: - -### πŸŽ“ Tutorial - -**Learning-oriented**: Get started with FolderWeb - -- [Getting Started](tutorial/00-getting-started.md) - Build your first site in 10 minutes - -**Start here** if you're new to FolderWeb. - -### πŸ“‹ How-To Guides - -**Task-oriented**: Solve specific problems - -- [Custom Templates](how-to/custom-templates.md) - Override default templates -- [Custom Styles](how-to/custom-styles.md) - Customize appearance with CSS -- [Multi-Language Sites](how-to/multi-language.md) - Set up multiple languages -- [Working with Metadata](how-to/working-with-metadata.md) - Use metadata.ini files - -**Use these** when you need to accomplish a specific task. - -### πŸ“– Reference - -**Information-oriented**: Look up technical details - -- [File Structure](reference/file-structure.md) - Complete directory layout -- [Metadata](reference/metadata.md) - All metadata fields -- [Templates](reference/templates.md) - Template variables and usage -- [Configuration](reference/configuration.md) - Configuration options -- [CSS Variables](reference/css-variables.md) - Styling customization - -**Consult these** when you need precise technical information. - -### πŸ’‘ Explanation - -**Understanding-oriented**: Understand concepts and design - -- [Philosophy](explanation/philosophy.md) - Design principles and thinking -- [Architecture](explanation/architecture.md) - How FolderWeb works - -**Read these** to understand why FolderWeb works the way it does. - -## Quick Links - -### Common Tasks - -- **Create a page**: Drop `index.md` in a folder -- **Create a blog**: Make a folder with subdirectories -- **Add navigation**: Set `menu = true` in `metadata.ini` -- **Customize look**: Override `/custom/styles/base.css` -- **Use custom template**: Set `page_template = "template-name"` in metadata -- **Multi-language**: Configure languages and add `.{lang}.md` files - -### Key Concepts - -- **File-based routing**: `content/blog/post/` β†’ `yoursite.com/blog/post/` -- **Template fallback**: Custom templates override defaults -- **Language prefixes**: `/en/page/` for English, `/no/page/` for Norwegian -- **Metadata inheritance**: None - each directory has its own `metadata.ini` -- **Content types**: Single-file, multi-file, or list view - -## Quick Start - -```bash -# 1. Create project -mkdir my-site && cd my-site - -# 2. Copy framework files -cp -r /path/to/folderweb/app ./app - -# 3. Create content -mkdir content -echo "# Hello World" > content/index.md - -# 4. Start server -php -S localhost:8000 -t . app/router.php - -# 5. Visit http://localhost:8000 -``` - -## System Requirements - -- **PHP**: 8.4 or higher -- **Web server**: Apache, Nginx, or PHP built-in server -- **Extensions**: Standard PHP (no special extensions needed) - -## File Structure Overview - -``` -project/ -β”œβ”€β”€ app/ # Framework (never modify) -β”‚ β”œβ”€β”€ router.php # Entry point -β”‚ β”œβ”€β”€ content.php # Content discovery -β”‚ β”œβ”€β”€ rendering.php # Template rendering -β”‚ └── default/ # Default templates, styles, languages -β”œβ”€β”€ content/ # Your website content -β”‚ β”œβ”€β”€ index.md # Home page -β”‚ β”œβ”€β”€ about/ # About page -β”‚ └── blog/ # Blog with posts -└── custom/ # Your customizations - β”œβ”€β”€ templates/ # Custom templates - β”œβ”€β”€ styles/ # Custom CSS - β”œβ”€β”€ languages/ # Custom translations - └── config.ini # Configuration overrides -``` - -## Core Features - -### File-Based Routing - -Your folder structure defines your URLs: - -``` -content/blog/2025-11-02-post/ β†’ /blog/2025-11-02-post/ -``` - -No route configuration needed. - -### Multiple Content Types - -- **Single-file page**: One file in a directory -- **Multi-file page**: Multiple files combined into one page -- **List view**: Directory with subdirectories becomes a listing - -### Template System - -Six templates included: -- `base.php` - HTML wrapper -- `page.php` - Page wrapper -- `list.php` - Simple list -- `list-grid.php` - Grid with images -- `list-card-grid.php` - Card grid -- `list-faq.php` - Expandable FAQ - -Override any template in `/custom/templates/`. - -### Multi-Language Support - -Configure languages: -```ini -[languages] -default = "en" -available = "en,no,fr" -``` - -Create language-specific files: -``` -index.md # English (default) -index.no.md # Norwegian -index.fr.md # French -``` - -URLs automatically prefixed: `/`, `/no/`, `/fr/` - -### Metadata System - -Control behavior with `metadata.ini`: - -```ini -title = "My Page" -date = "2025-11-02" -summary = "Page description" -menu = true -menu_order = 1 -page_template = "list-grid" -``` - -### Modern CSS - -Default styles use: -- CSS custom properties (variables) -- CSS nesting -- OKLCH colors -- Grid layouts -- Fluid typography with `clamp()` -- Logical properties - -Override in `/custom/styles/base.css`. - -## Philosophy Highlights - -- **Just enough, nothing more**: Minimal, maintainable code -- **Longevity over novelty**: Works today, works in 2035 -- **Files are content**: Portable, version-controllable -- **No JavaScript required**: Pure HTML and CSS -- **No build process**: Immediate feedback - -Read the full [Philosophy](explanation/philosophy.md) for more. - -## Example Use Cases - -### Personal Blog - -``` -content/ -β”œβ”€β”€ index.md # About me -β”œβ”€β”€ blog/ # Blog posts -β”‚ β”œβ”€β”€ metadata.ini # page_template = "list-grid" -β”‚ β”œβ”€β”€ 2025-11-01-post/ -β”‚ └── 2025-11-02-post/ -└── contact/ # Contact page - └── index.md -``` - -### Documentation Site - -``` -content/ -β”œβ”€β”€ index.md # Introduction -β”œβ”€β”€ getting-started/ # Multi-file tutorial -β”‚ β”œβ”€β”€ 00-install.md -β”‚ β”œβ”€β”€ 01-setup.md -β”‚ └── 02-first-steps.md -└── reference/ # API reference - β”œβ”€β”€ metadata.ini # page_template = "list" - β”œβ”€β”€ functions/ - └── classes/ -``` - -### Portfolio - -``` -content/ -β”œβ”€β”€ index.md # Homepage -β”œβ”€β”€ projects/ # Project grid -β”‚ β”œβ”€β”€ metadata.ini # page_template = "list-card-grid" -β”‚ β”œβ”€β”€ project-1/ -β”‚ β”‚ β”œβ”€β”€ index.md -β”‚ β”‚ β”œβ”€β”€ cover.jpg -β”‚ β”‚ └── metadata.ini # redirect = "https://project.com" -β”‚ └── project-2/ -└── about/ - └── index.md -``` - -## When to Use FolderWeb - -### βœ… Ideal For - -- Blogs and content sites -- Documentation -- Portfolios -- Marketing sites -- Personal websites -- Projects requiring longevity - -### ❌ Not Ideal For - -- User-generated content (no database/auth) -- E-commerce (use dedicated platform) -- Social networks (need real-time features) -- JavaScript-heavy SPAs -- Sites with thousands of pages (consider static generators) - -## Getting Help - -### Documentation - -- Follow the [Tutorial](tutorial/00-getting-started.md) step-by-step -- Check [How-To Guides](how-to/) for specific tasks -- Consult [Reference](reference/) for technical details -- Read [Explanation](explanation/) for concepts - -### Common Issues - -**Styles not loading**: Hard refresh (Ctrl+Shift+R or Cmd+Shift+R) - -**404 errors**: Check folder exists and has content files - -**Language not working**: Ensure language is in `available` config - -**Metadata not appearing**: Verify INI syntax with `parse_ini_file()` - -**Templates not found**: Check file exists in `/custom/templates/` - -## Contributing - -FolderWeb prioritizes stability and simplicity. Contributions should: -- Maintain simplicity -- Avoid dependencies -- Solve real problems -- Be maintainable long-term - -## License - -Check the project repository for license information. - -## Next Steps - -1. **New user?** Start with the [Getting Started Tutorial](tutorial/00-getting-started.md) -2. **Need to do something specific?** Browse [How-To Guides](how-to/) -3. **Want technical details?** Explore [Reference Documentation](reference/) -4. **Curious about design?** Read [Philosophy](explanation/philosophy.md) and [Architecture](explanation/architecture.md) - ---- - -**FolderWeb**: Simple, file-based content publishing for the long term. diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md deleted file mode 100644 index 038eeaa..0000000 --- a/docs/reference/configuration.md +++ /dev/null @@ -1,400 +0,0 @@ -# Configuration Reference - -Complete reference for FolderWeb configuration options. - -## Configuration File - -**Location**: `/custom/config.ini` (or `/app/config.ini` for defaults) - -**Format**: INI format with sections - -**Override Behavior**: Custom config values override defaults - -## Configuration Sections - -### [languages] - -Controls language support and defaults. - -```ini -[languages] -default = "en" -available = "en,no,fr" -``` - -#### default - -**Type**: String -**Required**: Yes -**Default**: `"en"` - -The primary language of your site. This language: -- Has no URL prefix -- Is used as fallback for missing translations -- Should match a translation file in `/custom/languages/` or `/app/default/languages/` - -**Examples**: -```ini -default = "en" ; English -default = "no" ; Norwegian -default = "fr" ; French -default = "de" ; German -``` - -#### available - -**Type**: Comma-separated string -**Required**: Yes -**Default**: `"en,no"` - -List of all languages supported by your site. Must include the default language. - -**Examples**: -```ini -; English only -available = "en" - -; English and Norwegian -available = "en,no" - -; Multiple languages -available = "en,no,fr,de,es" -``` - -**URL Structure**: -- Default language: `yoursite.com/page/` -- Other languages: `yoursite.com/fr/page/`, `yoursite.com/de/page/` - -## File Structure - -### Default Configuration - -**Location**: `/app/config.ini` - -```ini -[languages] -default = "no" -available = "no,en" -``` - -**Note**: Never modify `/app/config.ini` directly. - -### Custom Configuration - -**Location**: `/custom/config.ini` - -Create this file to override defaults: - -```ini -[languages] -default = "en" -available = "en,fr,de" -``` - -Only include settings you want to override. - -## Configuration Loading - -Configuration is loaded in this order: - -1. Load `/app/config.ini` (defaults) -2. Load `/custom/config.ini` if exists -3. Merge, with custom values overriding defaults - -Example: - -**app/config.ini**: -```ini -[languages] -default = "no" -available = "no,en" -``` - -**custom/config.ini**: -```ini -[languages] -default = "en" -``` - -**Result**: -```ini -[languages] -default = "en" ; From custom -available = "no,en" ; From default (not overridden) -``` - -## Complete Configuration Examples - -### Single Language Site - -```ini -[languages] -default = "en" -available = "en" -``` - -URLs: All at root level (`/page/`, `/blog/`, etc.) - -### Bilingual Site (English/Norwegian) - -```ini -[languages] -default = "en" -available = "en,no" -``` - -URLs: -- English: `/page/`, `/blog/` -- Norwegian: `/no/page/`, `/no/blog/` - -### Multilingual Site - -```ini -[languages] -default = "en" -available = "en,no,fr,de,es" -``` - -URLs: -- English (default): `/page/` -- Norwegian: `/no/page/` -- French: `/fr/page/` -- German: `/de/page/` -- Spanish: `/es/page/` - -## Language Codes - -Use ISO 639-1 two-letter codes: - -| Code | Language | -|------|----------| -| `en` | English | -| `no` | Norwegian | -| `fr` | French | -| `de` | German | -| `es` | Spanish | -| `it` | Italian | -| `pt` | Portuguese | -| `nl` | Dutch | -| `sv` | Swedish | -| `da` | Danish | -| `fi` | Finnish | -| `pl` | Polish | -| `ru` | Russian | -| `ja` | Japanese | -| `zh` | Chinese | -| `ko` | Korean | -| `ar` | Arabic | - -Full list: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes - -## Related Configuration - -### Translation Files - -For each language in `available`, create a translation file: - -**Pattern**: `/custom/languages/{lang}.ini` - -**Example** (with `available = "en,no,fr"`): -``` -custom/languages/ -β”œβ”€β”€ en.ini -β”œβ”€β”€ no.ini -└── fr.ini -``` - -See [Translation Reference](translations.md) for details. - -### Content Files - -Language-specific content uses the same codes: - -**Pattern**: `filename.{lang}.ext` - -**Examples**: -- `index.md` - Default language -- `index.no.md` - Norwegian -- `index.fr.md` - French - -See [Multi-Language Guide](../how-to/multi-language.md) for details. - -## Validation - -### Check Configuration - -Verify configuration is loaded correctly: - -**test-config.php**: -```php -defaultLang . "\n"; -echo "Available languages: " . implode(', ', $ctx->availableLangs) . "\n"; -echo "Current language: " . $ctx->currentLang . "\n"; -echo "Language prefix: " . $ctx->langPrefix . "\n"; -``` - -Run: -```bash -php test-config.php -``` - -### Common Errors - -**Missing default in available**: -```ini -; Wrong - default must be in available -[languages] -default = "en" -available = "no,fr" - -; Correct -[languages] -default = "en" -available = "en,no,fr" -``` - -**Invalid language codes**: -```ini -; Avoid - use ISO codes -available = "english,norwegian" - -; Correct - ISO 639-1 codes -available = "en,no" -``` - -**Typos in section names**: -```ini -; Wrong -[language] -default = "en" - -; Correct -[languages] -default = "en" -``` - -## Future Configuration Options - -FolderWeb is minimal by design. Currently, only language settings are configurable. - -Possible future additions: -- Date format preferences -- Timezone settings -- Content directory override -- Cache settings - -For now, these are handled through code or conventions. - -## Environment-Specific Configuration - -To use different configs per environment: - -**Option 1: Conditional Loading** - -**custom/config.ini**: -```ini -[languages] -default = "en" -available = "en,no" -``` - -**custom/config.dev.ini**: -```ini -[languages] -default = "en" -available = "en" -``` - -Modify `app/config.php` to load based on environment. - -**Option 2: Separate Deployments** - -Use different `custom/config.ini` files per deployment: -- Development: `/custom/config.ini` with dev settings -- Production: Different `/custom/config.ini` with prod settings - -## Configuration in Templates - -Access configuration through context object: - -```php - - - - - - - -currentLang === $ctx->defaultLang): ?> -

Viewing in default language

- - - -About -``` - -## Best Practices - -### Keep It Simple - -Only configure what's necessary. FolderWeb embraces sensible defaults. - -### Match Translation Files - -Ensure translation files exist for all languages: - -```ini -[languages] -available = "en,no,fr" -``` - -Requires: -- `custom/languages/en.ini` -- `custom/languages/no.ini` -- `custom/languages/fr.ini` - -### Choose Appropriate Default - -Your default language should be: -- Your primary audience's language -- The language with most content -- The language you'll maintain long-term - -### Document Your Choices - -Add comments to explain configuration: - -```ini -; Site uses English as primary language (most content) -; Norwegian and French are secondary translations -[languages] -default = "en" -available = "en,no,fr" -``` - -## Testing Configuration Changes - -After changing configuration: - -1. **Clear browser cache** (Ctrl+Shift+R or Cmd+Shift+R) -2. **Test default language**: Visit `/` -3. **Test other languages**: Visit `/no/`, `/fr/`, etc. -4. **Check navigation**: Ensure menu links include language prefix -5. **Verify translations**: Check UI strings change per language -6. **Test language switcher**: Confirm switching works - -## Related - -- [Multi-Language Guide](../how-to/multi-language.md) -- [Translation Reference](translations.md) -- [Metadata Reference](metadata.md) -- [Context Object Reference](templates.md#context-object) diff --git a/docs/reference/css-variables.md b/docs/reference/css-variables.md deleted file mode 100644 index 135978d..0000000 --- a/docs/reference/css-variables.md +++ /dev/null @@ -1,538 +0,0 @@ -# CSS Variables Reference - -Complete reference for all CSS custom properties available in FolderWeb. - -## Overview - -FolderWeb uses CSS custom properties (variables) for theming. Override these in `/custom/styles/base.css` to customize your site's appearance. - -## Color Variables - -### Primary Colors - -```css -:root { - --color-primary: oklch(0.65 0.15 250); - --color-secondary: oklch(0.50 0.12 250); - --color-light: oklch(0.97 0.01 250); - --color-grey: oklch(0.37 0 0); -} -``` - -| Variable | Default | Description | -|----------|---------|-------------| -| `--color-primary` | Blue (OKLCH) | Primary brand color, links, buttons | -| `--color-secondary` | Dark blue (OKLCH) | Secondary accents, hover states | -| `--color-light` | Off-white (OKLCH) | Background, light sections | -| `--color-grey` | Dark grey | Body text, headings | - -### OKLCH Color Space - -FolderWeb uses OKLCH for perceptually uniform colors: - -```css -oklch(lightness chroma hue) -``` - -- **Lightness**: 0 (black) to 1 (white) -- **Chroma**: 0 (grey) to ~0.4 (vibrant) -- **Hue**: 0-360 degrees - -**Examples**: -```css -/* Blue hues (250Β°) */ ---color-primary: oklch(0.65 0.15 250); - -/* Orange hues (30Β°) */ ---color-primary: oklch(0.65 0.20 30); - -/* Green hues (150Β°) */ ---color-primary: oklch(0.60 0.15 150); - -/* Red hues (0Β°) */ ---color-primary: oklch(0.60 0.20 0); - -/* Purple hues (300Β°) */ ---color-primary: oklch(0.60 0.18 300); -``` - -### Alternative Color Formats - -You can use hex, rgb, or hsl instead: - -```css -:root { - /* Hex */ - --color-primary: #4169E1; - --color-secondary: #1E3A8A; - - /* RGB */ - --color-primary: rgb(65, 105, 225); - --color-secondary: rgb(30, 58, 138); - - /* HSL */ - --color-primary: hsl(225, 73%, 57%); - --color-secondary: hsl(225, 64%, 33%); -} -``` - -## Typography Variables - -### Font Families - -```css -:root { - --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - --font-heading: Georgia, "Times New Roman", serif; -} -``` - -| Variable | Default | Description | -|----------|---------|-------------| -| `--font-body` | System sans-serif stack | Body text, paragraphs | -| `--font-heading` | Serif stack | Headings (h1-h6) | - -**Custom Fonts**: -```css -@font-face { - font-family: 'MyFont'; - src: url('/custom/fonts/MyFont.woff2') format('woff2'); - font-weight: 400; - font-style: normal; - font-display: swap; -} - -:root { - --font-body: 'MyFont', sans-serif; -} -``` - -### Font Sizes - -```css -:root { - --font-size-base: 1.125rem; /* 18px */ - --font-size-small: 0.875rem; /* 14px */ -} -``` - -| Variable | Default | Description | -|----------|---------|-------------| -| `--font-size-base` | 1.125rem (18px) | Body text size | -| `--font-size-small` | 0.875rem (14px) | Small text, metadata | - -**Responsive Sizing**: -```css -:root { - /* Fluid typography */ - --font-size-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem); -} - -h1 { - font-size: clamp(2rem, 1.5rem + 2vw, 3.5rem); -} -``` - -### Line Heights - -```css -:root { - --line-height-base: 1.6; - --line-height-heading: 1.2; -} -``` - -| Variable | Default | Description | -|----------|---------|-------------| -| `--line-height-base` | 1.6 | Body text line height | -| `--line-height-heading` | 1.2 | Heading line height | - -## Spacing Variables - -```css -:root { - --spacing-unit: 1.5rem; /* 24px */ - --spacing-small: 0.75rem; /* 12px */ - --spacing-large: 3rem; /* 48px */ -} -``` - -| Variable | Default | Description | -|----------|---------|-------------| -| `--spacing-unit` | 1.5rem (24px) | Base spacing unit | -| `--spacing-small` | 0.75rem (12px) | Small gaps | -| `--spacing-large` | 3rem (48px) | Large gaps, section spacing | - -**Usage**: -```css -.card { - padding: var(--spacing-unit); - margin-block-end: var(--spacing-large); -} - -.tag { - padding: var(--spacing-small); -} -``` - -**Responsive Spacing**: -```css -:root { - --spacing-unit: clamp(1rem, 0.8rem + 1vw, 2rem); -} -``` - -## Layout Variables - -```css -:root { - --max-width: 70rem; /* 1120px */ - --border-radius: 4px; -} -``` - -| Variable | Default | Description | -|----------|---------|-------------| -| `--max-width` | 70rem (1120px) | Content max-width | -| `--border-radius` | 4px | Corner rounding | - -**Usage**: -```css -.contain { - max-inline-size: var(--max-width); - margin-inline: auto; -} - -.card { - border-radius: var(--border-radius); -} -``` - -## Complete Variable List - -```css -:root { - /* Colors */ - --color-primary: oklch(0.65 0.15 250); - --color-secondary: oklch(0.50 0.12 250); - --color-light: oklch(0.97 0.01 250); - --color-grey: oklch(0.37 0 0); - - /* Typography */ - --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - --font-heading: Georgia, "Times New Roman", serif; - --font-size-base: 1.125rem; - --font-size-small: 0.875rem; - --line-height-base: 1.6; - --line-height-heading: 1.2; - - /* Spacing */ - --spacing-unit: 1.5rem; - --spacing-small: 0.75rem; - --spacing-large: 3rem; - - /* Layout */ - --max-width: 70rem; - --border-radius: 4px; -} -``` - -## Customization Examples - -### Orange Theme - -```css -:root { - --color-primary: oklch(0.65 0.20 30); - --color-secondary: oklch(0.50 0.18 30); - --color-light: oklch(0.97 0.01 30); -} -``` - -### Dark Mode - -```css -@media (prefers-color-scheme: dark) { - :root { - --color-primary: oklch(0.70 0.15 250); - --color-secondary: oklch(0.80 0.12 250); - --color-light: oklch(0.25 0 0); - --color-grey: oklch(0.90 0 0); - } -} -``` - -### Large Text - -```css -:root { - --font-size-base: 1.25rem; /* 20px */ - --line-height-base: 1.7; - --spacing-unit: 2rem; -} -``` - -### Tight Layout - -```css -:root { - --max-width: 50rem; /* 800px */ - --spacing-unit: 1rem; /* 16px */ - --spacing-large: 2rem; /* 32px */ -} -``` - -### Rounded Design - -```css -:root { - --border-radius: 12px; -} -``` - -## Using Variables - -### In Your Styles - -```css -.card { - background: var(--color-light); - color: var(--color-grey); - padding: var(--spacing-unit); - border-radius: var(--border-radius); -} - -.button { - background: var(--color-primary); - color: white; - padding: var(--spacing-small) var(--spacing-unit); - border-radius: var(--border-radius); -} - -.button:hover { - background: var(--color-secondary); -} -``` - -### With Fallbacks - -Provide fallbacks for older browsers: - -```css -.card { - background: #F5F5F5; /* Fallback */ - background: var(--color-light); /* Variable */ -} -``` - -### With calc() - -Combine with calculations: - -```css -.card { - padding: calc(var(--spacing-unit) * 2); - margin-block-end: calc(var(--spacing-large) - 1rem); -} -``` - -### With color-mix() - -Create variations: - -```css -.button { - background: var(--color-primary); -} - -.button:hover { - background: color-mix(in oklch, var(--color-primary), black 10%); -} - -.button-light { - background: color-mix(in oklch, var(--color-primary), white 80%); -} -``` - -## Adding Custom Variables - -Define your own variables: - -```css -:root { - /* Custom color palette */ - --color-accent: oklch(0.70 0.15 180); - --color-warning: oklch(0.70 0.20 60); - --color-danger: oklch(0.60 0.20 10); - --color-success: oklch(0.65 0.15 140); - - /* Custom spacing */ - --spacing-xs: 0.25rem; - --spacing-xl: 4rem; - --spacing-2xl: 6rem; - - /* Custom typography */ - --font-mono: 'Monaco', 'Courier New', monospace; - --font-size-large: 1.5rem; - --font-size-xlarge: 2rem; - - /* Custom layout */ - --sidebar-width: 20rem; - --header-height: 4rem; - --content-gap: 2rem; -} -``` - -Use them: - -```css -.sidebar { - width: var(--sidebar-width); - background: var(--color-light); -} - -code { - font-family: var(--font-mono); - background: var(--color-accent); - padding: var(--spacing-xs); -} -``` - -## Scoped Variables - -Override variables for specific sections: - -```css -/* Global defaults */ -:root { - --color-primary: oklch(0.65 0.15 250); -} - -/* Blog section uses green */ -.section-blog { - --color-primary: oklch(0.60 0.15 150); -} - -/* About page uses orange */ -.page-about { - --color-primary: oklch(0.65 0.20 30); -} - -/* Variables cascade to children */ -.section-blog .button { - background: var(--color-primary); /* Green in blog */ -} -``` - -## Responsive Variables - -Change variables at breakpoints: - -```css -:root { - --spacing-unit: 1rem; - --font-size-base: 1rem; - --max-width: 60rem; -} - -@media (min-width: 768px) { - :root { - --spacing-unit: 1.5rem; - --font-size-base: 1.125rem; - --max-width: 70rem; - } -} - -@media (min-width: 1200px) { - :root { - --spacing-unit: 2rem; - --font-size-base: 1.25rem; - --max-width: 80rem; - } -} -``` - -## Browser Support - -CSS custom properties are supported in all modern browsers: -- Chrome 49+ -- Firefox 31+ -- Safari 9.1+ -- Edge 15+ - -For older browsers, provide fallbacks or use PostCSS with custom properties plugin. - -## Debugging Variables - -Inspect variables in browser DevTools: - -1. Right-click element β†’ Inspect -2. Check "Computed" tab -3. Scroll to custom properties section -4. See resolved values - -Or log in console: - -```javascript -getComputedStyle(document.documentElement).getPropertyValue('--color-primary') -``` - -## Best Practices - -### Use Semantic Names - -```css -/* Good - semantic */ ---color-primary ---color-text ---color-background - -/* Avoid - non-semantic */ ---color-blue ---color-444 -``` - -### Group Related Variables - -```css -:root { - /* Colors */ - --color-primary: ...; - --color-secondary: ...; - - /* Typography */ - --font-body: ...; - --font-heading: ...; - - /* Spacing */ - --spacing-unit: ...; -} -``` - -### Document Your Variables - -```css -:root { - /* Brand colors from design system */ - --color-primary: oklch(0.65 0.15 250); /* Blue - primary CTA */ - --color-secondary: oklch(0.50 0.12 250); /* Dark blue - accents */ - - /* Layout constraints */ - --max-width: 70rem; /* 1120px - content max width */ -} -``` - -### Provide Fallbacks - -```css -.card { - background: #F5F5F5; - background: var(--color-light); -} -``` - -## Related - -- [Custom Styles Guide](../how-to/custom-styles.md) -- [Template Reference](templates.md) -- [File Structure Reference](file-structure.md) diff --git a/docs/reference/file-structure.md b/docs/reference/file-structure.md deleted file mode 100644 index 9e86833..0000000 --- a/docs/reference/file-structure.md +++ /dev/null @@ -1,394 +0,0 @@ -# File Structure Reference - -Complete reference for FolderWeb's file and directory structure. - -## Root Structure - -``` -project/ -β”œβ”€β”€ app/ # Framework core (never modify) -β”œβ”€β”€ content/ # Your website content -β”œβ”€β”€ custom/ # Your customizations -└── .htaccess # Web server configuration (optional) -``` - -## App Directory (Framework Core) - -``` -app/ -β”œβ”€β”€ router.php # Main entry point and request router -β”œβ”€β”€ content.php # Content discovery and parsing functions -β”œβ”€β”€ rendering.php # Template rendering engine -β”œβ”€β”€ context.php # Context object (readonly class) -β”œβ”€β”€ config.php # Configuration loader -β”œβ”€β”€ helpers.php # Utility functions -β”œβ”€β”€ constants.php # File extension constants -β”œβ”€β”€ static.php # Static file server -β”œβ”€β”€ config.ini # Default configuration -β”œβ”€β”€ default/ # Default files (fallback) -β”‚ β”œβ”€β”€ templates/ # Default templates -β”‚ β”‚ β”œβ”€β”€ base.php # HTML wrapper -β”‚ β”‚ β”œβ”€β”€ page.php # Page wrapper -β”‚ β”‚ β”œβ”€β”€ list.php # Simple list -β”‚ β”‚ β”œβ”€β”€ list-grid.php # Grid layout -β”‚ β”‚ β”œβ”€β”€ list-card-grid.php # Card grid -β”‚ β”‚ └── list-faq.php # FAQ layout -β”‚ β”œβ”€β”€ styles/ # Default CSS -β”‚ β”‚ └── base.css # Main stylesheet -β”‚ β”œβ”€β”€ languages/ # Default translations -β”‚ β”‚ β”œβ”€β”€ en.ini # English -β”‚ β”‚ └── no.ini # Norwegian -β”‚ └── content/ # Demo content (fallback) -└── vendor/ # Third-party libraries - └── Parsedown.php # Markdown parser -``` - -**Important**: Never modify files in `/app/`. All customization goes in `/custom/`. - -## Custom Directory - -``` -custom/ -β”œβ”€β”€ templates/ # Override templates -β”‚ β”œβ”€β”€ base.php # Custom base template -β”‚ β”œβ”€β”€ page.php # Custom page template -β”‚ β”œβ”€β”€ list-*.php # Custom list templates -β”‚ └── [custom].php # Your custom templates -β”œβ”€β”€ styles/ # Override styles -β”‚ └── base.css # Custom stylesheet -β”œβ”€β”€ languages/ # Override translations -β”‚ β”œβ”€β”€ en.ini # English translations -β”‚ β”œβ”€β”€ no.ini # Norwegian translations -β”‚ └── [lang].ini # Other languages -β”œβ”€β”€ fonts/ # Custom web fonts -β”‚ └── *.woff2 # Font files -β”œβ”€β”€ assets/ # Root-level assets -β”‚ β”œβ”€β”€ favicon.ico # Site favicon -β”‚ β”œβ”€β”€ robots.txt # Robots file -β”‚ β”œβ”€β”€ logo.svg # Logo -β”‚ └── [any file] # Served at root level -└── config.ini # Configuration overrides -``` - -## Content Directory - -Your content directory contains all your website pages and assets. - -### Basic Structure - -``` -content/ -β”œβ”€β”€ index.md # Home page -β”œβ”€β”€ about/ # About page -β”‚ β”œβ”€β”€ index.md # Page content -β”‚ β”œβ”€β”€ metadata.ini # Page metadata -β”‚ └── team-photo.jpg # Page asset -β”œβ”€β”€ blog/ # Blog (list view) -β”‚ β”œβ”€β”€ metadata.ini # Blog configuration -β”‚ β”œβ”€β”€ 2025-11-01-first-post/ -β”‚ β”‚ β”œβ”€β”€ index.md # Post content -β”‚ β”‚ β”œβ”€β”€ cover.jpg # Cover image -β”‚ β”‚ └── metadata.ini # Post metadata -β”‚ └── 2025-11-02-second-post/ -β”‚ β”œβ”€β”€ index.md -β”‚ β”œβ”€β”€ cover.webp -β”‚ └── metadata.ini -└── docs/ # Multi-file page - β”œβ”€β”€ 00-intro.md # Section 1 - β”œβ”€β”€ 01-setup.md # Section 2 - β”œβ”€β”€ 02-usage.md # Section 3 - └── metadata.ini # Page metadata -``` - -### Content Types - -#### Single-File Page - -``` -content/about/ -└── index.md -``` - -URL: `/about/` - -#### Multi-File Page - -``` -content/docs/ -β”œβ”€β”€ 00-intro.md -β”œβ”€β”€ 01-setup.md -└── 02-usage.md -``` - -URL: `/docs/` (all files render as one page) - -#### List View (Directory with Subdirectories) - -``` -content/blog/ -β”œβ”€β”€ metadata.ini -β”œβ”€β”€ 2025-11-01-post/ -β”‚ └── index.md -└── 2025-11-02-post/ - └── index.md -``` - -URL: `/blog/` (shows list of posts) - -## File Naming Conventions - -### Content Files - -Supported extensions: -- `.md` - Markdown (parsed with Parsedown) -- `.html` - HTML (included as-is) -- `.php` - PHP (executed with access to `$ctx`) - -### Language-Specific Files - -Format: `filename.{lang}.ext` - -Examples: -- `index.md` - Default language -- `index.no.md` - Norwegian -- `index.fr.md` - French -- `about.en.md` - English - -### Date Prefixes - -Format: `YYYY-MM-DD-slug` - -Examples: -- `2025-11-01-my-post` -- `2025-11-02-another-post` - -Dates are automatically extracted and formatted. - -### Cover Images - -Filename: `cover.{ext}` - -Supported formats: -- `cover.jpg` -- `cover.jpeg` -- `cover.png` -- `cover.webp` -- `cover.gif` - -Automatically detected in list views. - -### PDF Files - -Any `.pdf` file in a directory is automatically linked in grid layouts. - -### Metadata Files - -Filename: `metadata.ini` - -Format: INI with optional language sections. - -## File Discovery Order - -### Content File Priority - -For multi-file pages, files are rendered in alphanumerical order: - -``` -content/docs/ -β”œβ”€β”€ 00-intro.md # First -β”œβ”€β”€ 01-setup.md # Second -β”œβ”€β”€ 02-usage.md # Third -└── 99-appendix.md # Last -``` - -Use numerical prefixes to control order. - -### Template Resolution - -Templates are resolved with custom fallback: - -1. `/custom/templates/{name}.php` -2. `/app/default/templates/{name}.php` - -### CSS Resolution - -Stylesheets are resolved with custom fallback: - -1. `/custom/styles/base.css` -2. `/app/default/styles/base.css` - -### Translation Resolution - -Translations are resolved with custom fallback: - -1. `/custom/languages/{lang}.ini` -2. `/app/default/languages/{lang}.ini` - -### Configuration Resolution - -Configuration is merged: - -1. Load `/app/config.ini` -2. Merge with `/custom/config.ini` if exists - -Custom values override defaults. - -## URL Mapping - -### Basic Mapping - -``` -/content/about/index.md β†’ /about/ -/content/blog/ β†’ /blog/ -/content/docs/ β†’ /docs/ -``` - -### Language Prefixes - -Default language (no prefix): -``` -/content/about/index.md β†’ /about/ -``` - -Other languages (with prefix): -``` -/content/about/index.no.md β†’ /no/about/ -/content/about/index.fr.md β†’ /fr/about/ -``` - -### Translated Slugs - -With metadata slug overrides: -``` -content/about/metadata.ini: - [no] - slug = "om-oss" - - [fr] - slug = "a-propos" -``` - -URLs become: -- `/about/` (English) -- `/no/om-oss/` (Norwegian) -- `/fr/a-propos/` (French) - -### Trailing Slashes - -FolderWeb requires trailing slashes for directories. Missing slashes trigger 301 redirects: - -``` -/blog β†’ 301 redirect to β†’ /blog/ -``` - -## Special Files and Directories - -### System Files (Ignored) - -These files are automatically ignored: -- `.htaccess` -- `.git/` -- `.DS_Store` -- `node_modules/` -- Hidden files/directories (starting with `.`) - -### Index Files - -`index.md`, `index.html`, `index.php` are treated as directory content, not separate routes. - -### Metadata Files - -`metadata.ini` files are configuration, never rendered as content. - -## Asset Serving - -### Root-Level Assets - -Files in `/custom/assets/` are served at site root: - -``` -/custom/assets/robots.txt β†’ yoursite.com/robots.txt -/custom/assets/favicon.ico β†’ yoursite.com/favicon.ico -/custom/assets/logo.svg β†’ yoursite.com/logo.svg -``` - -### Content Assets - -Files in content directories are accessible at their directory URL: - -``` -/content/blog/2025-11-01-post/cover.jpg - β†’ yoursite.com/blog/2025-11-01-post/cover.jpg - -/content/about/team-photo.jpg - β†’ yoursite.com/about/team-photo.jpg -``` - -### CSS Files - -CSS is served with version hashing: - -``` -/custom/styles/base.css - β†’ yoursite.com/app/styles/base.css?v=abc123def456 -``` - -### Font Files - -Fonts in `/custom/fonts/` are accessible: - -``` -/custom/fonts/MyFont.woff2 - β†’ yoursite.com/custom/fonts/MyFont.woff2 -``` - -## File Permissions - -### Readable Files - -The web server must have read access to: -- All files in `/app/` -- All files in `/content/` -- All files in `/custom/` - -### Writable Files - -FolderWeb is read-only. No files require write access. - -### Security - -- Path validation prevents directory traversal -- Files must be within document root -- Realpath checks ensure proper resolution - -## Size Limits - -- **Read Tool**: Files larger than 50KB are truncated -- **No upload limits**: FolderWeb doesn't handle uploads -- **No execution limits**: Standard PHP limits apply - -## Caching - -### CSS Versioning - -CSS files are versioned with MD5 hash: - -```html - -``` - -Hash updates when file content changes. - -### No Built-in Cache - -FolderWeb doesn't implement content caching. Use: -- Web server caching (Apache, Nginx) -- Reverse proxy (Varnish, Cloudflare) -- PHP OPcache for code - -## Related - -- [Metadata Reference](metadata.md) -- [Configuration Reference](configuration.md) -- [How to Customize Templates](../how-to/custom-templates.md) -- [How to Customize Styles](../how-to/custom-styles.md) diff --git a/docs/reference/metadata.md b/docs/reference/metadata.md deleted file mode 100644 index a99faa4..0000000 --- a/docs/reference/metadata.md +++ /dev/null @@ -1,625 +0,0 @@ -# Metadata Reference - -Complete reference for all metadata fields and their usage in `metadata.ini` files. - -## File Format - -Metadata files use INI format: - -```ini -; Comments start with semicolon -key = "value" -array[] = "value1" -array[] = "value2" - -[section] -key = "section value" -``` - -## Standard Fields - -### title - -**Type**: String -**Used in**: All content types -**Purpose**: Override automatic title extraction - -```ini -title = "Custom Page Title" -``` - -If not provided, FolderWeb extracts title from: -1. First H1 heading (`# Title` in Markdown) -2. Folder name (as fallback) - -**Multi-language**: -```ini -title = "English Title" - -[no] -title = "Norsk Tittel" - -[fr] -title = "Titre FranΓ§ais" -``` - -### date - -**Type**: Date string (YYYY-MM-DD) -**Used in**: Blog posts, articles -**Purpose**: Override automatic date extraction - -```ini -date = "2025-11-02" -``` - -If not provided, FolderWeb extracts date from folder names like `2025-11-02-post-title`. - -Dates are automatically formatted in Norwegian style: "2. november 2025" - -### summary - -**Type**: String -**Used in**: List views -**Purpose**: Brief description for cards and listings - -```ini -summary = "A concise description that appears in blog listings." -``` - -**Multi-language**: -```ini -summary = "English summary" - -[no] -summary = "Norsk sammendrag" -``` - -### menu - -**Type**: Boolean -**Used in**: Top-level directories -**Purpose**: Include in site navigation - -```ini -menu = true -``` - -Accepted values: `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off` - -### menu_order - -**Type**: Integer -**Used in**: Navigation items -**Purpose**: Control navigation order (lower numbers first) - -```ini -menu = true -menu_order = 1 -``` - -### page_template - -**Type**: String -**Used in**: Directories with subdirectories -**Purpose**: Choose list template - -```ini -page_template = "list-grid" -``` - -Available values: -- `list` - Simple list (default) -- `list-grid` - Grid with cover images -- `list-card-grid` - Card-style grid -- `list-faq` - Expandable FAQ format -- Any custom template name (without `.php` extension) - -### slug - -**Type**: String -**Used in**: Language sections -**Purpose**: Translate URL segments - -```ini -[no] -slug = "om-oss" - -[fr] -slug = "a-propos" -``` - -The actual folder is `about/`, but URLs become: -- `/about/` (English) -- `/no/om-oss/` (Norwegian) -- `/fr/a-propos/` (French) - -### hide_list - -**Type**: Boolean -**Used in**: Directories with subdirectories -**Purpose**: Hide list of subfolders and show only page content - -```ini -hide_list = true -``` - -When enabled, directories with subfolders display as regular pages instead of showing a list view. Useful when you need subfolders for organization but want to present a single page to visitors. - -Accepted values: `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off` - -### redirect - -**Type**: URL string -**Used in**: List items (with `list-card-grid` template) -**Purpose**: Link to external site instead of internal page - -```ini -redirect = "https://example.com" -``` - -Creates an external link card in card grid layouts. - -## Custom Fields - -You can add any custom fields for use in your templates: - -### Common Custom Fields - -```ini -; Author information -author = "Jane Doe" -author_email = "jane@example.com" -author_url = "https://janedoe.com" - -; Content metadata -reading_time = "5 min" -difficulty = "intermediate" -featured = true - -; Categorization -tags[] = "PHP" -tags[] = "Tutorial" -tags[] = "Web Development" - -categories[] = "Programming" -categories[] = "Backend" - -; SEO -meta_description = "Complete guide to FolderWeb metadata" -meta_keywords = "metadata, ini, folderweb" - -; Social sharing -og_image = "/blog/post/social-card.jpg" -twitter_card = "summary_large_image" - -; Version tracking -version = "1.2.0" -last_updated = "2025-11-02" - -; Display options -hide_date = true -hide_author = false -hide_list = true -show_toc = true - -; External references -github_url = "https://github.com/user/repo" -demo_url = "https://demo.example.com" -download_url = "/files/document.pdf" -``` - -## Array Fields - -Use `[]` syntax for array values: - -```ini -tags[] = "PHP" -tags[] = "Web Development" -tags[] = "Tutorial" - -authors[] = "Jane Doe" -authors[] = "John Smith" - -related_posts[] = "/blog/post-1/" -related_posts[] = "/blog/post-2/" -``` - -Access in templates: - -```php - - - -``` - -## Boolean Values - -Accepted boolean formats: - -```ini -; True values -featured = true -featured = 1 -featured = yes -featured = on - -; False values -draft = false -draft = 0 -draft = no -draft = off -``` - -## Language Sections - -Use `[lang]` sections for multi-language overrides: - -```ini -; Base values (default language) -title = "About Us" -summary = "Learn about our company" -slug = "about" - -; Norwegian overrides -[no] -title = "Om Oss" -summary = "LΓ¦r om vΓ₯rt selskap" -slug = "om-oss" - -; French overrides -[fr] -title = "Γ€ Propos" -summary = "DΓ©couvrez notre entreprise" -slug = "a-propos" - -; Fields not overridden inherit base values -``` - -Language-specific fields override base fields for that language. - -## Comments - -Use `;` or `#` for comments: - -```ini -; This is a comment -title = "My Page" - -# This is also a comment -date = "2025-11-02" - -; Comments can be on same line as values -menu = true ; Include in navigation -``` - -## Special Characters - -### Quotes - -Use quotes for values with special characters: - -```ini -; Optional for simple values -title = Simple Title -title = "Simple Title" - -; Required for values with spaces at start/end -title = " Padded Title " - -; Required for values with special characters -summary = "Use \"quotes\" for nested quotes" -summary = 'Single quotes work too' -``` - -### Escape Sequences - -Standard INI escape sequences: - -```ini -; Newline -text = "First line\nSecond line" - -; Tab -text = "Indented\ttext" - -; Quote -text = "He said \"Hello\"" -``` - -## Metadata Location - -### Directory Metadata - -Place `metadata.ini` in the directory it describes: - -``` -content/blog/metadata.ini # Blog configuration -content/about/metadata.ini # About page metadata -``` - -### Item Metadata - -Place `metadata.ini` in each subdirectory: - -``` -content/blog/2025-11-01-post/metadata.ini # Post metadata -content/blog/2025-11-02-post/metadata.ini # Post metadata -``` - -## Metadata Scope - -Metadata applies only to its directory. **No inheritance** from parent directories. - -## Complete Examples - -### Blog Configuration - -**content/blog/metadata.ini**: -```ini -; Display settings -title = "Blog" -page_template = "list-grid" - -; Navigation -menu = true -menu_order = 1 - -; Multi-language -[no] -title = "Blogg" -slug = "blogg" - -[fr] -title = "Blog" -slug = "blog" -``` - -### Blog Post - -**content/blog/2025-11-02-web-performance/metadata.ini**: -```ini -; Basic information -title = "Optimizing Web Performance" -date = "2025-11-02" -summary = "Learn techniques to make your website faster." - -; Author information -author = "Jane Developer" -author_url = "https://jane.dev" - -; Content metadata -reading_time = "8 min" -difficulty = "intermediate" -featured = true - -; Categorization -tags[] = "Performance" -tags[] = "Web Development" -tags[] = "Optimization" - -categories[] = "Technical" -categories[] = "Tutorial" - -; SEO -meta_description = "Complete guide to web performance optimization" - -; Multi-language versions -[no] -title = "Optimalisering av Nettsideytelse" -summary = "LΓ¦r teknikker for Γ₯ gjΓΈre nettsiden din raskere." - -[fr] -title = "Optimisation des Performances Web" -summary = "Apprenez Γ  accΓ©lΓ©rer votre site web." -``` - -### Documentation Page - -**content/docs/metadata.ini**: -```ini -title = "Documentation" -menu = true -menu_order = 2 -page_template = "list" - -; Custom fields -show_toc = true -github_url = "https://github.com/user/repo" - -[no] -title = "Dokumentasjon" -slug = "dokumentasjon" -``` - -### Portfolio Project - -**content/portfolio/project-name/metadata.ini**: -```ini -title = "Project Name" -date = "2025-11-02" -summary = "Brief project description" - -; External links -redirect = "https://project-demo.com" -github_url = "https://github.com/user/project" - -; Project details -client = "Company Name" -role = "Lead Developer" -technologies[] = "PHP" -technologies[] = "HTML" -technologies[] = "CSS" - -[no] -title = "Prosjektnavn" -summary = "Kort prosjektbeskrivelse" -``` - -### FAQ Section - -**content/faq/metadata.ini**: -```ini -title = "Frequently Asked Questions" -menu = true -menu_order = 4 -page_template = "list-faq" - -[no] -title = "Ofte Stilte SpΓΈrsmΓ₯l" -slug = "oss" - -[fr] -title = "Questions FrΓ©quemment PosΓ©es" -slug = "faq" -``` - -## Accessing Metadata in Templates - -### In Page Templates - -Variable: `$pageMetadata` - -```php - - -
-

- - -

By

- - - - - -
- - - -
- -
-``` - -### In List Templates - -Variable: `$metadata` (directory metadata), `$items` (item metadata) - -```php - -

- - - -
-

- - - -

- - - - - - -

- -
- -``` - -## Validation - -### Check Syntax - -Test INI file parsing: - -```bash -php -r "print_r(parse_ini_file('content/blog/metadata.ini', true));" -``` - -### Common Errors - -**Unquoted special characters**: -```ini -; Wrong -title = Title with: special characters - -; Correct -title = "Title with: special characters" -``` - -**Missing array brackets**: -```ini -; Wrong (only last value kept) -tags = "PHP" -tags = "Tutorial" - -; Correct (array created) -tags[] = "PHP" -tags[] = "Tutorial" -``` - -**Invalid section names**: -```ini -; Wrong -[language.no] - -; Correct -[no] -``` - -## Best Practices - -### Always Escape Output - -```php - -``` - -### Provide Defaults - -```php -$author = $metadata['author'] ?? 'Anonymous'; -$tags = $metadata['tags'] ?? []; -``` - -### Check Before Using - -```php - -

By

- -``` - -### Use Consistent Field Names - -Stick to standard names across your site: -- `author` not `writer` or `by` -- `tags` not `keywords` or `topics` -- `summary` not `description` or `excerpt` - -### Document Custom Fields - -Add comments explaining non-obvious fields: - -```ini -; Featured articles appear at top of homepage -featured = true - -; External demo link (overrides internal page) -demo_url = "https://demo.example.com" -``` - -## Related - -- [Multi-Language Guide](../how-to/multi-language.md) -- [Working with Metadata](../how-to/working-with-metadata.md) -- [Template Variables Reference](templates.md) -- [Configuration Reference](configuration.md) diff --git a/docs/reference/templates.md b/docs/reference/templates.md deleted file mode 100644 index 0fe7beb..0000000 --- a/docs/reference/templates.md +++ /dev/null @@ -1,608 +0,0 @@ -# Template Reference - -Complete reference for all templates and available variables in FolderWeb. - -## Template System Overview - -FolderWeb uses a fallback template system: -1. Check `/custom/templates/{name}.php` -2. Fall back to `/app/default/templates/{name}.php` - -Templates are plain PHP files with access to specific variables and the context object. - -## Core Templates - -### base.php - -**Purpose**: HTML wrapper for all pages (header, navigation, footer) -**Used**: On every page render -**Customizable**: Yes - -**Available Variables**: - -| Variable | Type | Description | -|----------|------|-------------| -| `$content` | string | Rendered page content (HTML) | -| `$ctx` | Context | Full context object | -| `$currentLang` | string | Current language code (e.g., "en", "no") | -| `$navigation` | array | Navigation menu items | -| `$homeLabel` | string | Site title | -| `$translations` | array | UI translation strings | -| `$pageTitle` | string | Current page title | -| `$dirName` | string | Parent directory name | -| `$pageName` | string | Current page filename | - -**Example**: -```php - - - - - <?= htmlspecialchars($pageTitle) ?> | <?= htmlspecialchars($homeLabel) ?> - - - -
- -
- -
- -
- - - - -``` - -### page.php - -**Purpose**: Wrapper for single pages and articles -**Used**: For file and multi-file pages -**Customizable**: Yes - -**Available Variables**: - -| Variable | Type | Description | -|----------|------|-------------| -| `$content` | string | Rendered content (HTML) | -| `$pageMetadata` | array | Page metadata from metadata.ini | -| `$translations` | array | UI translation strings | - -**Example**: -```php -
- - - - - -
-``` - -## List Templates - -### list.php - -**Purpose**: Simple list view (default) -**Used**: Directories with subdirectories -**Customizable**: Yes - -**Available Variables**: - -| Variable | Type | Description | -|----------|------|-------------| -| `$items` | array | Array of subdirectory items | -| `$metadata` | array | Directory metadata | -| `$pageContent` | string | Optional intro content (HTML) | -| `$translations` | array | UI translation strings | - -**Item Structure**: - -Each item in `$items` has: - -```php -[ - 'title' => 'Item Title', // From metadata or H1 - 'date' => '2. november 2025', // Formatted date - 'url' => '/blog/post-slug/', // Full URL with language prefix - 'cover' => '/path/to/cover.jpg', // Cover image path or null - 'summary' => 'Brief description', // From metadata or null - 'pdf' => '/path/to/file.pdf', // PDF file path or null - 'redirect' => 'https://...', // External URL or null -] -``` - -**Example**: -```php - -
- -
- - -
- -
-

- - - -

- - - - -

- -
- -
-``` - -### list-grid.php - -**Purpose**: Grid layout with cover images -**Used**: Visual blog/portfolio listings -**Customizable**: Yes - -**Same variables as list.php** - -Features: -- Grid layout -- Cover images -- PDF download links -- "Read more" buttons - -**Example**: -```php -
- -
- - - - -

- - - -

- - - - - - -

- - - -
- -
-``` - -### list-card-grid.php - -**Purpose**: Card-style grid with external link support -**Used**: Portfolios, resource lists -**Customizable**: Yes - -**Same variables as list.php** - -Features: -- Card-style layout -- PDF download support -- External redirect support -- Cover images - -**Example**: -```php -
- -
- - - - -

- - -

- - - - - Visit Site - - - - Download PDF - - - - View Details - - -
- -
-``` - -### list-faq.php - -**Purpose**: Expandable FAQ/Q&A format -**Used**: FAQ sections, documentation -**Customizable**: Yes - -**Same variables as list.php** - -Features: -- Collapsible `
` elements -- Semantic HTML -- Keyboard accessible - -**Example**: -```php - -
- -
- - -
- -
- - - -

- - - - - -
- -
-``` - -## Context Object - -All templates have access to `$ctx` (Context object): - -### Properties - -| Property | Type | Description | -|----------|------|-------------| -| `$ctx->contentDir` | string | Path to content directory | -| `$ctx->currentLang` | string | Current language code | -| `$ctx->defaultLang` | string | Default language code | -| `$ctx->availableLangs` | array | Available language codes | -| `$ctx->langPrefix` | string | URL language prefix (e.g., "/en" or "") | -| `$ctx->requestPath` | string | Current request path | -| `$ctx->hasTrailingSlash` | bool | Whether path has trailing slash | -| `$ctx->navigation` | array | Navigation menu items (computed) | -| `$ctx->homeLabel` | string | Site title (computed) | -| `$ctx->translations` | array | UI translations (computed) | - -### Example Usage - -```php - -availableLangs as $lang): ?> - defaultLang - ? '/' . trim($ctx->requestPath, '/') - : '/' . $lang . '/' . trim($ctx->requestPath, '/'); - ?> - currentLang ? 'aria-current="true"' : '' ?>> - - - - - - -``` - -## Navigation Array - -Structure of `$navigation` items: - -```php -[ - [ - 'title' => 'Blog', - 'url' => '/blog/', - 'order' => 1 - ], - [ - 'title' => 'About', - 'url' => '/about/', - 'order' => 2 - ], - // ... -] -``` - -Already sorted by `menu_order` field. - -## Translation Array - -Structure of `$translations`: - -```php -[ - 'home' => 'Home', - 'read_more' => 'Read more', - 'categories' => 'Categories', - 'tags' => 'Tags', - 'footer_text' => 'Made with FolderWeb', - 'footer_handcoded' => 'Generated in', - 'footer_page_time' => 'ms', - // ... custom translations -] -``` - -## Helper Functions Available in Templates - -### resolveTemplate() - -Find custom or default template: - -```php -$templatePath = resolveTemplate('base', 'templates'); -$cssPath = resolveTemplate('base.css', 'styles'); -``` - -### htmlspecialchars() - -Escape output (always use for user content): - -```php - -``` - -### Other PHP Functions - -All standard PHP functions are available: -- `isset()`, `empty()` -- `count()`, `array_filter()` -- `date()`, `time()` -- String functions -- etc. - -## Creating Custom Templates - -### Step 1: Create Template File - -```bash -touch custom/templates/my-custom-list.php -``` - -### Step 2: Use Standard Variables - -Custom list templates receive `$items`, `$metadata`, `$pageContent`, `$translations`. - -### Step 3: Apply in Metadata - -**content/my-section/metadata.ini**: -```ini -page_template = "my-custom-list" -``` - -Note: Omit `.php` extension. - -## Template Best Practices - -### Always Escape Output - -```php - - - - - -``` - -### Check Variables Before Use - -```php - - - -``` - -### Use Null Coalescing - -```php -$author = $metadata['author'] ?? 'Anonymous'; -``` - -### Semantic HTML - -```php - -
-

- -
- - -
- - -
-``` - -### Accessibility - -```php - -<?= htmlspecialchars($item['title']) ?> - - -