Add default language files for English and Norwegian Add list-card-grid template for card-based content display Add list-faq template for FAQ-style content display Add list-grid template for grid-based content display |
||
|---|---|---|
| .. | ||
| 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