folderweb/app
Ruben 4c697122ab Add demo content and documentation for FolderWeb
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
2025-11-01 16:47:15 +01:00
..
default Add demo content and documentation for FolderWeb 2025-11-01 16:47:15 +01:00
vendor Initial commit 2025-10-02 16:54:47 +02:00
config.ini Initial commit 2025-10-02 16:54:47 +02:00
README.md Add default templates for list views 2025-11-01 16:11:33 +01:00
router.php Add demo content and documentation for FolderWeb 2025-11-01 16:47:15 +01:00
static.php Add test comment to static and router files 2025-10-03 13:17:00 +02:00

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:

[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

[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:

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:

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:

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