691 lines
20 KiB
Markdown
691 lines
20 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)
|
|
│ │ │ ├── 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
|
|
|
|
```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",
|
|
"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`)
|
|
|
|
```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
|
|
<?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:
|
|
|
|
```yaml
|
|
---
|
|
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
|
|
|
|
```yaml
|
|
---
|
|
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:
|
|
```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.
|