- Bug: dashboard toonde 0 content (AdminPluginAPI::getContentDir() gaf relatief pad terug zonder normalisatie) - Dynamische pad-resolutie: PluginAPIInterface uitgebreid met getProjectRoot/getContentDir/getPluginsDir/getVersionInfo; CMSAPI en AdminPluginAPI implementeren deze universeel - public/index.php media-serving gebruikt $config['content_dir'] i.p.v. hardcoded /content - Navigation en Logs plugins halen paden via de API i.p.v. hardcoded dirname(__DIR__) - WordPress-stijl docblocks toegevoegd voor alle classes, methods, properties en functies (~450 docblocks, @since 2.6.5) - Security: hardcoded plaintext-wachtwoord 'admin' verwijderd uit AdminAuth.php; bij eerste installatie wordt een cryptografisch veilig wachtwoord gegenereerd (random_bytes, 16 tekens) en eenmalig op het inlogscherm getoond - Security: git-geschiedenis schoongemaakt (admin.json, admin.json.example, admin-console/config/admin.json verwijderd uit alle commits; filter-branch over alle branches + tags, gc --prune --aggressive) - README.md, README.en.md, AGENTS.md bijgewerkt - Test-scripts bijgewerkt naar clean-URL structuur + actuele ARIA-waarden - Versie verhoogd naar 2.6.5 - Tests: pentest 29/29, WCAG 25/25, functioneel 16/16, enhanced 25/25
10 KiB
CodePress CMS
A lightweight, file-based content management system built with PHP (≥8.0).
Version: 2.6.5 | License: AGPL v3 / Commercial
✨ Features
- 📝 Multi-format Content - Markdown, PHP and HTML files
- 🧭 Dynamic Navigation - Automatic menu generation
- 🌍 Multi-language - NL/EN/DE support
- 🔍 Search - Full-text search
- 📱 Responsive - Bootstrap 5 themes
- 🔒 Security - 100/100 pentest score
- 🛡️ Admin Console - CodeMirror editor, media management, themes, plugins
- 👥 User Roles - Admin, Content Manager, BI Manager, Site Admin
- 📊 Analytics - Visitor statistics with GeoIP
- 🤖 BotGuard - Bot/AI protection
- 📈 Logging - Comprehensive logging system
- 🔌 Plugin System - Sidebar plugins with own CSS/SCSS, Twig templates
🚀 Quick Start
# Install dependencies
composer install
# Start server with router for clean URLs (local only)
php -S localhost:8080 cms/router.php
Website: http://localhost:8080
Admin: http://localhost:8080/admin (login: admin / admin)
📦 Installation
Requirements
- PHP ≥ 8.0 with extensions:
json,mbstring - Composer (PHP dependency manager)
- Web server: Apache 2.4+ with
mod_rewriteor Nginx with PHP-FPM - Optional:
opcache(recommended for performance),git(for content versioning),zipextension (for ZIP backup/restore)
Step 1 — Code and dependencies
git clone <repository-url> codepress
cd codepress
composer install
Step 2 — Configuration
cp config.json.example config.json
Edit config.json with your site title, language and plugins. On the first visit to /admin, admin/config/admin.json is created automatically with a random password that is shown on the login screen. Save this password safely and change it immediately after login.
Step 3a — Apache 2.4+
The webroot is the public/ directory. Example vhost (/etc/apache2/sites-available/codepress.conf):
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/codepress/public
<Directory /var/www/codepress/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/codepress_error.log
CustomLog ${APACHE_LOG_DIR}/codepress_access.log combined
</VirtualHost>
Required Apache modules:
sudo a2enmod rewrite headers
sudo systemctl restart apache2
mod_rewrite— for clean URLs (/nl/page) and asset-servingmod_headers— for security headersAllowOverride All— so the.htaccessinpublic/is applied
Step 3b — Nginx
Example server block (/etc/nginx/sites-available/codepress):
server {
listen 80;
server_name example.com;
root /var/www/codepress/public;
index index.php;
# Clean URLs: language-prefixed pages
location ~ ^/(nl|en|de)(/(.+))?$ {
try_files $uri /index.php?lang=$1&page=$2;
}
# Admin routes
location /admin {
try_files $uri /admin.php?$args;
}
# Asset-serving via asset.php (themes/plugins/admin outside webroot)
location ~ ^/(themes|plugins)/([^/]+)/assets/(.+)$ {
try_files $uri /asset.php;
}
location ~ ^/admin/assets/(.+)$ {
try_files $uri /asset.php;
}
# PHP via FPM
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Security: block access to sensitive directories
location ~ ^/(content|cms|admin/src|admin/config|admin/storage|var|vendor)/ {
deny all;
return 403;
}
location ~ /\.(git|htaccess) {
deny all;
}
}
Note: Nginx does not use .htaccess. Security headers must be set in the Nginx config:
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy strict-origin-when-cross-origin;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';";
Step 4 — Directory permissions
Make sure the web server has write access to the runtime directories:
chown -R www-data:www-data var/ admin/storage/ content/
chmod -R 755 .
Step 5 — Test
Open the website in your browser. With an empty content directory you'll see a welcome page. The admin console is available at /admin (login admin/admin).
📚 Documentation
See guide/ for extensive documentation per role:
| Role | Guide |
|---|---|
| 📝 Content Editor | Content Manager |
| ⚙️ Administrator | Admin Manager |
| 🎨 Theme Developer | Theme Developer |
| 💻 Developer | CodePress Developer |
Each guide has sub-topics in separate folders with sidebar navigation.
👥 User Roles
| Role | Permissions |
|---|---|
| Admin | Full access (everything) |
| Content Manager | Content management, guide |
| BI Manager | Statistics, logs, guide |
| Site Admin | Theme, plugins, statistics, logs, update, guide |
📁 Project Structure
codepress/
├── cms/ # Core CMS engine
│ ├── core/class/ # CMS classes (CodePressCMS, ThemeManager, etc.)
│ ├── core/plugin/ # Plugin system (PluginManager, CMSAPI)
│ └── router.php # PHP dev server router (clean URLs)
├── language/ # Translation files (nl/, en/, de/ — each with site.php + admin.php)
├── admin/ # Admin console
│ ├── config/ # Admin configuration (admin.json)
│ ├── src/AdminAuth.php # Authentication, roles, permissions
│ ├── static/ # Static files (404.html)
│ ├── storage/ # Logs, cache, geoip
│ └── theme/default/ # Admin theme
│ ├── assets/ # CSS, JS, fonts, codemirror
│ ├── views/ # Twig templates (layouts, pages)
│ └── theme.json # Admin theme configuration
├── themes/ # Website themes
│ ├── default/ # Default theme
│ │ ├── theme.json # Layout mapping, colors
│ │ ├── base.twig # Main layout
│ │ ├── *.twig # Layout templates
│ │ ├── partials/ # Header, navigation, footer
│ │ └── assets/ # SCSS, CSS, JS, img
├── plugins/ # Plugins
│ ├── HTMLBlock/ # Example sidebar plugin
│ └── Navigation/ # Essential navigation plugin (protected)
│ ├── Navigation.php # Plugin code
│ ├── plugin.json # Plugin metadata
│ ├── assets/scss/ # Plugin SCSS source
│ └── assets/css/ # Plugin CSS
├── content/ # Website content (.md, .php, .html)
├── public/ # Web root
│ ├── index.php # Website entry point
│ └── admin.php # Admin entry point + routing
├── guide/ # Documentation (nl/en)
│ ├── nl/ # Dutch guides
│ └── en/ # English guides
├── cli/test/ # Test suites
├── var/ # Cache (twig)
├── config.json # Site configuration
├── composer.json # PHP dependencies
└── version.php # Version information
⚙️ Configuration
config.json
{
"site_title": "CodePress",
"active_theme": "default",
"default_page": "auto",
"language": {
"default": "nl",
"available": ["nl", "en"]
},
"enabled_plugins": ["HTMLBlock", "Navigation"],
"features": {
"search_enabled": true,
"breadcrumbs_enabled": true
},
"security": {
"block_ai_bots": true,
"rate_limit_enabled": true
},
"analytics": { "enabled": true },
"logging": { "enabled": true }
}
🔧 Dependencies
- PHP ≥8.0 with extensions: json, mbstring
- Composer packages:
- twig/twig (templating)
- scssphp/scssphp (SCSS compilation)
- league/commonmark (Markdown with HeadingPermalinks)
- maxmind-db/reader (GeoIP)
🔐 Security
- ✅ XSS prevention (htmlspecialchars)
- ✅ CSRF tokens (admin forms)
- ✅ Path traversal prevention (realpath checks)
- ✅ Secure cookies (HttpOnly, SameSite)
- ✅ Security headers (X-Frame-Options, CSP)
- ✅ Bot/AI protection (BotGuard)
- ✅ Rate limiting per IP
- ✅ Role-based access control (RBAC)
🔌 Plugins
Plugin structure
plugins/MyPlugin/
├── MyPlugin.php # Plugin code (name = plugin name)
├── plugin.json # Plugin metadata
├── assets/scss/ # Plugin SCSS source
└── assets/css/ # Plugin CSS (after compilation)
Essential plugins
The Navigation plugin is an essential plugin and cannot be disabled, edited, or deleted. This plugin automatically generates sidebar navigation for guides and content.
Plugin CSS
Plugin CSS is automatically loaded after theme CSS, so themes can override plugin styling.
📝 Content Examples
Markdown with frontmatter
---
layout: full_content
plugins: HTMLBlock, Navigation
---
# Page title
Content in Markdown format...
PHP content
<?php
/** @var ContentAPI $api */
$pages = $api->getAllPages();
echo "<h1>My Page</h1>";
echo "<p>Number of pages: " . count($pages) . "</p>";
🧪 Testing
# Penetration tests
cli/test/pentest/security-test.sh
# Accessibility tests (WCAG 2.1 AA)
cli/test/accessibility.sh
# Functional tests
cli/test/functional/*.sh
📞 Support
- Documentation: guide/
- Issues: Git repository
- Contact: commercial@noorlander.info
📄 License
Dual-licensed:
- AGPL v3 - For open-source projects
- Commercial - For proprietary use
See LICENSE for details.
CodePress CMS - Built by E.Noorlander / CodePress Development Team