# 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: 1. **Language Detection**: Extracts language from URL path (`/no/`, `/en/`) 2. **Slug Resolution**: Converts language-specific slugs to directory names using metadata 3. **Path Resolution**: Maps URLs to filesystem paths in `/content/` 4. **Content Loading**: Reads content files (`.md`, `.html`, `.php`) 5. **Template Application**: Applies appropriate template based on content type 6. **Rendering**: Outputs final HTML with base template **Key Functions:** - `resolveLanguageSlugToName()` - Translates slugs to directory names - `findContentFile()` - Locates content files with language variants - `renderPage()` - Renders content with templates - `parseMetadata()` - 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: ```ini [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 list - `list-grid.php` - Grid layout - `list-card-grid.php` - Card grid with images - `list-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 ```ini [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: 1. `article.[language].md` (e.g., `article.no.md`) 2. `article.[language].html` 3. `article.[language].php` 4. `article.md` (fallback) 5. `article.html` (fallback) 6. `article.php` (fallback) 7. `page.[language].md` (for directory index) 8. `page.md` (fallback) ## Language System ### URL Structure - Norwegian: `/no/artikler/pasientinfo` - English: `/en/articles/patient-info` ### Slug Translation Slugs are resolved using metadata: ```ini 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 translations - `en.ini` - English translations Format: ```ini key = "Translated text" another_key = "More text" ``` Access in templates: `$translations['key']` ## Security Considerations - **Path Traversal Protection**: `static.php` validates 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: 1. **Custom Functions**: Add helper functions in custom templates 2. **New Template Types**: Create new template files in `/custom/templates/` 3. **Metadata Fields**: Add new fields to `metadata.ini` files 4. **Custom Routes**: Extend `router.php` (requires modifying framework) ## Debugging Enable error reporting in `content/index.php`: ```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