# Agent Instructions for CodePress CMS

## AI Model
- **Huidig model**: GLM-5.2 max (Ollama cloud)
- Sessie gestart: 16 feb 2026

## Build & Run
- **Run Server**: `php -S localhost:8080 cms/router.php` (router nodig voor clean URLs)
- **Lint PHP**: `find . -name "*.php" -not -path "./vendor/*" -not -path "./var/*" -exec php -l {} \;`
- **Dependencies**: Composer vereist voor CommonMark, Twig en scssphp. Geen NPM.
- **Admin Console**: Toegankelijk op `/admin` (standaard login: `admin` / `admin`)

## Project Structuur
```
codepress/
├── cms/                                # Core CMS engine
│   ├── core/
│   │   ├── class/
│   │   │   ├── CodePressCMS.php         # Hoofd CMS class (routing, rendering, breadcrumb, guide)
│   │   │   ├── ThemeManager.php         # Thema-resolver + Twig render + SCSS compile
│   │   │   ├── ContentAPI.php           # Read-only API voor PHP content bestanden
│   │   │   ├── ContentSecurityPolicy.php # CSP header management
│   │   │   ├── Analytics.php            # Bezoekersstatistieken
│   │   │   ├── BotGuard.php             # Bot/AI detectie
│   │   │   ├── Cache.php               # Cache systeem
│   │   │   ├── GeoIP.php                # GeoIP lookup (land, vlag)
│   │   │   ├── Logger.php               # Basis logging
│   │   │   ├── LogManager.php           # Dynamisch logging systeem (SQLite/syslog)
│   │   │   ├── RateLimiter.php          # Rate limiting per IP
│   │   │   ├── RequestLogger.php        # Request logging + visitor info
│   │   │   ├── SearchEngine.php         # Volledige tekst zoekfunctie
│   │   │   ├── SimpleTemplate.php       # Legacy Mustache-style engine (niet meer gebruikt)
│   │   │   └── AccessibilityManager.php # Accessibility features
│   │   ├── plugin/
│   │   │   ├── PluginManager.php         # Plugin loader (laadt, hooks, filters, sidebar)
│   │   │   └── CMSAPI.php                # API voor plugins (getPage, getConfig, etc.)
│   │   ├── config.php                   # Config loader (leest config.json)
│   │   └── index.php                    # Bootstrap (autoloader, requires)
│   ├── lang/                            # Taalbestanden (nl.php, en.php)
│   └── router.php                       # PHP dev server router (serveert themes/, admin/assets/, plugins/assets/)
├── themes/                              # Dynamische thema's (volledig zelfstandig)
│   ├── default/                         # Standaard thema
│   │   ├── theme.json                   # { title, config.default_template, template: layout→.twig mapping }
│   │   ├── base.twig                    # Hoofd layout (head, header, nav, breadcrumb, footer)
│   │   ├── full_content.twig            # Layout: volledige breedte
│   │   ├── left_sidebar.twig            # Layout: sidebar links
│   │   ├── right_sidebar.twig           # Layout: sidebar rechts
│   │   ├── custom1.twig                 # Layout: custom
│   │   ├── guide.twig                   # Layout: handleiding met sidebar (Navigation plugin)
│   │   ├── partials/                    # header.twig, navigation.twig, footer.twig
│   │   └── assets/
│   │       ├── scss/theme.scss           # SCSS bron (runtime gecompileerd)
│   │       ├── css/theme.css             # Gecompileerde CSS
│   │       ├── css/style.css             # Extra CSS (search fix, etc.)
│   │       ├── css/bootstrap.min.css     # Bootstrap 5
│   │       ├── css/bootstrap-icons.css   # Bootstrap Icons
│   │       ├── css/mobile.css            # Mobile styles
│   │       ├── js/app.js                 # Thema JavaScript
│   │       ├── js/bootstrap.bundle.min.js
│   │       ├── fonts/                     # bootstrap-icons.woff, woff2
│   │       └── img/                      # favicon, icon, world-map
│   └── demo/                            # Demo thema (zelfde structuur, andere look)
├── admin/                               # Admin paneel
│   ├── config/
│   │   ├── app.php                      # Admin app configuratie (paths, config_json, etc.)
│   │   └── admin.json                   # Gebruikers & security (file-based, .gitignore'd)
│   ├── src/
│   │   └── AdminAuth.php                # Authenticatie (sessies, bcrypt, CSRF, lockout, RBAC)
│   ├── theme/default/                   # Admin thema
│   │   ├── theme.json                   # Admin thema configuratie
│   │   ├── assets/
│   │   │   ├── css/
│   │   │   │   ├── style.css             # Admin styles (code blocks, guide nav)
│   │   │   │   ├── editor.css            # CodeMirror editor styles
│   │   │   │   ├── bootstrap.min.css
│   │   │   │   └── bootstrap-icons.css
│   │   │   ├── js/
│   │   │   │   ├── app.js
│   │   │   │   ├── editor-toolbar.js     # CodeMirror toolbar + shortcuts
│   │   │   │   ├── keyboard-navigation.js
│   │   │   │   └── bootstrap.bundle.min.js
│   │   │   ├── codemirror/               # CodeMirror editor (modes, addons)
│   │   │   ├── fonts/                    # bootstrap-icons.woff, woff2
│   │   │   └── img/                      # favicon, world-map
│   │   └── views/
│   │       ├── login.twig                # Login pagina
│   │       ├── layouts/
│   │       │   └── admin.twig            # Admin layout met sidebar (role-based zichtbaarheid)
│   │       └── pages/
│   │           ├── dashboard.twig        # Dashboard (role-based inhoud)
│   │           ├── content.twig          # Content beheer
│   │           ├── content-edit.twig     # Content bewerken (layout select, plugins, CodeMirror)
│   │           ├── content-new.twig      # Nieuwe content
│   │           ├── content-move-form.twig # Content verplaatsen
│   │           ├── content-dir-form.twig  # Map hernoemen
│   │           ├── config.twig           # Site configuratie
│   │           ├── security.twig         # Beveiliging instellingen
│   │           ├── theme.twig            # Thema beheer
│   │           ├── theme-new.twig        # Nieuw thema
│   │           ├── plugins.twig          # Plugin beheer (beschermd: essentiële plugins)
│   │           ├── plugins-edit.twig     # Plugin bewerken (CodeMirror)
│   │           ├── plugins-new.twig      # Nieuwe plugin
│   │           ├── plugin-config.twig    # Plugin configuratie
│   │           ├── users.twig            # Gebruikersbeheer (rollen, wachtwoord)
│   │           ├── statistics.twig       # Statistieken
│   │           ├── logs.twig             # Log viewer
│   │           ├── media.twig            # Media beheer
│   │           ├── guide.twig            # Handleiding (met Navigation sidebar)
│   │           ├── update.twig           # Update pagina
│   │           └── error.twig            # 403/404 fout pagina
│   └── storage/                         # Logs, cache, geoip
├── plugins/                             # CMS plugins
│   ├── Navigation/                       # Essentiële navigatie plugin (beschermd)
│   │   ├── Navigation.php               # Plugin code (guide + content navigatie)
│   │   ├── plugin.json                   # Plugin metadata
│   │   ├── assets/
│   │   │   ├── scss/navigation.scss      # SCSS bron
│   │   │   └── css/navigation.css        # Gecompileerde CSS
│   │   └── views/                        # Plugin Twig templates (toekomstig)
│   └── HTMLBlock/                        # Voorbeeld sidebar plugin
│       └── HTMLBlock.php
├── content/                             # Website content (.md, .php, .html)
├── public/                              # Web root
│   ├── index.php                        # Website entry point
│   ├── admin.php                        # Admin entry point + routing
│   ├── favicon.ico
│   └── robots.txt
├── guide/                               # Handleidingen (nl/en, gesplitst in mappen)
│   ├── nl/                              # Nederlandse handleidingen
│   │   ├── index.md                     # Index (verwijst naar onderwerpen)
│   │   ├── admin-beheerder.md           # Admin handleiding (inleiding)
│   │   ├── admin-beheerder/             # Sub-onderdelen
│   │   ├── content-beheerder.md
│   │   ├── content-beheerder/
│   │   ├── codepress-developer.md
│   │   ├── codepress-developer/
│   │   ├── theme-developer.md
│   │   └── theme-developer/
│   ├── en/                              # Engelse handleidingen (zelfde structuur als nl/)
│   └── README.md
├── cli/                                 # CLI scripts & tests
│   └── test/
│       ├── accessibility.sh             # WCAG 2.1 AA test suite
│       ├── enhanced-suite.sh            # Enhanced test suite
│       ├── functional/                   # Functionele testen
│       └── pentest/                      # Penetratietesten
├── var/                                 # Cache (twig) — .gitignore'd
├── config.json                          # Site configuratie — .gitignore'd
├── composer.json                        # PHP dependencies
├── version.php                          # Versie informatie (huidige: 2.5.1)
├── .gitignore                           # Negeert: var/, config.json, admin/config/admin.json, content/
└── AGENTS.md                            # Dit bestand
```

## Code Style & Conventions
- **PHP Standards**: Follow PSR-12. Use 4 spaces for indentation.
- **Naming**: Classes `PascalCase` (e.g., `CodePressCMS`), methods `camelCase` (e.g., `renderMenu`), variables `camelCase`, config keys `snake_case`.
- **Architecture**: 
  - Core CMS logic in `cms/core/class/CodePressCMS.php`
  - Bootstrap/requires in `cms/core/index.php`
  - Configuration loaded from `config.json` via `cms/core/config.php`
  - Public website entry point: `public/index.php`
  - Admin entry point + routing: `public/admin.php`
  - Admin authentication + RBAC: `admin/src/AdminAuth.php`
  - Admin theme: `admin/theme/default/` (views + assets)
  - Plugin assets: `plugins/<Name>/assets/` (served via router `/plugins/<Name>/assets/`)
- **Content**: Stored in `content/`. Supports `.md` (Markdown), `.php` (Dynamic), `.html` (Static).
- **Templating**: Twig templates in `themes/<naam>/`. `ThemeManager` rendert via Twig en compileert `assets/scss/theme.scss` runtime naar `assets/css/theme.css`. Layout gekozen via frontmatter `layout:` key; onbekende layouts vallen terug op `config.default_template` in `theme.json`.
- **Plugin CSS**: Plugins hebben eigen `assets/scss/` en `assets/css/`. Plugin CSS wordt automatisch geladen na theme CSS (in `base.twig`), zodat thema's plugin styling kunnen overschrijven. Plugin assets worden geserveerd via `cms/router.php` op URL `/plugins/<Name>/assets/...`.
- **Navigation**: Auto-generated from directory structure. Folders require an index file to be clickable in breadcrumbs. Breadcrumb is dynamisch: Home > [submappen] > [pagina]. Homepage toont altijd het pad.
- **Security**: 
  - Always use `htmlspecialchars()` for outputting user/content data
  - Use `realpath()` + prefix-check for path traversal prevention
  - Admin forms require CSRF tokens via `AdminAuth::verifyCsrf()`
  - Passwords stored as bcrypt hashes in `admin/config/admin.json`
  - Role-based access control (RBAC) via `AdminAuth::hasPermission()`
- **Git**: `main` is the clean CMS core. `development` is de actieve development branch. `e.noorlander` bevat persoonlijke content. Niet mixen.

## Admin Console
- **File-based**: Geen database. Gebruikers opgeslagen in `admin/config/admin.json`
- **Routing**: Via clean URLs `/admin/<route>` (omgezet naar `?route=` door `cms/router.php`)
- **Routes**: `login`, `logout`, `dashboard`, `content`, `content-edit`, `content-new`, `content-delete`, `content-dir-create`, `content-dir-rename`, `content-dir-delete`, `content-move`, `config`, `security`, `theme`, `theme-new`, `plugins`, `plugins-new`, `plugins-edit`, `plugins-config`, `plugins-toggle`, `plugins-delete`, `users`, `statistics`, `logs`, `media`, `guide`, `update`
- **Auth**: Session-based. `AdminAuth` class handelt login, logout, CSRF, brute-force lockout af
- **Templates**: Twig templates in `admin/theme/default/views/pages/`. Layout in `admin/theme/default/views/layouts/admin.twig`
- **Essentiële plugins**: Gedefinieerd in `getProtectedPlugins()` in `public/admin.php`. Deze plugins kunnen niet worden gedeactiveerd, bewerkt of verwijderd. Huidige essentiële plugins: `Navigation`.

## Gebruikersrollen (RBAC)
Gedefinieerd in `AdminAuth::ROLE_PERMISSIONS` als een mapping van rol → toegestane routes.

| Rol | Label | Permissies |
|-----|-------|-----------|
| `admin` | Admin | Alles (`*`) |
| `content-manager` | Content Beheerder | Content beheer, handleiding |
| `bi-manager` | BI Beheerder | Statistieken, logs, handleiding |
| `site-admin` | Site Admin | Thema, plugins, statistieken, logs, update, handleiding |

- Sidebar items worden conditioneel getoond via `has_permission()` Twig function
- Dashboard inhoud is role-based (statistieken, content stats, systeem info, quick actions)
- Route access control in `public/admin.php`: onbevoegde routes geven 403 error

## Guide Systeem
- Handleidingen in `guide/<lang>/` met sub-onderdelen in aparte mappen
- NL en EN hebben identieke structuur (bestandsnamen zijn gelijk voor fallback)
- `getGuidePage()` in `CodePressCMS.php` laadt guide content en injecteert `plugins: Navigation` in metadata
- Navigation plugin genereert zijbalk navigatie vanuit de mapstructuur (guide + content)
- Guide titles worden uit H1 van markdown bestanden gehaald (via `getTitleFromFile()`)
- Admin guide laadt Navigation plugin direct in `handleGuide()` in `public/admin.php`

## Important: Title vs File/Directory Name Logic
- **CRITICAL**: When user asks for "title" corrections, they usually mean **FILE/DIRECTORY NAME WITHOUT LANGUAGE PREFIX AND EXTENSIONS**, not the HTML title from content!
- **Examples**:
  - `nl.test.md` → display as "Test" (not content title)
  - `nl.test/` directory → display as "Test" (not H1 content)
  - `en.php-testen` → display as "Php Testen" (not "ICT")
- **Method**: Use `formatDisplayName()` to process file/directory names correctly
- **Priority**: Directory names take precedence over file names when both exist
- **Language prefixes**: Dynamisch verwijderd op basis van beschikbare talen via `getAvailableLanguages()`

## Bekende aandachtspunten
- LSP errors over "Undefined function" in PHP files zijn vals-positief (standaard PHP functies worden niet herkend door de LSP). Negeer deze.
- Zie `TODO.md` voor alle openstaande verbeteringen en nieuwe features.
- `vendor/` map bevat Composer dependencies (CommonMark, Twig, scssphp). Niet handmatig wijzigen.
- `admin/config/admin.json` bevat wachtwoord-hashes. Niet committen met echte productie-wachtwoorden.
- `config.json` staat in `.gitignore`. Niet committen.
- `var/` (Twig cache) staat in `.gitignore`. Kan veilig worden gewist: `rm -rf var/cache/twig/*`
- `content/` staat in `.gitignore`. Content wordt lokaal beheerd.
- Pad-referenties vanuit `public/admin.php`: gebruik `__DIR__ . "/../themes/..."` (één niveau omhoog), NIET `../../` (twee niveaus).
