Add about page with project philosophy and technical details Add articles about Markdown, templates, and getting started Implement demo content system that shows when no user content exists Update logo to show FolderWeb branding Improve Apache configuration for development environment |
||
|---|---|---|
| .. | ||
| default | ||
| vendor | ||
| config.ini | ||
| README.md | ||
| router.php | ||
| static.php | ||
Framework Documentation
This directory contains the core framework for the file-based CMS. It provides a minimal, extensible foundation that can be customized via the /custom/ directory.
Architecture
The framework is a lightweight PHP-based routing system that:
- Converts URLs to filesystem paths
- Resolves language-specific content and slugs
- Applies templates to render content
- Serves static assets (styles, fonts, images)
Directory Structure
app/
├── router.php # Main routing logic
├── static.php # Static asset server for /app/* resources
├── config.ini # Default framework configuration
├── vendor/ # Third-party dependencies
│ └── Parsedown/ # Markdown parser
└── default/ # Default templates and styles (fallback)
├── templates/
│ ├── base.php # Base HTML structure
│ ├── page.php # Single page/article template
│ └── list.php # Directory listing template
└── styles/
└── base.css # Default base styles
Core Components
router.php
The main request router that handles all content requests. Key responsibilities:
- Language Detection: Extracts language from URL path (
/no/,/en/) - Slug Resolution: Converts language-specific slugs to directory names using metadata
- Path Resolution: Maps URLs to filesystem paths in
/content/ - Content Loading: Reads content files (
.md,.html,.php) - Template Application: Applies appropriate template based on content type
- Rendering: Outputs final HTML with base template
Key Functions:
resolveLanguageSlugToName()- Translates slugs to directory namesfindContentFile()- Locates content files with language variantsrenderPage()- Renders content with templatesparseMetadata()- Parses INI metadata files
static.php
Serves static assets from /app/ directory. Handles requests for:
/app/styles/*- Framework CSS files/app/fonts/*- Framework fonts/app/default-styles/*- Default stylesheet aliases
Includes security checks to prevent path traversal attacks.
config.ini
Default configuration for the framework:
[languages]
default = "no" # Default language
available = "no,en" # Available languages
Can be overridden by /custom/config.ini.
vendor/
Third-party dependencies:
- Parsedown: Markdown-to-HTML parser library
default/
Fallback templates and styles used when custom templates are not provided.
Request Flow
1. User requests URL (e.g., /no/artikler/pasientinfo)
↓
2. Apache routes to /content/index.php
↓
3. index.php includes router.php
↓
4. router.php:
- Extracts language: "no"
- Resolves slug "artikler" → "artikler" directory
- Resolves slug "pasientinfo" → "pasientinfo" directory
- Checks if path exists in /content/
- Determines content type (file or directory)
↓
5. For single article:
- Loads metadata.ini
- Loads article.no.md (or article.md)
- Applies /custom/templates/page.php (or default)
- Wraps with /custom/templates/base.php
↓
6. For directory listing:
- Scans directory for subdirectories
- Loads metadata.ini for each item
- Applies list template specified in metadata
- Wraps with base.php
↓
7. Outputs final HTML to browser
Template System
Templates can be overridden by placing files in /custom/templates/:
Base Template (base.php)
Wraps all content with HTML structure, header, footer, navigation.
Variables available:
$title- Page title$content- Rendered page content$language- Current language code$metadata- Page metadata array
Page Template (page.php)
Renders single articles/pages.
Variables available:
$contentHtml- Parsed HTML content$metadata- Article metadata$language- Current language code$parentMetadata- Parent directory metadata
List Templates
Render directory listings. Multiple variants:
list.php- Simple listlist-grid.php- Grid layoutlist-card-grid.php- Card grid with imageslist-faq.php- Expandable FAQ view
Variables available:
$items- Array of child items with metadata$metadata- Directory metadata$language- Current language code
Customization
The framework is designed to be minimal and extensible. All customization should happen in /custom/:
Override Templates
Create files in /custom/templates/ with the same name as default templates.
Override Configuration
Create /custom/config.ini to override default settings.
Add Custom Styles
Place CSS in /custom/styles/ and reference in custom templates.
Add Custom Fonts
Place font files in /custom/fonts/ and reference in CSS.
Add Translations
Create or edit /custom/languages/[lang].ini files.
Metadata System
Content is configured via metadata.ini files placed in each directory.
Common Metadata Fields
[metadata]
title[no] = "Norwegian Title"
title[en] = "English Title"
slug[no] = "norwegian-slug"
slug[en] = "english-slug"
summary[no] = "Norwegian summary"
summary[en] = "English summary"
date = "2024-10-15"
category = "Category Name"
tags = "tag1,tag2,tag3"
template = "list-card-grid" # For directories
show_in_menu = true
menu_order = 10
Metadata Inheritance
Child items inherit parent metadata when not specified.
Content File Resolution
The router looks for content files in this order:
article.[language].md(e.g.,article.no.md)article.[language].htmlarticle.[language].phparticle.md(fallback)article.html(fallback)article.php(fallback)page.[language].md(for directory index)page.md(fallback)
Language System
URL Structure
- Norwegian:
/no/artikler/pasientinfo - English:
/en/articles/patient-info
Slug Translation
Slugs are resolved using metadata:
slug[no] = "pasientinfo"
slug[en] = "patient-info"
The router automatically translates URLs to filesystem paths regardless of language.
Translation Files
Located in /custom/languages/:
no.ini- Norwegian translationsen.ini- English translations
Format:
key = "Translated text"
another_key = "More text"
Access in templates: $translations['key']
Security Considerations
- Path Traversal Protection:
static.phpvalidates paths to prevent directory traversal - Input Sanitization: URLs are sanitized before filesystem operations
- Template Isolation: Templates run in controlled scope with specific variables
- No Database: File-based system eliminates SQL injection risks
Performance
- No Caching: Content is rendered on each request (suitable for low-traffic sites)
- Performance Tracking: Page generation time is measured and displayed
- Static Assets: Served directly by Apache when possible
Extending the Framework
To add new features:
- Custom Functions: Add helper functions in custom templates
- New Template Types: Create new template files in
/custom/templates/ - Metadata Fields: Add new fields to
metadata.inifiles - Custom Routes: Extend
router.php(requires modifying framework)
Debugging
Enable error reporting in content/index.php:
ini_set('display_errors', 1);
error_reporting(E_ALL);
View page generation time at bottom of each page.
Requirements
- PHP 8.3 or higher
- Apache with mod_rewrite enabled
- Write permissions on content directories (for future admin features)
Limitations
- No built-in caching (regenerates pages on each request)
- No built-in admin interface (content edited via filesystem)
- No user authentication system
- No built-in search functionality
- Performance may degrade with very large content libraries