Major changes: - New ThemeManager with Twig templating and SCSS compilation - Dynamic themes system (themes/default, themes/demo) - LogManager with SQLite storage and syslog forwarding - RequestLogger with static helper methods - Admin UI overhaul (Bootstrap 5, dark mode) - Admin config page with logging and theme settings - Admin logs page with filters and search - Removed legacy Mustache templates - Removed test plugin and theme - Composer dependencies: Twig, scssphp, CommonMark, MaxMind GeoIP
755 lines
24 KiB
Markdown
755 lines
24 KiB
Markdown
# CodePress CMS Guide
|
||
|
||
## Table of Contents
|
||
|
||
- [Overview](#overview)
|
||
- [Installation](#installation)
|
||
- [Project Structure](#project-structure)
|
||
|
||
- [Content](#content)
|
||
- [Content Structure](#content-structure)
|
||
- [Content API (for PHP content files)](#content-api-for-php-content-files)
|
||
|
||
- [Settings](#settings)
|
||
- [Configuration](#configuration)
|
||
- [Themes](#themes)
|
||
- [Security](#security)
|
||
|
||
- [Data](#data)
|
||
- [Statistics & Analytics](#statistics--analytics)
|
||
- [Logging](#logging)
|
||
|
||
- [System](#system)
|
||
- [Plugin System](#plugin-system)
|
||
- [User Management](#user-management)
|
||
- [Update](#update)
|
||
|
||
- [Guide (in Admin)](#guide-in-admin)
|
||
|
||
- [Other](#other)
|
||
- [Templates](#templates)
|
||
- [URL Structure](#url-structure)
|
||
- [SEO Optimization](#seo-optimization)
|
||
- [Frequently Asked Questions](#frequently-asked-questions)
|
||
- [Troubleshooting](#troubleshooting)
|
||
|
||
- [Version](#version)
|
||
- [Support](#support)
|
||
- [License](#license)
|
||
|
||
## 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)
|
||
│ │ │ ├── ThemeManager.php # Theme resolver + Twig render + SCSS compile
|
||
│ │ │ ├── Logger.php # Structured logging system
|
||
│ │ │ ├── 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
|
||
│ └── router.php # PHP dev server router (also serves /themes/)
|
||
├── themes/ # Dynamic themes (fully self-contained)
|
||
│ ├── default/ # Default theme
|
||
│ │ ├── theme.json # { title, config.default_template, template→.twig mapping }
|
||
│ │ ├── base.twig # Main layout (head, header, nav, footer)
|
||
│ │ ├── full_content.twig # Layout: full width
|
||
│ │ ├── left_sidebar.twig # Layout: sidebar left
|
||
│ │ ├── right_sidebar.twig # Layout: sidebar right
|
||
│ │ ├── custom1.twig # Layout: custom
|
||
│ │ ├── partials/ # header.twig, navigation.twig, footer.twig
|
||
│ │ ├── css/theme.scss # Colors, heights, background (compiled at runtime)
|
||
│ │ ├── js/theme.js # Theme JavaScript
|
||
│ │ └── theme.png # Preview image
|
||
│ ├── demo/ # Demo theme (same structure, different look)
|
||
│ └── test/ # Test theme
|
||
├── 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/ # Runtime compiled theme CSS (public/themes)
|
||
│ └── manifest.json / sw.js # PWA support
|
||
├── themes/ # Dynamic themes (fully self-contained)
|
||
│ ├── default/ # Default theme
|
||
│ │ ├── theme.json # Title, default template, template mapping
|
||
│ │ ├── base.twig # Main layout
|
||
│ │ ├── *.twig # Layout templates (full_content, left_sidebar, ...)
|
||
│ │ ├── partials/ # header, navigation, footer
|
||
│ │ ├── css/theme.scss # Colors, heights, background
|
||
│ │ ├── js/theme.js # Theme JavaScript
|
||
│ │ └── theme.png # Preview image
|
||
│ ├── demo/ # Demo theme
|
||
│ └── test/ # Test theme
|
||
├── 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
|
||
|
||
```php
|
||
// 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
|
||
|
||
```php
|
||
// Get menu structure
|
||
$menu = $api->getMenu();
|
||
// Nested array with 'title', 'path', 'url', 'children'
|
||
```
|
||
|
||
#### Configuration
|
||
|
||
```php
|
||
// Get config value (dot notation)
|
||
$title = $api->getConfig('site_title');
|
||
$lang = $api->getConfig('language.default');
|
||
$seoDesc = $api->getConfig('seo.description', 'Default description');
|
||
```
|
||
|
||
#### Current page
|
||
|
||
```php
|
||
// 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
|
||
|
||
```php
|
||
// 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();
|
||
```
|
||
|
||
#### Translations and search
|
||
|
||
```php
|
||
// Get translation
|
||
$label = $api->t('home');
|
||
|
||
// Search results (if searching)
|
||
if ($api->isSearching()) {
|
||
$results = $api->getSearchResults();
|
||
}
|
||
```
|
||
|
||
#### Example PHP content file
|
||
|
||
```php
|
||
---
|
||
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`
|
||
|
||
```json
|
||
{
|
||
"site_title": "CodePress",
|
||
"content_dir": "content",
|
||
"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`. This is a selection page: pick the active theme and click "Activate theme". Each theme is a fully self-contained folder in `themes/` with its own Twig templates, SCSS and JavaScript.
|
||
|
||
#### Theme structure (`themes/<name>/`)
|
||
|
||
```
|
||
themes/<name>/
|
||
├── theme.json # Title, default template, template mapping
|
||
├── base.twig # Main layout (head, header, nav, footer)
|
||
├── full_content.twig # Layout: full width
|
||
├── left_sidebar.twig # Layout: sidebar left
|
||
├── right_sidebar.twig # Layout: sidebar right
|
||
├── custom1.twig # Layout: custom
|
||
├── partials/ # header.twig, navigation.twig, footer.twig
|
||
├── css/theme.scss # Colors, heights, background (compiled at runtime)
|
||
├── js/theme.js # Theme JavaScript
|
||
└── theme.png # Preview image (shown in admin)
|
||
```
|
||
|
||
#### Theme Configuration (`themes/<name>/theme.json`)
|
||
|
||
```json
|
||
{
|
||
"title": "default",
|
||
"config": {
|
||
"default_template": "full_content"
|
||
},
|
||
"template": {
|
||
"full_content": "full_content.twig",
|
||
"left_sidebar": "left_sidebar.twig",
|
||
"right_sidebar": "right_sidebar.twig",
|
||
"custom1": "custom1.twig"
|
||
}
|
||
}
|
||
```
|
||
|
||
- **`config.default_template`**: the default template used when a page requests an unknown layout.
|
||
- **`template`**: the layout-key → `.twig` file mapping. A theme can have multiple template pages.
|
||
|
||
Colors, heights and background are **not** set in `theme.json` but in `css/theme.scss`:
|
||
|
||
```scss
|
||
$header-bg: #0a369d;
|
||
$header-font: #ffffff;
|
||
$header-height: 56px;
|
||
$nav-bg: #2754b4;
|
||
$nav-font: #ffffff;
|
||
$nav-height: 42px;
|
||
$sidebar-bg: #f8f9fa;
|
||
$sidebar-border: #dee2e6;
|
||
$header-bg-image: none; // optional header background
|
||
$header-bg-opacity: 1;
|
||
```
|
||
|
||
The SCSS is compiled at runtime into `public/themes/<name>/theme.css`.
|
||
|
||
#### How to create a new theme
|
||
|
||
Themes are created manually: copy the `themes/default/` folder to `themes/<name>/`, adjust the SCSS colors and templates, and add a `theme.png` preview. The theme is then available on `/admin/theme` to activate.
|
||
|
||
### 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 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.
|
||
- **Dynamic log** — structured log entries via `LogManager`, with event type, level, IP, and message.
|
||
|
||
#### Configuring dynamic logging
|
||
|
||
Via `/admin/config` → **Logging** you can configure how and what is recorded:
|
||
|
||
- **Storage**: `SQLite` (default) or `Syslog`.
|
||
- **Syslog server**: if a host is provided, log entries are sent to that server over UDP. Leave empty to use SQLite.
|
||
- **Facility**: the category of the log source in syslog. `local0`–`local7` are for your own applications; `daemon`, `user`, and `auth` are standard system categories.
|
||
- **Syslog ident**: the name that appears in the log message (e.g. `codepress`).
|
||
- **Events**: choose which types are recorded — `admin`, `requests`, `errors`, `security`, `content`, `system`.
|
||
|
||
If no syslog server is configured, SQLite is always used (with a file fallback if SQLite is unavailable).
|
||
|
||
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
|
||
<?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
|
||
|
||
Templates are Twig files per theme in `themes/<name>/`. `ThemeManager` renders them and compiles `css/theme.scss` at runtime into `public/themes/<name>/theme.css`.
|
||
|
||
#### 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** - `theme_title`, `theme_css_url`, `theme_js_url`, `theme_config` (config from theme.json)
|
||
|
||
**Language** - `current_lang`, `current_lang_upper`, `t_*` (translated strings)
|
||
|
||
#### Layout Options
|
||
|
||
Use YAML frontmatter to select the template. The layout key references a template in the active theme:
|
||
|
||
```yaml
|
||
---
|
||
title: My Page
|
||
layout: left_sidebar
|
||
plugins: HTMLBlock
|
||
---
|
||
```
|
||
|
||
#### Available Layouts
|
||
|
||
The available layouts are defined by the `template` section of the active theme (`themes/<name>/theme.json`). The default theme includes:
|
||
|
||
- `full_content` - Content only (full width)
|
||
- `left_sidebar` - Sidebar left, content right
|
||
- `right_sidebar` - Content left, sidebar right
|
||
- `custom1` - Custom layout
|
||
|
||
If a page requests an unknown layout, the `default_template` from the theme's `config` is used.
|
||
|
||
#### Meta Data
|
||
|
||
```yaml
|
||
---
|
||
title: Page Title
|
||
layout: left_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:
|
||
```html
|
||
<meta name="generator" content="CodePress CMS">
|
||
<meta name="author" content="E. Noorlander">
|
||
<meta name="description" content="...">
|
||
<meta name="keywords" content="...">
|
||
```
|
||
|
||
#### Security Headers
|
||
|
||
```http
|
||
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:
|
||
- **Git**: https://git.noorlander.info/E.Noorlander/CodePress
|
||
- **Website**: https://noorlander.info
|
||
- **Issues**: Report problems via Git issues
|
||
|
||
## License
|
||
|
||
CodePress CMS is open-source software under dual-license: AGPL v3 for open-source use, commercial license for proprietary use.
|