Files
CodePress/guide/en.codepress.md
T

20 KiB

CodePress CMS Guide

Table of Contents

Overview

CodePress CMS is a lightweight, file-based content management system built with PHP (>=8.0). Works without a database.

Installation

  1. Upload files to web server
  2. Set permissions for web server
  3. Run composer install for CommonMark dependency
  4. Configure config.json if needed
  5. Access website via browser
  6. PHP development server: php -S localhost:8080 -t public (uses cms/router.php)

Project Structure

codepress/
├── cms/                            # Core CMS engine
│   ├── core/
│   │   ├── class/
│   │   │   ├── CodePressCMS.php    # Main CMS class (content, navigation, search)
│   │   │   ├── Logger.php          # Structured logging system
│   │   │   ├── SimpleTemplate.php  # Mustache-style template engine
│   │   │   ├── Analytics.php       # Visitor statistics
│   │   │   ├── BotGuard.php        # Bot/AI/scraper detection
│   │   │   ├── GeoIP.php           # Country lookup by IP
│   │   │   ├── Cache.php           # File-based caching
│   │   │   └── RateLimiter.php     # Per-IP rate limiting
│   │   ├── plugin/
│   │   │   ├── PluginManager.php   # Plugin loader and manager
│   │   │   └── CMSAPI.php          # API for plugin developers
│   │   ├── config.php              # Configuration loader (merge with config.json)
│   │   └── index.php               # Bootstrap (autoloader, requires)
│   ├── lang/                       # Language files
│   │   ├── nl.php                  # Dutch translations
│   │   └── en.php                  # English translations
│   ├── templates/                  # Mustache templates
│   │   ├── layout.mustache         # Main layout (CSS, structure)
│   │   ├── assets/                 # Header, navigation, footer partials
│   │   ├── markdown_content.mustache
│   │   ├── php_content.mustache
│   │   └── html_content.mustache
│   └── router.php                  # PHP dev server router
├── admin/                          # Admin panel
│   ├── config/
│   │   ├── app.php                 # Admin app configuration (paths, timezone)
│   │   └── admin.json              # Users & security (bcrypt hashes)
│   ├── src/
│   │   └── AdminAuth.php           # Authentication (sessions, bcrypt, CSRF, lockout)
│   ├── templates/
│   │   ├── login.php               # Login page
│   │   ├── layout.php              # Admin layout with sidebar navigation
│   │   └── pages/
│   │       ├── dashboard.php       # Dashboard with statistics
│   │       ├── content.php         # Content overview with file upload
│   │       ├── content-edit.php    # CodeMirror editor with toolbar and rename
│   │       ├── content-new.php     # Create new content
│   │       ├── content-dir-form.php    # Create/edit directory
│   │       ├── content-move-form.php   # Move content
│   │       ├── config.php          # Configuration editor
│   │       ├── security.php        # Security settings
│   │       ├── statistics.php      # Statistics dashboard
│   │       ├── plugins.php         # Plugin overview
│   │       ├── plugins-edit.php    # Plugin PHP source code editor
│   │       ├── plugins-new.php     # Create new plugin
│   │       ├── plugin-config.php   # Plugin configuration editor
│   │       ├── theme.php           # Theme management
│   │       ├── users.php           # User management
│   │       ├── logs.php            # Log viewer
│   │       ├── update.php          # System update
│   │       └── guide.php           # Guide
│   └── storage/logs/               # Admin logs
├── cli/                            # CLI scripts & tests
├── content/                        # Content files
│   ├── -assets/                    # Uploaded media files
│   ├── index.md                    # Default homepage
│   └── ...                         # Other content
├── plugins/                        # CMS plugins
│   ├── HTMLBlock/                  # Custom HTML blocks in sidebar
│   └── MQTTTracker/                # Real-time analytics and tracking
├── public/                         # Web root
│   ├── index.php                   # Website entry point (media serving + CMS)
│   ├── admin.php                   # Admin entry point + routing
│   ├── .htaccess                   # Apache rewrite/security rules
│   ├── assets/                     # CSS, JS, favicons
│   │   ├── codemirror/             # CodeMirror editor (minified JS/CSS)
│   │   └── css/js/                 # Bootstrap, icons, app CSS/JS
│   ├── themes/                     # Uploaded theme backgrounds
│   └── manifest.json / sw.js       # PWA support
├── themes/                         # Theme definitions
│   ├── default/                    # Default theme
│   │   └── theme.json              # Colors, heights, background
│   └── ...                         # Other themes
├── config.json                     # Site configuration
├── version.php                     # Version information
└── vendor/                         # Composer dependencies

Content

Content Structure

File Structure

content/
├── folder1/
│   ├── subfolder1/
│   │   ├── nl.page1.md
│   │   └── en.page1.md
│   └── page3.html
├── folder2/
│   └── page4.md
├── index.md
└── -assets/
    ├── image.jpg
    └── document.pdf

File Naming

  • Use lowercase filenames
  • No spaces - use - or _
  • Logical extensions - .md, .php, .html
  • Unique names - no duplicates
  • Language prefixes - nl.file.md and en.file.md

Media Files

Media files (images, PDFs, video, audio) can be placed in any content/ subdirectory and are served via:

  • /-media/path/file.jpg - Media from any content subdirectory
  • /-assets/file.jpg - Backward compatibility (old URLs)
  • Uploads via the admin panel go to content/-assets/

Content API (for PHP content files)

PHP content files (.php in the content/ directory) have access to an $api variable with the following methods:

Getting pages

// Get all pages with titles
$pages = $api->getAllPages();
// Result: ['index' => 'Home', 'about' => 'About Us', ...]

// Get a specific page's content
$page = $api->getPage('about');
// $page['title'], $page['content'], $page['path'], $page['layout'], $page['metadata']

// Check if a page exists
if ($api->pageExists('contact')) {
    // ...
}

Navigation

// Get menu structure
$menu = $api->getMenu();
// Nested array with 'title', 'path', 'url', 'children'

Configuration

// Get config value (dot notation)
$title = $api->getConfig('site_title');
$lang = $api->getConfig('language.default');
$seoDesc = $api->getConfig('seo.description', 'Default description');

Current page

// Current page title
$pageTitle = $api->getCurrentPageTitle();

// Current page path
$pagePath = $api->getCurrentPagePath();

// Check if this is the homepage
if ($api->isHomepage()) {
    echo 'Welcome!';
}

URLs and language

// Build URL for a page
$url = $api->buildUrl('about', 'en');

// Current language
$lang = $api->getCurrentLanguage();

// Available languages
$languages = $api->getAvailableLanguages();

// Site title
$title = $api->getSiteTitle();
// Get translation
$label = $api->t('home');

// Search results (if searching)
if ($api->isSearching()) {
    $results = $api->getSearchResults();
}

Example PHP content file

---
title: Page Overview
layout: content
---
<h1>All Pages</h1>
<ul>
<?php foreach ($api->getAllPages() as $path => $title): ?>
    <li><a href="<?= $api->buildUrl($path) ?>"><?= htmlspecialchars($title) ?></a></li>
<?php endforeach; ?>
</ul>

Settings

Configuration

The site configuration is managed via the admin panel at /admin/config. The form includes:

  • General settings - Site title and homepage (dropdown with available pages)
  • Language - Default language and available languages
  • SEO - Meta description and keywords
  • Author - Name and website
  • Features - Auto-link pages, search, breadcrumbs, show version
  • IP Exclusions - Exclude IP addresses from statistics and security checks

The configuration is stored in config.json. You can also edit this file manually for advanced options.

IP Exclusions

Under Configuration in the admin panel, the "IP Exclusions" field lets you specify IP addresses that will be:

  • Excluded from visitor statistics
  • Skipped during all security checks (bot detection, rate limiting, IP blocklist)

This is useful for your own IP address or internal monitoring tools.

Example config.json

{
    "site_title": "CodePress",
    "content_dir": "content",
    "templates_dir": "cms\/templates",
    "default_page": "index",
    "active_theme": "default",
    "language": {
        "default": "en",
        "available": ["nl", "en"]
    },
    "seo": {
        "description": "CodePress CMS - Lightweight file-based content management system",
        "keywords": "cms, php, content management, file-based"
    },
    "author": {
        "name": "E. Noorlander",
        "website": "https:\/\/noorlander.info"
    },
    "features": {
        "auto_link_pages": true,
        "search_enabled": true,
        "breadcrumbs_enabled": true
    },
    "analytics": {
        "enabled": true,
        "excluded_ips": ["127.0.0.1", "::1"]
    },
    "security": {
        "block_ai_bots": true,
        "block_scrapers": true,
        "block_empty_user_agent": true,
        "rate_limit_enabled": true
    }
}

Themes

Themes are managed via the admin panel at /admin/theme. You can create, activate, adjust colors, upload background images, and delete themes.

Theme Configuration (themes/<name>/theme.json)

{
    "name": "Default",
    "header_color": "#0a369d",
    "header_font_color": "#ffffff",
    "header_height": "56",
    "navigation_color": "#2754b4",
    "navigation_font_color": "#ffffff",
    "nav_height": "42",
    "sidebar_background": "#f8f9fa",
    "sidebar_border": "#dee2e6",
    "background_image": "",
    "background_image_opacity": "100"
}

How to create a new theme

  1. Go to /admin/theme
  2. Enter a name and click "Create"
  3. Adjust colors, heights and background
  4. Activate the theme

Security

Security settings are managed via /admin/security. Includes:

Bot, AI & Scraper Blocking

Incoming requests are checked against known bot and AI crawler patterns via the User-Agent header. Detected bots receive a 403 Forbidden response.

Category Examples
AI Crawlers GPTBot, ChatGPT-User, Claude-Web, ClaudeBot, Google-Extended, CCBot, PerplexityBot
Search Engines Googlebot, Bingbot, BingPreview, DuckDuckBot, YandexBot, Baiduspider
Scrapers HTTrack, Scrapy, PhantomJS

Rate Limiting

Prevents IPs from overloading the site. Returns HTTP 429 on exceedance.

IP Lists

  • IP Whitelist - IPs on the whitelist are never blocked
  • IP Blocklist - IPs on the blocklist always receive a 403 Forbidden

Dynamic robots.txt

The system automatically generates a robots.txt based on your security settings, available at /robots.txt.


Data

Statistics & Analytics

The statistics dashboard is available at /admin/statistics and provides:

  • KPI cards - Page views, unique visitors, human/bot ratio, blocked requests
  • World map - Visual representation of visitors per country with color intensity
  • Countries list - Top 25 countries with percentage
  • Most viewed pages - Top 25 pages
  • Daily chart - Bar chart of visitors per day
  • Referring sites - Top 15 referrers

Periods and export

Filter by 7, 30, 90 days or all time. Export data as CSV or JSON.

GeoIP

Country detection via three sources:

  • Local (DB-IP Lite) - Offline, privacy-friendly, auto-updated
  • MaxMind database (.mmdb) - Custom MMDB file
  • External API - Custom API URL and key

Logging

The admin console maintains two logs, viewable at /admin/logs:

  • Activity log (admin/storage/logs/admin.log) — admin actions like creating, editing, deleting pages, enabling/disabling plugins, changing configuration.
  • Request log (admin/storage/logs/requests.log) — every page view on the website, including IP, page, domain, language, user agent, and referrer.

The dashboard shows the last 20 entries of each log. Click "View all →" for the full list, where you can also download or clear.


System

Plugin System

Plugin Structure

plugins/
├── HTMLBlock/
│   ├── HTMLBlock.php         # Plugin class (required)
│   ├── config.json            # Configuration (optional)
│   └── README.md              # Documentation (optional)
├── MQTTTracker/
│   ├── MQTTTracker.php
│   ├── config.json
│   └── README.md

Plugin Development

  • API access via CMSAPI class - gives access to CMS configuration, templates, menu
  • Sidebar content with getSidebarContent() - returns HTML for sidebar
  • Metadata access from YAML frontmatter via CMSAPI
  • Configuration via config.json - editable through admin panel
  • viewable field in config.json determines if plugin is visible in sidebar
  • Per-page visibility - via the editor plugin selector per page

Plugin Boilerplate

<?php

class MyPlugin
{
    private ?CMSAPI $api = null;
    private array $config;

    public function __construct()
    {
        $this->config = [
            'viewable' => true,
        ];
    }

    public function setAPI(CMSAPI $api): void
    {
        $this->api = $api;
    }

    public function getSidebarContent(): string
    {
        return '';
    }

    public function getConfig(): array
    {
        return $this->config;
    }

    public function setConfig(array $config): void
    {
        $this->config = array_merge($this->config, $config);
    }
}

Known Issue: MQTTTracker Credentials

The MQTTTracker plugin stores broker_host, broker_port, client_id, username and password in plain text in plugins/MQTTTracker/config.json. This is a known open security issue - in a production environment it is recommended to externalize these credentials to environment variables or a separate credential manager.

User Management

Users are managed via /admin/users. Features:

  • Add user with username, password and role
  • Delete user
  • Change password for other users (admin)
  • Change own password (requires current password)

Passwords are stored as bcrypt hashes in admin/config/admin.json.

Update

Via /admin/update the system can be updated in one click via Git pull. The page shows the current version and git branch, and executes git pull origin <branch> on confirmation.


Guide (in Admin)

This guide is also built into the admin panel via /admin/guide, with support for Dutch and English.


Other

Templates

Template Variables

Site Info - site_title, author_name, author_website, author_git

Page Info - page_title, content, file_info, is_homepage

Navigation - menu, breadcrumb, homepage

Theme (from theme.json) - header_color, header_font_color, header_height, navigation_color, navigation_font_color, nav_height, sidebar_background, sidebar_border, background_image_css, background_image_opacity

Language - current_lang, current_lang_upper, t_* (translated strings)

Layout Options

Use YAML frontmatter to select layout:

---
title: My Page
layout: sidebar-content
plugins: HTMLBlock
---

Available Layouts

  • sidebar-content - Sidebar left, content right (default)
  • content - Content only (full width)
  • sidebar - Sidebar only
  • content-sidebar - Content left, sidebar right
  • content-sidebar-reverse - Content right, sidebar left

Meta Data

---
title: Page Title
layout: content-sidebar
description: Page description
author: Author Name
date: 2025-11-26
plugins: HTMLBlock, MQTTTracker
---

URL Structure

Frontend Page URLs

  • Home: / or /en/
  • Page: /en/folder/page
  • Search: ?search=query (via search form)

Media URLs

  • Media: /-media/path/to/file.jpg (from any content subdirectory)
  • Assets: /-assets/file.jpg (from content/-assets/, backward compatible)

Admin URLs

  • Admin: /admin
  • Dashboard: /admin/dashboard
  • Content: /admin/content
  • Configuration: /admin/config
  • Security: /admin/security
  • Statistics: /admin/statistics
  • Theme: /admin/theme
  • Plugins: /admin/plugins
  • Users: /admin/users
  • Logs: /admin/logs
  • Update: /admin/update
  • Guide: /admin/guide

SEO Optimization

Meta Tags

The CMS automatically adds meta tags:

<meta name="generator" content="CodePress CMS">
<meta name="author" content="E. Noorlander">
<meta name="description" content="...">
<meta name="keywords" content="...">

Security Headers

X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; ...

Frequently Asked Questions

How do I set the homepage?

  1. Go to Configuration in the admin panel (/admin/config)
  2. Select the desired page in the Default/homepage dropdown
  3. Click Save configuration

How does navigation work?

  • Directories become dropdown menus
  • Files become direct links
  • Sub-directories become nested dropdowns
  • Only files without a language prefix show in the menu

How do I add new content?

  1. Via the admin panel: /admin/content-new
  2. Or upload files to the content/ directory
  3. Organize in logical directories
  4. Use correct filenames and extensions

How do I move a file or directory?

  1. Go to /admin/content
  2. Click "Move" next to the item
  3. Select the target directory
  4. Confirm the move

How do I exclude my own IP from statistics?

  1. Go to Configuration in the admin panel (/admin/config)
  2. Scroll to the "IP Exclusions" field
  3. Enter your IP address (one per line)
  4. Click Save configuration

Troubleshooting

Page not found (404)

  1. Check filename and path
  2. Check file extension (.md, .php, .html)
  3. Check file permissions
  4. Check if the file has the correct language prefix (nl. or en.)

Navigation not updated

  1. Reload the page
  2. Check content directory structure
  3. Check filenames (no spaces)
  4. Files with language prefix only show in the correct language mode

Admin panel not accessible

  1. Check if the session is still valid
  2. On lockout: wait 15 minutes or clear lockout data in admin/config/admin.json
  3. Check CSRF token (reload the page)

Version

Current version: 1.9.1 Release date: 2026-07-29

Support

For technical support:

License

CodePress CMS is open-source software under dual-license: AGPL v3 for open-source use, commercial license for proprietary use.