Version 1.0.0

Prime Core Documentation

A comprehensive, modern PHP content management system built from the ground up with security, performance, and extensibility in mind. No external PHP dependencies required.

Welcome

Thank you for choosing Prime Core CMS — a lightweight, feature-rich CMS built with a custom PHP MVC framework. Prime Core is designed for developers, agencies, and content creators who need a fast, secure, and easy-to-customize content management platform.

Key Features

Custom MVC Framework

Clean architecture with zero external PHP dependencies. Router, template engine, ORM-like database layer, and more — all built from scratch.

Advanced Security

CSRF protection, two-factor authentication (TOTP), rate limiting, IP blocking, bcrypt hashing, CSP headers, and XSS prevention.

Theme System

Included Starter theme with a flexible template engine supporting layouts, sections, partials, and auto-escaping. 3-level deep navigation menus, layout switcher (Grid/List/Magazine), social sharing, and reading progress bar. Additional theme skeleton (Flavor) ready for custom development.

SEO Optimized

Meta tags, Open Graph, JSON-LD schema, XML sitemap, custom redirects, robots.txt, and clean URLs out of the box.

Media Management

Full-featured media library with drag-and-drop uploads, folder organization, grid/list views, type filtering, bulk operations, and automatic responsive image generation (4 sizes with srcset).

Admin Dashboard

Beautiful admin panel built with Tailwind CSS, featuring analytics charts, quick actions, activity logs, real-time notification system, and comprehensive content management.

File-Based Caching

Page cache and data cache with configurable TTL, atomic writes, and cache statistics. No Redis or Memcached required.

Contact System

Built-in contact page with Google Maps integration, feedback form with CSRF protection, and admin message management panel.

Email System

Zero-dependency SMTP mailer built with raw PHP sockets. TLS/SSL support, HTML email templates, and a send_email() helper for password resets, contact notifications, and newsletters.

Content Versioning

Full revision history for posts and pages with word-level diff comparison (LCS algorithm), side-by-side compare view, and one-click restore. Autosave prevents data loss.

What Is Included

  • Complete Prime Core CMS source code
  • Frontend theme: Starter (Editorial Magazine style with Ink + Rose Gold color scheme) plus a Flavor skeleton theme for custom development
  • Built-in SMTP email system (no external PHP dependencies)
  • Real-time notification system with AJAX polling
  • Dedicated user profile page for all roles
  • Tailwind CSS standalone CLI (no Node.js required)
  • Web-based installer with demo content
  • This documentation file
  • SaaS-style landing page template (landing.html) — a premium product showcase page with feature breakdowns, pricing tiers, admin/frontend live previews, trust signals, testimonials, FAQ section, and demo credentials card for one-click demo access

Server Requirements

Before installing Prime Core, ensure your server meets the following requirements. The built-in installer will automatically verify these during setup.

PHP Requirements

RequirementMinimumNotes
PHP Version8.0+PHP 8.1 or 8.2 recommended for best performance

Required PHP Extensions

ExtensionPurpose
pdoDatabase abstraction layer
pdo_mysqlMySQL database driver
mbstringMultibyte string handling (UTF-8 support)
jsonJSON encoding/decoding
fileinfoMIME type detection for uploads
gdImage processing and dimension detection
curlHTTP client functionality
opensslEncryption and TOTP 2FA support
zipBackup creation and extraction

Database Requirements

SoftwareMinimum Version
MySQL5.7+
MariaDB10.3+

Web Server Requirements

  • Apache with mod_rewrite enabled (recommended)
  • Nginx with equivalent URL rewrite rules

Writable Directories

The following directories must be writable by the web server user (typically www-data or apache):

DirectoryPurpose
config/Configuration files are written during installation
cache/File-based page and data cache storage
storage/Session files, logs, and temporary data
uploads/User-uploaded media files
content/Theme files and content assets
Tip On Linux servers, you can set permissions with: chmod -R 775 config cache storage uploads content and ensure the directories are owned by the web server group.

Installation

Prime Core ships with a web-based installer that guides you through the entire setup process. No command-line access is required.

Quick Start

  1. Upload Files

    Upload all Prime Core files to your web server's document root (or a subdirectory). You can use FTP, SFTP, or your hosting provider's file manager. Ensure the .htaccess file is included (it may be hidden by default).

  2. Create a Database

    Create a new MySQL database and a database user with full privileges on that database. Note down the database name, username, password, and host (usually 127.0.0.1 or localhost).

  3. Run the Installer

    Navigate to https://your-domain.com/install in your web browser. The installer will launch automatically if the application has not been installed yet.

  4. Requirements Check

    The installer verifies your PHP version, required extensions, and directory permissions. All items must pass (shown with green checkmarks) before you can proceed. Fix any issues indicated in red and refresh the page.

  5. Database Setup

    Enter your database credentials:

    • Database Host — Usually 127.0.0.1 or localhost
    • Database Port — Default: 3306
    • Database Name — The database you created in Step 2
    • Username — Your database user
    • Password — Your database password
    • Table Prefix — Default: pm_ (useful for shared databases)

    The installer will test the connection before proceeding.

  6. Create Admin Account

    Set up your administrator account with a username, email address, password, and display name. Use a strong password — the system enforces a minimum of 8 characters.

  7. Site Settings

    Configure your site name, URL, and description. The URL should match your actual domain (e.g., https://your-domain.com). Do not include a trailing slash.

  8. Demo Content (Optional)

    Optionally install demo content including sample posts, categories, pages, tags, comments, menus, and media. This is recommended for first-time users to see the CMS in action. You can delete all demo content later.

  9. Finalize

    The installer creates your configuration files, sets the install lock, and provides you with a link to your admin panel. Save your login credentials!

Important After installation, the installer automatically sets an install lock. If you need to reinstall, you must remove the install lock by setting 'install_lock' => false in config/app.php and 'installed' => false.

Nginx Configuration

If you are using Nginx instead of Apache, add the following to your server block to enable clean URLs:

server {
    listen 80;
    server_name your-domain.com;
    root /var/www/html;
    index index.php;

    # Block access to sensitive directories
    location ~ ^/(config|core|storage|cache|admin/controllers|admin/views)/ {
        deny all;
        return 404;
    }

    # Block dotfiles
    location ~ /\. {
        deny all;
    }

    # Block PHP execution in uploads
    location ~ ^/uploads/.*\.php$ {
        deny all;
    }

    # Main rewrite rule
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP processing
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Configuration

All configuration is stored in PHP files within the config/ directory. These files are automatically generated during installation, but can be manually edited afterward.

Application Configuration config/app.php

KeyTypeDefaultDescription
namestringYour site name, displayed in the title and header
versionstring1.0.0Application version (do not change)
urlstringFull site URL without trailing slash
base_pathstring/Base path if installed in a subdirectory
admin_pathstringRandomized admin URL slug for security (e.g., admin-x7k9m)
timezonestringUTCPHP timezone identifier
debugboolfalseEnable debug mode (shows errors; never enable in production)
installedboolfalseSet to true after successful installation
install_lockboolfalsePrevents reinstallation when true
themestringstarterActive frontend theme directory name
per_pageint10Items per page in listings
cache_enabledbooltrueEnable file-based caching
cache_ttlint3600Cache time-to-live in seconds
upload_max_sizeint10485760Maximum upload file size in bytes (10 MB)
allowed_extensionsarraysee belowPermitted file upload extensions
maintenance_modeboolfalseEnable maintenance mode (blocks frontend)
maintenance_messagestringMessage displayed during maintenance
cookie_consentbooltrueShow cookie consent banner
google_analyticsstringGoogle Analytics tracking ID (e.g., G-XXXXXXXXXX)
encryption_keystringAuto-generated encryption key for security operations

Allowed File Extensions (Default)

'allowed_extensions' => [
    'jpg', 'jpeg', 'png', 'gif', 'webp',
    'pdf', 'doc', 'docx', 'xls', 'xlsx',
    'zip', 'rar', 'mp4', 'mp3'
]

Database Configuration config/database.php

KeyTypeDefaultDescription
hoststring127.0.0.1Database server hostname or IP
portint3306Database server port
databasestringDatabase name
usernamestringDatabase username
passwordstringDatabase password
charsetstringutf8mb4Character set for full Unicode support
collationstringutf8mb4_unicode_ciCollation for sorting and comparison
prefixstringpm_Table name prefix (useful for shared databases)
debugboolfalseLog all SQL queries (development only)
Security Warning Never commit your config/database.php file to a public repository. It contains database credentials. The .htaccess file blocks direct web access to the config directory, but always exercise caution.

File Structure

Below is the complete directory structure of Prime Core. Understanding this structure is essential for customization and theme development.

prime/ ├── index.php — Application entry point, routing, CSP headers ├── .htaccess — Apache rewrite rules and security directives ├── robots.txt — Search engine crawler directives ├── tailwind.admin.config.js — Tailwind config for admin panel ├── tailwind.frontend.config.js — Tailwind config for frontend theme ├── tailwindcss — Tailwind standalone CLI (v3.4.17) │ ├── config/ — Configuration files (generated by installer) │ ├── app.php — Application settings │ └── database.php — Database credentials │ ├── core/ — Framework core classes │ ├── Auth.php — Authentication and authorization │ ├── Autoloader.php — PSR-4 class autoloader │ ├── Cache.php — File-based caching system │ ├── Database.php — PDO database wrapper (singleton) │ ├── Helpers.php — Global helper functions │ ├── Router.php — URL routing engine │ ├── Security.php — CSRF, XSS, rate limiting, 2FA │ ├── Session.php — Secure session management │ ├── SitemapGenerator.php — XML sitemap builder │ ├── Mailer.php — Zero-dependency SMTP mailer │ └── Template.php — Template rendering engine │ ├── admin/ — Admin panel │ ├── controllers/ — 19 admin controllers │ │ ├── AuthController.php │ │ ├── DashboardController.php │ │ ├── PostController.php │ │ ├── PageController.php │ │ ├── CategoryController.php │ │ ├── TagController.php │ │ ├── CommentController.php │ │ ├── MediaController.php │ │ ├── MenuController.php │ │ ├── UserController.php │ │ ├── ProfileController.php — User profile (all roles) │ │ ├── SettingsController.php │ │ ├── SeoController.php │ │ ├── NewsletterController.php │ │ ├── ContactController.php │ │ ├── SearchController.php │ │ ├── LogController.php │ │ ├── CacheController.php │ │ └── BackupController.php │ │ │ ├── views/ — Admin panel templates │ │ ├── layouts/ — main.php, admin.php │ │ ├── auth/ — login.php, 2fa.php │ │ ├── dashboard/ — index.php │ │ ├── posts/ — index.php, form.php │ │ ├── pages/ — index.php, form.php │ │ ├── categories/ — index.php │ │ ├── tags/ — index.php │ │ ├── comments/ — index.php │ │ ├── media/ — index.php │ │ ├── menus/ — index.php │ │ ├── users/ — index.php, form.php │ │ ├── profile/ — index.php (user profile page) │ │ ├── settings/ — index.php │ │ ├── seo/ — index.php, redirects.php, robots.php │ │ ├── newsletter/ — index.php │ │ ├── contact/ — index.php │ │ ├── logs/ — activity.php, system.php │ │ ├── cache/ — index.php │ │ └── backup/ — index.php │ │ │ └── assets/ — Admin CSS and JavaScript │ ├── css/ │ │ ├── admin.css — Custom admin styles │ │ ├── tailwind.css — Built Tailwind output │ │ └── tailwind-input.css — Tailwind directives │ └── js/ │ └── admin.js — PrimeAdmin namespace │ ├── install/ — Web-based installer │ ├── InstallController.php │ ├── view.php — Single-page installer wizard (all steps) │ └── assets/ — Installer CSS and JavaScript │ ├── content/ — Themes and content │ └── themes/ │ ├── starter/ — Default theme │ │ ├── controllers/ │ │ │ └── FrontendController.php │ │ ├── templates/ │ │ │ ├── layout.php │ │ │ ├── home.php │ │ │ ├── post.php │ │ │ ├── page.php │ │ │ ├── category.php │ │ │ ├── tag.php │ │ │ ├── search.php │ │ │ ├── contact.php │ │ │ ├── 404.php │ │ │ └── maintenance.php │ │ ├── partials/ │ │ │ ├── sidebar.php │ │ │ ├── post-card.php │ │ │ ├── pagination.php │ │ │ └── breadcrumb.php │ │ └── assets/ │ │ ├── css/ │ │ │ ├── theme.css — Custom theme styles │ │ │ ├── tailwind.css — Built Tailwind output │ │ │ └── tailwind-input.css — Tailwind directives │ │ └── js/ │ │ └── theme.js │ └── flavor/ — Alternative theme │ ├── uploads/ — User-uploaded files │ ├── media/ — Media library files │ ├── thumbnails/ — Generated thumbnails │ ├── images/ — Resized image variants │ ├── avatars/ — User avatar uploads │ └── {YYYY}/{MM}/ — Date-based featured images │ ├── cache/ — Cache storage │ ├── data/ — Serialized data cache │ └── pages/ — Full-page HTML cache │ └── storage/ — Sessions, logs, temp files

Database Schema

Prime Core uses 20 database tables (all prefixed with pm_ by default). The schema is automatically created during installation. Below is a complete reference of every table and its columns.

pm_users

Stores administrator, editor, and author accounts.

ColumnTypeNotes
idINT AUTO_INCREMENT PKPrimary key
usernameVARCHAR(50) UNIQUELogin username
emailVARCHAR(255) UNIQUEEmail address
passwordVARCHAR(255)Bcrypt hash (cost 12)
display_nameVARCHAR(100)Public display name
avatarVARCHAR(255) NULLPath to uploaded avatar image
roleENUM('admin','editor','author','demo')User role with hierarchical permissions
bioTEXT NULLAuthor biography
two_factor_secretVARCHAR(255) NULLTOTP secret key (encrypted)
two_factor_enabledTINYINT(1) DEFAULT 0Whether 2FA is active
recovery_codesTEXT NULLJSON array of one-time recovery codes
statusENUM('active','inactive')Account status
last_loginDATETIME NULLLast successful login timestamp
created_atDATETIMEAccount creation timestamp
updated_atDATETIMELast update timestamp

pm_posts

Blog posts and articles with full SEO metadata support.

ColumnTypeNotes
idINT AUTO_INCREMENT PKPrimary key
user_idINTFK to pm_users
category_idINT NULLFK to pm_categories
titleVARCHAR(255)Post title
slugVARCHAR(255) UNIQUEURL-friendly slug
excerptTEXT NULLShort summary/teaser
contentLONGTEXTFull post content (HTML)
featured_imageVARCHAR(255) NULLPath to featured image
show_featured_imageTINYINT(1) DEFAULT 1Show featured image on full post page
statusENUM('draft','published','archived','scheduled')Publication status
is_featuredTINYINT(1) DEFAULT 0Featured post flag
is_stickyTINYINT(1) DEFAULT 0Sticky post flag
viewsINT DEFAULT 0View counter
reading_timeINT DEFAULT 0Estimated reading time in minutes
meta_titleVARCHAR(255) NULLSEO meta title override
meta_descriptionTEXT NULLSEO meta description override
og_imageVARCHAR(255) NULLOpen Graph image override
schema_typeVARCHAR(50) NULLJSON-LD schema type (Article, BlogPosting, etc.)
published_atDATETIME NULLPublication date
scheduled_atDATETIME NULLScheduled publication date
created_atDATETIMERecord creation
updated_atDATETIMELast modification

pm_pages

Static pages (About, Contact, etc.) with template selection and SEO fields.

ColumnTypeNotes
idINT AUTO_INCREMENT PKPrimary key
user_idINTFK to pm_users (author)
titleVARCHAR(255)Page title
slugVARCHAR(255) UNIQUEURL slug
contentLONGTEXTPage content (HTML)
excerptTEXT NULLShort summary
templateVARCHAR(100) NULLCustom template file name
featured_imageVARCHAR(255) NULLFeatured image path
statusENUM('draft','published','archived')Publication status
published_atDATETIME NULLPublication date
sort_orderINT DEFAULT 0Display ordering
meta_titleVARCHAR(255) NULLSEO title
meta_descriptionTEXT NULLSEO description
og_imageVARCHAR(255) NULLOpen Graph image
created_atDATETIMERecord creation
updated_atDATETIMELast modification

pm_categories

Hierarchical post categories with parent-child relationships.

ColumnTypeNotes
idINT AUTO_INCREMENT PKPrimary key
parent_idINT NULLParent category (self-referencing FK)
nameVARCHAR(100)Category name
slugVARCHAR(100) UNIQUEURL slug
descriptionTEXT NULLCategory description
imageVARCHAR(255) NULLCategory image
meta_titleVARCHAR(255) NULLSEO title
meta_descriptionTEXT NULLSEO description
sort_orderINT DEFAULT 0Display ordering
created_atDATETIMERecord creation
updated_atDATETIMELast modification

pm_tags & pm_post_tags

Tags provide a flat taxonomy for posts. The pm_post_tags table is a many-to-many junction table.

TableColumnTypeNotes
pm_tagsidINT AUTO_INCREMENT PKPrimary key
pm_tagsnameVARCHAR(50)Tag name
pm_tagsslugVARCHAR(50) UNIQUEURL slug
pm_tagscreated_atDATETIMERecord creation
pm_post_tagspost_idINTFK to pm_posts (composite PK)
pm_post_tagstag_idINTFK to pm_tags (composite PK)

pm_comments

Post comments with nested replies (parent-child), moderation status, and optional user association.

ColumnTypeNotes
idINT AUTO_INCREMENT PKPrimary key
post_idINTFK to pm_posts
parent_idINT NULLParent comment for threading
user_idINT NULLFK to pm_users (if logged in)
author_nameVARCHAR(100)Guest commenter name
author_emailVARCHAR(255)Guest commenter email
author_urlVARCHAR(255) NULLGuest commenter website
contentTEXTComment text
statusENUM('pending','approved','spam')Moderation status
ip_addressVARCHAR(45)Commenter IP (IPv4/IPv6)
user_agentTEXT NULLBrowser user agent string
created_atDATETIMEComment timestamp

pm_media

Media library entries tracking uploaded files, dimensions, and folder organization.

ColumnTypeNotes
idINT AUTO_INCREMENT PKPrimary key
user_idINTFK to pm_users (uploader)
filenameVARCHAR(255)Stored filename (may be sanitized)
original_nameVARCHAR(255)Original upload filename
mime_typeVARCHAR(100)MIME type (e.g., image/jpeg)
file_sizeINTFile size in bytes
dimensionsVARCHAR(20) NULLImage dimensions (e.g., 1920x1080)
alt_textVARCHAR(255) NULLAlt text for accessibility
folderVARCHAR(100) DEFAULT ''Organizational folder
disk_pathVARCHAR(500)Relative path on disk
created_atDATETIMEUpload timestamp

pm_menus & pm_menu_items

Configurable navigation menus with hierarchical items and multiple location support.

TableColumnTypeNotes
pm_menusidINT AUTO_INCREMENT PKPrimary key
pm_menusnameVARCHAR(100)Menu name
pm_menuslocationVARCHAR(50)Display location (header, footer)
pm_menuscreated_at / updated_atDATETIMETimestamps
pm_menu_itemsidINT AUTO_INCREMENT PKPrimary key
pm_menu_itemsmenu_idINTFK to pm_menus
pm_menu_itemsparent_idINT NULLParent item for dropdowns
pm_menu_itemstitleVARCHAR(100)Display text
pm_menu_itemsurlVARCHAR(255)Link URL
pm_menu_itemstypeENUM('custom','page','category','post')Link type
pm_menu_itemstargetVARCHAR(20)Link target (_blank, _self)
pm_menu_itemssort_orderINT DEFAULT 0Display order
pm_menu_itemscss_classVARCHAR(100) NULLCustom CSS classes

Other Tables

TablePurposeKey Columns
pm_settings Key-value settings storage setting_key (UNIQUE), setting_value, setting_group
pm_post_revisions Post content revision history post_id (FK), user_id (FK), title, content, revision_note
pm_page_revisions Page content revision history page_id (FK), user_id (FK), title, content, revision_note
pm_user_tokens Remember-me and password reset tokens user_id (FK), selector, validator, type ENUM('remember','password_reset'), expires_at
pm_redirects SEO URL redirects (301/302) from_url, to_url, status_code, hits
pm_activity_logs Admin activity audit trail user_id, action, description, ip_address
pm_newsletter_subscribers Email newsletter subscriptions email (UNIQUE), status, subscribed_at, unsubscribed_at
pm_login_attempts Login attempt tracking for rate limiting ip_address, username, attempted_at, successful
pm_blocked_ips IP address blocking ip_address (UNIQUE), reason, blocked_at, expires_at
pm_contact_messages Contact form submissions name, email, subject, message, ip_address, is_read

Routing

All routing is defined in the main index.php entry point. Prime Core uses a custom Router class that supports GET, POST, and ANY methods, route groups with prefixes and middleware, named routes, and URL generation.

Frontend Routes

MethodURI PatternHandlerDescription
GET/FrontendController::homeHomepage with featured/sticky/recent posts
GET/searchFrontendController::searchSearch results page (?q=keyword)
GET/page/{slug}FrontendController::pageStatic page display
GET/tag/{slug}FrontendController::tagTag archive page
GET/sitemap.xmlSitemapGeneratorXML sitemap for search engines
GET/robots.txtStatic fileCrawler directives
GET/{slug}FrontendController::categoryOrPageCategory archive or static page (auto-detected)
GET/{category}/{post}FrontendController::postSingle post display

API Routes

MethodURI PatternDescriptionResponse
GET/api/search?q=Search autocompleteJSON array of matching posts
POST/api/commentsSubmit a commentJSON success/error
POST/api/newsletter/subscribeNewsletter signupJSON success/error
POST/api/contactContact form submissionJSON success/error

Admin Routes

All admin routes are grouped under the randomized admin path (e.g., /admin-x7k9m/) and protected by authentication middleware. The admin path is set in config/app.php as admin_path.

URI PatternControllerActions
/DashboardControllerindex
/postsPostControllerindex, create, store, edit, update, delete
/pagesPageControllerindex, create, store, edit, update, delete
/categoriesCategoryControllerindex, create, store, edit, update, delete
/tagsTagControllerindex, store, delete
/commentsCommentControllerindex, approve, spam, delete
/mediaMediaControllerindex, upload, update, delete
/menusMenuControllerindex, create, store, edit, update, delete
/usersUserControllerindex, create, store, edit, update, delete
/profileProfileControllerindex, update (all roles)
/notifications/pollJSON endpoint for notification polling
/settingsSettingsControllerindex, update
/seoSeoControllerindex, redirects (CRUD), generate sitemap
/newsletterNewsletterControllerindex, delete, export
/contactContactControllerindex, view, delete
/searchSearchControllerGlobal admin search
/system-logsLogControllerindex, clear
/cacheCacheControllerindex, clear
/backupBackupControllerindex, create, download, delete

Route Middleware

Admin routes use an authentication middleware that checks for an active session and valid user. If not authenticated, users are redirected to the login page. The middleware also verifies the user's status is active.

// Middleware is applied via route groups
$router->group(['prefix' => $adminPath, 'middleware' => 'auth'], function($router) {
    $router->get('/', [DashboardController::class, 'index']);
    // ... more routes
});

Core Classes

Prime Core is built on a set of foundational classes located in the core/ directory. These form the framework layer that the application is built upon.

Database core/Database.php

A singleton PDO wrapper providing a fluent interface for database operations. Uses prepared statements exclusively to prevent SQL injection.

Key Methods

MethodDescription
getInstance()Returns the singleton database instance
query($sql, $params)Execute a raw SQL query with parameter binding
fetch($sql, $params)Fetch a single row as an associative array
fetchAll($sql, $params)Fetch all rows as an array of associative arrays
insert($table, $data)Insert a row and return the last insert ID
update($table, $data, $where, $params)Update rows matching a WHERE clause
delete($table, $where, $params)Delete rows matching a WHERE clause
count($table, $where, $params)Count rows in a table
beginTransaction()Start a database transaction
commit() / rollback()Commit or roll back a transaction
getPrefix()Returns the configured table prefix (e.g., pm_)
// Usage example
$db = Database::getInstance();
$prefix = $db->getPrefix();

// Fetch a single post
$post = $db->fetch(
    "SELECT * FROM {$prefix}posts WHERE slug = :slug AND status = 'published'",
    ['slug' => $slug]
);

// Insert a new record (table name without prefix — prefix is added automatically)
$id = $db->insert("posts", [
    'title' => 'My Post',
    'slug' => 'my-post',
    'content' => '<p>Hello world</p>',
    'status' => 'published',
    'user_id' => 1,
    'created_at' => date('Y-m-d H:i:s'),
    'updated_at' => date('Y-m-d H:i:s')
]);

Router core/Router.php

A lightweight URL router supporting dynamic parameters, route groups, middleware, and named routes.

Key Methods

MethodDescription
get($uri, $handler)Register a GET route
post($uri, $handler)Register a POST route
any($uri, $handler)Register a route for all HTTP methods
group($options, $callback)Group routes with shared prefix/middleware
dispatch()Match the current request and execute the handler
url($name, $params)Generate a URL from a named route
// Route with dynamic parameter
$router->get('/post/{slug}', [PostController::class, 'show']);

// Route group with prefix and middleware
$router->group(['prefix' => '/admin', 'middleware' => 'auth'], function($router) {
    $router->get('/dashboard', [DashboardController::class, 'index']);
    $router->post('/posts/store', [PostController::class, 'store']);
});

Template core/Template.php

A PHP-based template engine supporting layouts, sections, partials, and automatic HTML escaping.

Key Methods

MethodDescription
render($template, $data)Render a template with given data
extend($layout)Specify a parent layout
section($name) / endSection()Define a content section
yield($name)Output a section's content in the layout
partial($name, $data)Include a partial template
e($value)HTML-escape a value (alias for htmlspecialchars)

Template paths use context prefixes:

  • theme:: — Resolves to the active theme's templates directory
  • admin:: — Resolves to the admin views directory

Session core/Session.php

Secure session management with fixation prevention, timeout enforcement, and flash messages.

Features

  • Automatic session ID regeneration to prevent fixation attacks
  • Configurable session timeout (default: 30 minutes of inactivity)
  • Flash messages (data available only for the next request)
  • Remember-me token storage (file-based)
  • Secure cookie settings (HttpOnly, SameSite, Secure when HTTPS)

Security core/Security.php

Comprehensive security utilities including CSRF protection, rate limiting, 2FA, and more.

Key Features

FeatureDetails
CSRF ProtectionToken generation with lifetime-based expiry (default 1 hour). Validated on all POST requests. Tokens stored in $_SESSION['_prime_csrf']. Tokens are not rotated after validation to support multiple AJAX requests per page.
XSS PreventionHTML escaping via htmlspecialchars() with ENT_QUOTES | ENT_SUBSTITUTE and UTF-8 encoding.
Password HashingBcrypt with cost factor 12 via password_hash().
Rate LimitingDatabase-backed rate limiting on login attempts. Configurable threshold and lockout duration.
IP BlockingPermanent or time-based IP blocks stored in pm_blocked_ips table.
File Upload ValidationExtension whitelist, MIME type verification, file size limits, filename sanitization.
2FA (TOTP)RFC 6238 compliant Time-based One-Time Passwords. Compatible with Google Authenticator, Authy, etc.
Security HeadersContent-Security-Policy, X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy.

Auth core/Auth.php

Authentication and authorization manager handling login, session management, and role-based access control.

Role Hierarchy

RoleLevelPermissions
adminHighestFull access to all features, user management, settings, backups
editorMiddleManage all content (posts, pages, categories, tags, comments, media)
authorLowCreate and manage own posts only
demoLowestRead-only access to entire admin panel, all POST requests blocked

Key Methods

  • login($username, $password) — Authenticate a user with credentials
  • logout() — Destroy the session and remove remember-me cookies
  • check() — Check if a user is currently authenticated
  • user() — Get the currently authenticated user's data
  • hasRole($role) — Check if the current user has a specific role (or higher)
  • loginFromRememberCookie() — Authenticate via remember-me cookie (selector:validator pattern)
  • generatePasswordResetToken($email) — Create a time-limited password reset token
  • verifyTwoFactor($code) — Validate a TOTP code during 2FA verification

Cache core/Cache.php

File-based caching system with two cache types: data cache (serialized PHP objects) and page cache (full HTML output).

Key Methods

MethodDescription
get($key)Retrieve a cached value (returns null if expired)
set($key, $value, $ttl)Store a value with TTL (uses atomic writes)
delete($key)Remove a specific cache entry
flush()Clear all cache entries
getPageCache($url)Retrieve cached HTML for a URL
setPageCache($url, $html, $ttl)Cache full HTML output for a URL
getStats()Return cache statistics (size, file count)

Mailer core/Mailer.php

A zero-dependency SMTP mailer using raw PHP sockets. Supports TLS/SSL encryption, SMTP authentication, HTML emails, and custom headers.

Key Methods

MethodDescription
send($to, $subject, $body)Send an HTML email via SMTP
setFrom($email, $name)Set the sender address and name
setReplyTo($email)Set the reply-to address

Configuration is loaded automatically from the pm_settings table (keys: smtp_host, smtp_port, smtp_encryption, smtp_username, smtp_password, mail_from_email, mail_from_name).

SitemapGenerator core/SitemapGenerator.php

Generates dynamic XML sitemaps including published posts, categories, and pages with last-modified dates. The sitemap is accessible at /sitemap.xml and is automatically regenerated when content changes.

Helper Functions

Prime Core provides a rich set of global helper functions defined in core/Helpers.php. These are available everywhere in the application.

URL Helpers

FunctionDescriptionExample
site_url($path)Generate a full site URLsite_url('/about')https://example.com/about
admin_url($path)Generate an admin panel URLadmin_url('/posts')https://example.com/admin-x7k9m/posts
asset_url($path)Generate a theme asset URLasset_url('css/theme.css')
admin_asset_url($path)Generate an admin asset URLadmin_asset_url('admin.css')
upload_url($path)Generate an uploads URLupload_url('2024/photo.jpg')
current_url()Get the current page URL

Text & Formatting Helpers

FunctionDescription
e($value)HTML-escape a string (XSS prevention)
truncate_text($text, $length, $suffix)Truncate text to a specified length with a suffix
slugify($string)Convert a string to a URL-safe slug
format_date($date, $format)Format a date string
time_ago($date)Convert a date to relative time (e.g., "2 hours ago")
reading_time($content)Estimate reading time in minutes from HTML content
format_size($bytes)Format bytes to human-readable size (KB, MB, GB)
gravatar($email, $size)Generate a Gravatar URL from an email address
generate_toc($content)Generate a table of contents from HTML headings
add_heading_ids($content)Add ID attributes to HTML headings for anchor links

Security & Session Helpers

FunctionDescription
csrf_field()Output a hidden CSRF token input field
csrf_token()Get the current CSRF token value
set_flash($key, $value)Set a flash message (available for one request)
get_flash($key)Retrieve and remove a flash message
has_flash($key)Check if a flash message exists
redirect($url)Redirect to a URL and exit
get_client_ip()Get the client's IP address (uses REMOTE_ADDR only; does not trust proxy headers)

Utility Helpers

FunctionDescription
config($key, $default)Read a configuration value with dot notation
json_response($data, $code)Send a JSON response with HTTP status code
is_ajax()Check if the current request is an AJAX request
is_installed()Check if the application has been installed
log_activity($action, $desc)Log an admin activity to the audit trail
log_system($message)Write a message to the system log file
send_email($to, $subject, $body)Send an email via the configured SMTP mailer

Admin Panel

The admin panel is a full-featured content management interface built with Tailwind CSS (production build via standalone CLI — no CDN or Node.js required), TinyMCE 6.8.3 for rich text editing (lazy-loaded on demand), and Chart.js 4.4.1 for analytics charts (lazy-loaded on demand).

Accessing the Admin Panel

The admin panel URL is randomized during installation for security. You can find it in config/app.php under the admin_path key. The full URL follows this pattern:

https://your-domain.com/{admin_path}/
# Example: https://your-domain.com/admin-x7k9m/
Tip Bookmark your admin URL. The randomized path helps prevent automated attacks on your login page.

Dashboard

The dashboard provides an at-a-glance overview of your site with:

  • Statistics cards — Total posts, pages, comments, and users
  • Views chart — Post view trends over the past 30 days (Chart.js, lazy-loaded on demand)
  • Recent posts — Latest posts with quick-edit links
  • Recent comments — Latest comments awaiting moderation
  • Activity log — Recent admin actions
  • Quick actions — Clear cache, create new post, etc.

Authentication Features

  • Login — Username/email and password with rate limiting (5 attempts per 15 minutes per IP)
  • Remember Me — Persistent login using secure selector:validator token pattern
  • Forgot Password — Email-based password reset with time-limited tokens
  • Two-Factor Authentication — TOTP-based 2FA with QR code setup and recovery codes
  • Session Security — Auto-timeout after 30 minutes, session fixation prevention

Notification System

The admin panel includes a real-time notification bell icon in the top navigation bar. Notifications are polled every 60 seconds via AJAX and alert administrators to items requiring attention.

Notification Types

  • Pending Comments — Comments awaiting moderation approval
  • Unread Messages — New contact form submissions not yet read
  • New Subscribers — Newsletter signups within the last 24 hours
  • Scheduled Posts — Posts scheduled to publish within the next hour

How It Works

  • Notification counts are queried at page load from the database and rendered server-side in main.php layout
  • A JavaScript polling loop in admin.js calls GET /{admin-path}/notifications/poll every 60 seconds
  • The endpoint returns a JSON response with { total, items[] }
  • The bell icon badge updates dynamically — it hides automatically when there are zero notifications
  • Clicking the bell opens a dropdown with color-coded notification rows and count badges
  • Each notification row links to its relevant admin section (comments, contact, newsletter, posts)

Posts

Posts are the primary content type in Prime Core. They support rich text editing, categories, tags, featured images, SEO metadata, and revision history.

Creating a Post

  1. Navigate to Posts in the admin sidebar
  2. Click Create New Post
  3. Fill in the post details:
    • Title — The post headline (slug is auto-generated)
    • Content — Rich text editor (TinyMCE) with image uploads, code blocks, tables, etc.
    • Excerpt — Short summary for listings and search results
    • Category — Select from existing categories (auto-assigned to "Uncategorized" if none selected)
    • Tags — Assign multiple tags
    • Featured Image — Select from the media library
      • Show on full post page — If unchecked, the featured image will only appear in post cards/listings, not on the full post page
    • Status — Draft, Published, Scheduled, or Archived
    • Featured/Sticky — Flag as featured or sticky post
  4. Configure SEO settings (optional):
    • Meta title and description overrides
    • Open Graph image
    • Schema type (Article, BlogPosting, NewsArticle)
  5. Click Save or Publish

Post Statuses

StatusBehavior
draftNot visible on the frontend. Only accessible in admin.
publishedVisible on the frontend. Appears in listings, feeds, and search.
scheduledWill be automatically published at the scheduled date/time.
archivedHidden from listings but may still be accessible via direct URL.

Revisions

Every time a post is updated, a revision is automatically saved to the pm_post_revisions table. Revisions store the title, content, user who made the change, and an optional revision note. This provides a complete content audit trail.

Revision Diff & Compare

The post editor includes a revisions sidebar that lists all previous versions. For each revision you can:

  • Compare — Opens a side-by-side diff modal showing word-level changes between the revision and the current version, using an LCS (Longest Common Subsequence) algorithm with color-coded additions (green) and deletions (red)
  • Restore — Reverts the post content to the selected revision

Autosave

The post editor automatically saves drafts at regular intervals via AJAX, preventing data loss. The autosave status indicator shows when the last save occurred. Use PrimeAdmin.autoSave() to configure autosave behavior.

Auto-Categorization

If a post is saved without selecting a category, it is automatically assigned to an "Uncategorized" category. This category is created automatically if it doesn't exist. This ensures all posts have a valid category for proper URL routing (posts use the /{category}/{slug} URL pattern).

Menu Item Cleanup

When you delete a Category, Tag, or Page, any menu items linking to that content are automatically removed (including child menu items). This prevents broken links in your navigation menus.

Pages

Pages are static content (About, Contact, Terms, etc.) that are not associated with categories or tags. They support custom templates, sort ordering, and full SEO metadata.

Creating a Page

  1. Navigate to Pages in the admin sidebar
  2. Click Create New Page
  3. Fill in the page details:
    • Title — The page title
    • Content — Rich text editor
    • Excerpt — Short summary
    • Template — Select a custom template file (optional)
    • Featured Image — Optional header image
    • Status — Draft, Published, or Archived
    • Sort Order — Numeric value for ordering in navigation
  4. Configure SEO settings (optional)
  5. Click Save

Page URLs

Pages are accessible at /page/{slug} or /{slug}. The router first checks for a matching category when a single-segment URL is accessed, then falls back to pages.

Custom Templates

You can assign a custom template to any page. Create a new PHP file in your theme's templates/ directory and select it from the Template dropdown when editing the page. For example, a contact.php template is included for the contact page.

Page Revisions

Like posts, pages also support a full revision history system. Every update creates a revision in the pm_page_revisions table. The page editor includes a revisions sidebar with word-level diff comparison and one-click restore — identical to the post revision system.

Categories & Tags

Categories

Categories provide a hierarchical taxonomy for organizing posts. Each category can have:

  • Name and Slug — Display name and URL-friendly identifier
  • Parent Category — For creating nested hierarchies
  • Description — Category description for archive pages
  • Image — Category header/thumbnail image
  • SEO Fields — Meta title and description for the archive page
  • Sort Order — Control display ordering

Category archive pages display all published posts within that category, accessible at /{category-slug}.

Tags

Tags provide a flat (non-hierarchical) taxonomy for cross-cutting content classification. A post can have multiple tags, and tags can be shared across posts.

  • Tags are managed inline from the admin panel (create and delete)
  • Tags are assigned to posts via the post editor
  • Tag archive pages are accessible at /tag/{tag-slug}
  • Tags display with post counts in the admin listing

Media Manager

The media manager provides a centralized library for uploading, organizing, and managing files.

Features

  • Drag and Drop — Drop files directly onto the upload area
  • File Validation — Extension whitelist, MIME type check, and size limit enforcement
  • Image Dimensions — Automatic detection and storage of image dimensions
  • Responsive Image Variants — Automatic generation of 4 image sizes on upload: Original, Thumbnail (150×150), Medium (max 600×400), and Large (max 1200×800) with responsive srcset attributes on the frontend
  • Folder Organization — Organize files into folders. Folders are scanned from the uploads/media/ directory on the filesystem, so empty folders are also displayed. Create new folders directly from the media manager sidebar.
  • Alt Text — Inline AJAX editing of accessibility alt text with debounced auto-save
  • Grid/List Toggle — Switch between grid view (thumbnails) and list view (table), with preference persisted in localStorage
  • Type Filtering — Filter by All, Images, or Documents using tab navigation
  • Bulk Actions — Select multiple files with checkboxes and delete in bulk
  • Thumbnail Optimization — Grid view displays optimized thumbnails instead of full-size images
  • TinyMCE Integration — Browse and insert media directly into posts and pages from the editor

Upload Limits

SettingDefaultConfiguration
Maximum file size10 MBupload_max_size in config/app.php
Allowed extensionsjpg, jpeg, png, gif, webp, pdf, doc, docx, xls, xlsx, zip, rar, mp4, mp3allowed_extensions in config/app.php
Note PHP's own upload_max_filesize and post_max_size directives in php.ini must also be large enough to handle your desired upload size. The CMS validates against the lower of the two limits.

Comments

Prime Core includes a comment system with moderation, threaded replies, and spam management.

Comment Flow

  1. Visitors submit comments via the AJAX-powered comment form on post pages
  2. Comments are submitted to /api/comments with CSRF protection
  3. New comments default to pending status and require admin approval
  4. Admins can approve, mark as spam, or delete comments from the admin panel
  5. Only approved comments are displayed on the frontend

Comment Features

  • Threaded Replies — Comments support parent-child relationships for threaded discussions
  • Guest Comments — Visitors can comment with name, email, and optional URL
  • IP Tracking — Commenter IP and user agent are stored for moderation
  • Gravatar Support — Commenter avatars are generated from email addresses via Gravatar
  • Bulk Moderation — Approve or delete multiple comments at once

Users & Roles

User management supports creating multiple admin, editor, author, and demo accounts with role-based permissions.

Role Permissions

FeatureAdminEditorAuthorDemo
DashboardFull statsLimited statsOwn statsView only
PostsAllAllOwn onlyView only
PagesAllAllView only
Categories & TagsFullFullView only
CommentsFullFullView only
MediaFullFullOwn onlyView only
MenusFullView only
UsersFullView only
SettingsFullView only
SEO & RedirectsFullView only
BackupsFullView only
ProfileOwnOwnOwnView only

Profile Management

Prime Core includes a dedicated profile page accessible to all authenticated users (admin, editor, author, and demo) at /{admin-path}/profile. This is handled by ProfileController.php — a separate controller from UserController — ensuring every role can manage their own account without needing access to the Users admin section.

  • Display name and bio
  • Email address
  • Password change (with current password confirmation)
  • Avatar upload (with Gravatar fallback)
  • Two-factor authentication setup
  • Username, role, and account status displayed as read-only

The profile link is available in the top-right user dropdown menu of the admin layout.

Demo Mode

Prime Core includes a built-in demo mode designed for live preview environments (e.g., Envato marketplace demos). When enabled, a special demo user role provides full read-only access to the entire admin panel without allowing any modifications.

How It Works

  • Router-Level Middleware — A middleware in index.php intercepts all POST requests for users with the demo role. Only logout is permitted.
  • AJAX Requests — Returns a JSON 403 response with a descriptive message, so AJAX forms display clean error feedback.
  • Regular POST — Redirects back with a flash message: "This is a demo admin panel. Modifications are not permitted in demo mode."
  • Demo Banner — A sticky banner is displayed at the top of every admin page when logged in as a demo user.
  • Account Protection — The demo user account cannot be modified or deleted by any user, including admins.

Demo User Setup

A demo user is automatically created when demo content is installed during the installation wizard:

FieldValue
Emaildemo@example.com
Passworddemo
Roledemo

Login Page Integration

When a demo user exists in the database, the login page automatically displays an "Access Demo Panel" button that pre-fills the demo credentials and submits the form — providing a one-click demo experience for visitors.

Settings

The Settings panel provides a centralized interface for configuring all aspects of your site. Settings are stored in the pm_settings table as key-value pairs with grouping.

General Settings

  • Site Name — Displayed in the header, title tags, and email templates
  • Site Description — Default meta description for the homepage
  • Site Logo — Upload a logo image
  • Favicon — Upload a favicon
  • Timezone — Set the server timezone for date display
  • Posts Per Page — Number of posts shown in listings

Social Links

Configure social media profile URLs that are displayed in the frontend sidebar and footer:

  • Facebook, Twitter/X, Instagram, LinkedIn, YouTube, GitHub

Analytics & Tracking

  • Google Analytics — Enter your GA tracking ID (e.g., G-XXXXXXXXXX)
  • Cookie Consent — Enable/disable the cookie consent banner

Maintenance Mode

Enable maintenance mode to take the frontend offline while performing updates. Logged-in administrators can still access the site. Configure a custom maintenance message.

Contact Page Settings

Contact page settings are displayed when a page with the slug contact exists and is published. The settings tab will show a warning if the contact page is missing or not published, with a quick link to create/edit it.

  • Office Address — Physical address displayed on the contact page
  • General Email — Primary email address displayed; also used as the Reply-To address for auto-replies
  • Support Email — Support email address displayed
  • Phone Number — Phone number displayed on the contact page
  • Business Hours — Weekday, Saturday, and Sunday hours
  • Google Maps Embed URL — Embed URL for the Google Maps iframe on the contact page

Auto-Reply

When enabled, users who submit the contact form receive an automatic confirmation email. This is optional but recommended for professional communication.

  • Enable Auto-Reply — Toggle to send confirmation emails automatically
  • Email Subject — Subject line for the auto-reply email
  • Email Message — Customizable message body with variable support
  • Test Button — Send a test email to verify your configuration

Available Variables:

VariableReplaced With
{name}Submitter's name
{email}Submitter's email address
{subject}Subject line from the form
{message}Message content (truncated to 200 characters)
{site_name}Your site name from General settings

Reply-To Header: Auto-reply emails include a Reply-To header set to your General Email, so users can reply directly to the confirmation email and reach your team.

Default Message:

Hi {name},

Thank you for reaching out to us! We have received your message and our team will get back to you within 24-48 hours.

Best regards,
{site_name}

Email / SMTP Settings

Configure the built-in SMTP mailer for sending emails (password resets, contact notifications, newsletter). See the Email System section for detailed configuration instructions.

  • SMTP Host — Mail server hostname
  • SMTP Port — Connection port (587 for TLS, 465 for SSL)
  • SMTP Encryption — TLS, SSL, or none
  • SMTP Username/Password — Authentication credentials
  • From Email / From Name — Default sender identity
  • Test Email — Send a test message to verify configuration

SEO & Redirects

Built-in SEO Features

  • Meta Tags — Custom meta title and description for every post, page, and category
  • Open Graph — Full OG tag support for social media sharing (og:title, og:description, og:image, og:type)
  • JSON-LD Schema — Structured data markup for posts (Article, BlogPosting, NewsArticle)
  • XML Sitemap — Auto-generated sitemap at /sitemap.xml including posts, categories, and pages with last-modified dates
  • Robots.txt — Configurable via /robots.txt
  • Canonical URLs — Automatic canonical URL tags on all pages
  • Clean URLs — SEO-friendly URL structure (/{category}/{post-slug})
  • Breadcrumbs — Automatic breadcrumb navigation

URL Redirects

Manage 301 (permanent) and 302 (temporary) redirects from the SEO settings page. This is useful when you change post slugs or restructure your site. Each redirect tracks the number of hits.

FieldDescription
From URLThe old URL path (e.g., /old-post-slug)
To URLThe new URL path (e.g., /new-post-slug)
Status Code301 (permanent) or 302 (temporary)
HitsNumber of times the redirect has been followed

Sitemap Generation

The sitemap is generated dynamically and includes:

  • All published posts with their last modified date and category URL prefix
  • All categories with post counts
  • All published pages
  • The homepage

You can regenerate the sitemap manually from the SEO settings page, or it is regenerated automatically when content changes.

Newsletter

Prime Core includes a built-in newsletter subscription system for collecting email addresses from your visitors.

How It Works

  1. A subscription form is displayed in the frontend sidebar
  2. Visitors enter their email and submit via AJAX (POST /api/newsletter/subscribe)
  3. The email is validated and stored in pm_newsletter_subscribers
  4. Duplicate emails are rejected with a friendly message

Admin Management

  • View Subscribers — See all subscribers with their status and subscription date
  • Delete Subscribers — Remove individual subscribers
  • Export to CSV — Download all subscribers as a CSV file for use with email marketing services (Mailchimp, SendGrid, etc.)
  • Send Emails — With the built-in SMTP system configured (see Email System), you can send emails directly to subscribers
Note Prime Core includes a built-in SMTP email system (core/Mailer.php) that can send emails directly. Configure your SMTP settings in Settings → Email to enable email sending for newsletters, contact form notifications, and password reset emails. You can also export subscribers as CSV for use with external email marketing platforms.

Email System

Prime Core includes a zero-dependency SMTP mailer (core/Mailer.php) that sends emails directly from the server using raw PHP sockets. No external libraries like PHPMailer or SwiftMailer are needed.

Configuration

Configure email settings from Settings → Email in the admin panel:

SettingDescriptionExample
SMTP HostMail server hostnamesmtp.gmail.com
SMTP PortConnection port587 (TLS) or 465 (SSL)
SMTP EncryptionEncryption methodtls, ssl, or none
SMTP UsernameAuthentication usernameyour@gmail.com
SMTP PasswordAuthentication passwordApp-specific password
From EmailSender email addressnoreply@yoursite.com
From NameSender display namePrime Core

Features

  • Zero Dependencies — Pure PHP socket-based SMTP communication (no Composer packages)
  • TLS/SSL Support — Secure connections via STARTTLS or direct SSL
  • HTML Email — Sends rich HTML emails with proper MIME headers
  • Email Templates — Consistent, branded email templates for all outgoing messages
  • Test Email — Send a test email from the admin settings to verify your SMTP configuration

Usage

Use the send_email() helper function anywhere in the application:

// Send an email using the helper
send_email(
    'recipient@example.com',
    'Subject Line',
    '<p>HTML email body content</p>'
);

// Or use the Mailer class directly
$mailer = new \Core\Mailer();
$mailer->send('recipient@example.com', 'Subject', $htmlBody);

Where Emails Are Used

  • Password Reset — Sends a reset link to the user's email
  • Contact Form — Notifies the admin when a new contact message is received
  • Newsletter — Ability to send emails to newsletter subscribers
Important For Gmail SMTP, you must use an App Password (not your regular Google password) if 2-Step Verification is enabled on your Google account.

Contact Messages

The contact system provides a public-facing contact page with a feedback form and an admin panel for managing received messages.

Contact Page Features

  • Google Maps Embed — Configurable Google Maps iframe showing your location
  • Contact Information — Displays email, phone, and address from settings
  • Feedback Form — Name, email, subject, and message fields with CSRF protection
  • AJAX Submission — Form submits via POST /api/contact with real-time validation feedback
  • IP Tracking — Sender IP is recorded for spam prevention

Admin Management

  • Message List — View all messages with read/unread status
  • View Message — Read full message details including sender info and IP
  • Mark as Read — Messages are automatically marked as read when viewed
  • Delete — Remove messages individually
  • Unread Counter — Dashboard and sidebar show unread message count

Configuration

Configure the contact page from Settings in the admin panel:

  • Enable or disable the contact page
  • Set the contact email, phone, and address
  • Configure the Google Maps embed URL (get it from Google Maps > Share > Embed a map)

Theme System

Prime Core uses a theme-based frontend system. Themes are self-contained packages that include controllers, templates, partials, and assets.

Included Themes

ThemeDescription
StarterA clean, minimal theme perfect as a starting point for custom development. Includes all template files.
FlavorA skeleton theme with the directory structure ready for custom development. Copy and build your own design on top of it.

Design System

Prime Core uses a unified design system across the frontend theme, admin panel, and installer. The visual identity is defined by custom CSS properties and Tailwind config tokens:

ElementValue
Primary Color (Ink)#0f172a — deep navy
Ink Light#1e293b
Ink Muted#475569
Accent (Rose Gold)#c2727d
Rose Gold Light#e8a5ad
Rose Gold Dark#a85d67
Background (Cream)#fafaf9
Warm Gray#f1f5f9
Heading FontOutfit (geometric sans-serif, weights 400–800)
Body FontPlus Jakarta Sans (sans-serif, weights 300–700)
Monospace FontFira Code (weights 400–500)

These values are defined as CSS custom properties in theme.css (frontend), admin.css (admin panel), and inline styles in install/view.php (installer). The Tailwind configs (tailwind.frontend.config.js and tailwind.admin.config.js) mirror these tokens for utility class generation.

Theme Structure

content/themes/your-theme/ ├── controllers/ │ └── FrontendController.php — Handles all frontend routes ├── templates/ │ ├── layout.php — Master layout (header, footer, sidebar) │ ├── home.php — Homepage template │ ├── post.php — Single post template │ ├── page.php — Static page template │ ├── category.php — Category archive template │ ├── tag.php — Tag archive template │ ├── search.php — Search results template │ ├── contact.php — Contact page template │ ├── 404.php — Not found error page │ └── maintenance.php — Maintenance mode page ├── partials/ │ ├── sidebar.php — Sidebar widget area │ ├── post-card.php — Post card partial │ ├── pagination.php — Pagination partial │ └── breadcrumb.php — Breadcrumb navigation └── assets/ ├── css/ │ ├── theme.css — Custom theme styles │ ├── tailwind.css — Built Tailwind output │ └── tailwind-input.css — Tailwind directives └── js/ └── theme.js

Switching Themes

To switch the active theme, change the theme value in config/app.php:

// config/app.php
'theme' => 'flavor',  // Change from 'starter' to 'flavor'

Creating a Custom Theme

  1. Copy the starter theme directory and rename it
  2. Modify the templates, CSS, and JavaScript to match your design
  3. Update the FrontendController.php if you need to change data fetching logic
  4. Update config/app.php to use your new theme name
Tip The FrontendController.php in each theme handles all frontend data fetching and template rendering. It provides data to templates and receives route parameters from the router. Study the Starter theme's controller to understand the data flow.

Template Reference

Every frontend template receives a set of common variables plus template-specific data. All variables are accessible as PHP variables within templates.

Common Variables (All Templates)

VariableTypeDescription
$siteNamestringSite name from settings
$siteDescstringSite description
$siteLogostring|nullLogo image URL
$faviconstring|nullFavicon URL
$gaCodestring|nullGoogle Analytics tracking ID
$headerMenuarrayHeader navigation menu items
$footerMenuarrayFooter navigation menu items
$settingsarrayAll site settings as key-value pairs
$socialLinksarraySocial media URLs
$cookieConsentboolWhether to show the cookie banner
$sidebararraySidebar data (categories, tags, recent posts)
$breadcrumbsarrayBreadcrumb navigation trail
$pageTitlestringPage title for the <title> tag
$metaDescstringMeta description for the page
$canonicalstringCanonical URL
$ogTypestringOpen Graph type (website, article)
$ogImagestring|nullOpen Graph image URL
$templateFilestringCurrent template filename

Template-Specific Variables

home.php

  • $featuredPosts — Array of featured posts
  • $stickyPosts — Array of sticky posts
  • $posts — Paginated array of recent posts
  • $pagination — Pagination data (current page, total pages, etc.)
Compact Hero Grid The homepage features a compact hero grid showcasing featured posts in an editorial magazine layout. The grid displays 1 large featured post on the left (with background image, category badge, title, excerpt, author avatar, date, and reading time) and 3 smaller posts on the right side. Dimensions are optimized for readability: 320px height on desktop, 280px on tablet, and fully responsive on mobile with stacked layout. Images support responsive srcset with multiple size variants.
Layout Switcher The homepage and category archive templates include a layout switcher that lets visitors toggle between three display modes: Grid (card columns), List (horizontal rows with side thumbnails), and Magazine (editorial-style mixed layout). The selected layout is persisted in localStorage so it survives page reloads. The switcher UI is rendered as icon buttons above the post grid.

post.php

  • $post — The current post object (all columns)
  • $category — The post's category
  • $tags — Array of tags associated with the post
  • $comments — Approved comments (threaded)
  • $relatedPosts — Related posts from the same category
  • $author — Author information
  • $toc — Table of contents generated from headings
  • $prevPost — Previous post (for navigation, with thumbnail)
  • $nextPost — Next post (for navigation, with thumbnail)
Social Sharing & Post Features The single post template includes built-in social share buttons (Twitter/X, Facebook, LinkedIn, and Copy Link) displayed both above and below the article content. It also features a reading progress bar at the top of the page, an auto-generated table of contents from headings, an author bio box, previous/next post navigation with thumbnails, and a related posts section showing up to 4 posts from the same category.

category.php

  • $category — The current category object
  • $posts — Paginated posts in this category
  • $pagination — Pagination data

tag.php

  • $tag — The current tag object
  • $posts — Paginated posts with this tag
  • $pagination — Pagination data

search.php

  • $query — The search query string
  • $posts — Matching posts
  • $totalResults — Total number of results
  • $pagination — Pagination data

contact.php

  • $contactEmail — Contact email from settings
  • $contactPhone — Contact phone from settings
  • $contactAddress — Contact address from settings
  • $googleMapsUrl — Google Maps embed URL from settings

page.php

  • $page — The current page object (all columns)

API Endpoints

Prime Core provides four public API endpoints used by the frontend JavaScript for dynamic interactions. All endpoints return JSON responses.

Search Autocomplete

GET /api/search?q={query}

// Response (200 OK)
[
    {
        "title": "Post Title",
        "url": "/category-slug/post-slug",
        "excerpt": "Short excerpt...",
        "image": "/uploads/featured.jpg"
    }
]

Submit Comment

POST /api/comments
Content-Type: application/x-www-form-urlencoded

Parameters:
  post_id       (required) - The post ID
  author_name   (required) - Commenter name
  author_email  (required) - Commenter email
  content       (required) - Comment text
  parent_id     (optional) - Parent comment ID for replies
  csrf_token    (required) - CSRF token

// Response (200 OK)
{
    "success": true,
    "message": "Comment submitted for moderation"
}

// Response (422 Validation Error)
{
    "success": false,
    "message": "Validation error description"
}

Newsletter Subscribe

POST /api/newsletter/subscribe
Content-Type: application/x-www-form-urlencoded

Parameters:
  email         (required) - Subscriber email
  csrf_token    (required) - CSRF token

// Response (200 OK)
{
    "success": true,
    "message": "Successfully subscribed!"
}

// Response (409 Conflict)
{
    "success": false,
    "message": "Email already subscribed"
}

Contact Form

POST /api/contact
Content-Type: application/x-www-form-urlencoded

Parameters:
  name          (required) - Sender name
  email         (required) - Sender email
  subject       (required) - Message subject
  message       (required) - Message content
  csrf_token    (required) - CSRF token

// Response (200 OK)
{
    "success": true,
    "message": "Message sent successfully!"
}

// Response (422 Validation Error)
{
    "success": false,
    "message": "Validation error description"
}

Security

Prime Core implements multiple layers of security to protect your site and its data.

CSRF Protection

All POST requests are protected by CSRF tokens. The system generates a unique token stored in $_SESSION['_prime_csrf'] and validates it on every form submission.

<!-- In forms, use the csrf_field() helper -->
<form method="POST">
    <?= csrf_field() ?>
    <!-- form fields -->
</form>

<!-- For AJAX requests, include the token as a parameter -->
<script>
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
fetch('/api/endpoint', {
    method: 'POST',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    body: 'csrf_token=' + csrfToken + '&other=data'
});
</script>

Two-Factor Authentication (2FA)

Users can enable TOTP-based two-factor authentication from their profile settings.

  1. Enable 2FA from the user profile page
  2. Scan the QR code with an authenticator app (Google Authenticator, Authy, etc.)
  3. Enter the 6-digit verification code to confirm setup
  4. Save the recovery codes in a secure location

When 2FA is enabled, users must enter a 6-digit code after their password on every login. Recovery codes provide backup access if the authenticator device is lost.

Rate Limiting

Login attempts are rate-limited per IP address. After 5 failed attempts within 15 minutes, the IP is temporarily blocked from further login attempts. All attempts (successful and failed) are logged in the pm_login_attempts table.

IP Blocking

Administrators can manually block IP addresses from the Security settings. Blocked IPs are denied access to the entire site. Blocks can be permanent or time-limited (with an expiration date).

Content Security Policy (CSP)

Prime Core sends a Content-Security-Policy header that restricts resource loading to trusted sources:

  • Scripts: Self, CDN hosts (cdn.tiny.cloud, cdn.jsdelivr.net) — TinyMCE and Chart.js are loaded from CDN on demand
  • Styles: Self, with unsafe-inline for TinyMCE compatibility
  • Images: Self, data URIs, blob URIs, Gravatar, uploads
  • Fonts: Self
  • Frames: Self, Google Maps (google.com/maps)

Security Headers

The following security headers are set via .htaccess and PHP:

HeaderValue
X-Content-Type-Optionsnosniff
X-Frame-OptionsSAMEORIGIN
X-XSS-Protection1; mode=block
Referrer-Policystrict-origin-when-cross-origin

Directory Protection

The .htaccess file blocks direct web access to sensitive directories and files:

  • config/ — Configuration files with database credentials
  • core/ — Framework source code
  • storage/ — Sessions, logs, and temporary files
  • cache/ — Cached data and pages
  • admin/controllers/ — Admin controller source code
  • admin/views/ — Admin template source code
  • .env, .git — Environment files and git data

Additionally, PHP execution is blocked in the uploads/ directory to prevent uploaded script execution.

Randomized Admin URL

During installation, the admin panel URL is assigned a random slug (e.g., /admin-x7k9m/) instead of a predictable /admin/. This prevents automated bots from targeting your login page.

Caching

Prime Core includes a file-based caching system that requires no external services like Redis or Memcached. Caching significantly improves page load times by avoiding redundant database queries.

Cache Types

TypeStoragePurpose
Data Cachecache/data/Serialized PHP objects (query results, computed data)
Page Cachecache/pages/Full HTML output of rendered pages

Configuration

// config/app.php
'cache_enabled' => true,    // Enable/disable caching globally
'cache_ttl' => 3600,        // Cache lifetime: 3600 seconds (1 hour)

Cache Management

From the admin panel, navigate to Cache to:

  • View cache statistics (total files, total size)
  • Clear all cache with a single click
  • Cache is automatically invalidated when content is created, updated, or deleted

Atomic Writes

The caching system uses atomic file writes (write to temp file, then rename) to prevent data corruption from concurrent access. This ensures cache files are never in a half-written state.

Customization

Custom Theme Development

The recommended approach for customization is creating a custom theme. This keeps your changes separate from the core files and makes updates easier.

  1. Copy the Starter Theme

    Duplicate content/themes/starter/ to content/themes/your-theme/

  2. Modify Templates

    Edit the PHP templates in templates/ to change the HTML structure. All templates use plain PHP — no special template syntax required.

  3. Customize Styles

    Edit assets/css/theme.css to change colors, fonts, spacing, and layout. The Starter theme uses clean, semantic CSS that is easy to customize.

  4. Add JavaScript

    Edit assets/js/theme.js for custom interactivity. The file includes handlers for search autocomplete, newsletter subscription, and comment submission.

  5. Modify the Controller

    Edit controllers/FrontendController.php to change data fetching logic, add new template variables, or modify query behavior.

  6. Activate Your Theme

    Set 'theme' => 'your-theme' in config/app.php

Adding Custom Page Templates

Create a new PHP file in your theme's templates/ directory (e.g., landing.php). When editing a page in the admin panel, select your custom template from the Template dropdown.

<!-- templates/landing.php -->
<div class="landing-page">
    <div class="hero-banner">
        <h1><?= e($page['title']) ?></h1>
    </div>
    <div class="page-content">
        <?= $page['content'] ?>
    </div>
</div>

Modifying the Admin Panel

Admin views are located in admin/views/ and use Tailwind CSS for styling. You can modify admin templates directly, but keep in mind that changes may be overwritten during updates.

Tailwind CSS Build System

Prime Core uses the Tailwind CSS standalone CLI (v3.4.17) — no Node.js or npm required. Two separate configurations exist:

ConfigScansOutput
tailwind.admin.config.jsadmin/views/**/*.phpadmin/assets/css/tailwind.css
tailwind.frontend.config.jscontent/themes/starter/templates/**/*.php, partials/**/*.phpcontent/themes/starter/assets/css/tailwind.css

After modifying any PHP templates, rebuild the CSS:

# Rebuild admin CSS
./tailwindcss -i admin/assets/css/tailwind-input.css -o admin/assets/css/tailwind.css -c tailwind.admin.config.js -m

# Rebuild frontend CSS
./tailwindcss -i content/themes/starter/assets/css/tailwind-input.css -o content/themes/starter/assets/css/tailwind.css -c tailwind.frontend.config.js -m

Both configs share the same color theme: Ink (#0f172a), Rose Gold (#c2727d), Cream (#fafaf9), and Warm Gray (#f1f5f9).

Important If you modify core files (core/, admin/, or index.php), document your changes carefully. These files may be overwritten during future updates. For frontend customizations, always use the theme system.

Troubleshooting

Common Issues

Blank Page / 500 Internal Server Error

  • Enable debug mode: Set 'debug' => true in config/app.php
  • Check PHP error logs (usually in /var/log/apache2/error.log or /var/log/nginx/error.log)
  • Verify PHP version is 8.0 or higher: php -v
  • Ensure all required PHP extensions are installed: php -m
  • Check file permissions on config/, cache/, storage/, uploads/

404 Not Found on All Pages

  • Verify mod_rewrite is enabled: a2enmod rewrite (Apache)
  • Ensure .htaccess file exists in the root directory (it may be hidden)
  • Check Apache configuration allows .htaccess overrides (AllowOverride All)
  • For Nginx, ensure the rewrite rules are in your server block configuration

Backup Download / Delete Returns 404

  • This was a known issue where the router's default {param} regex ([a-zA-Z0-9_-]+) did not allow dots in filenames (e.g., backup_2026-02-14.sql)
  • Resolved by using constrained route parameters: {file:[a-zA-Z0-9._-]+}
  • If you experience similar 404 issues with routes containing dots, use the {param:regex} syntax in your route definitions

Admin Panel Not Loading / CSS Broken

  • Ensure the url in config/app.php matches your actual domain (no trailing slash)
  • Verify that admin/assets/css/tailwind.css exists (rebuild with the Tailwind CLI if missing)
  • Verify the CSP header is not blocking required resources (check browser console)

File Uploads Failing

  • Check PHP upload_max_filesize in php.ini
  • Check PHP post_max_size in php.ini (must be larger than upload_max_filesize)
  • Verify uploads/ directory is writable
  • Ensure the file extension is in the allowed list in config/app.php

Database Connection Error

  • Verify database credentials in config/database.php
  • Ensure MySQL/MariaDB service is running
  • Check that the database user has proper privileges on the database
  • Try connecting manually: mysql -u username -p -h 127.0.0.1 database_name

CSRF Token Errors

  • This usually indicates session issues — check that storage/ is writable
  • Ensure session cookies are being set (check browser cookies)
  • If you see "Invalid CSRF token" on every form, try clearing your browser cookies and logging in again

TinyMCE Editor Not Loading

  • Check browser console for CSP or network errors
  • Verify internet access (TinyMCE loads from CDN: cdn.tiny.cloud) — it is lazy-loaded only on pages that need it
  • Ensure JavaScript is enabled in the browser

Maintenance Mode — Locked Out

  • Edit config/app.php directly and set 'maintenance_mode' => false
  • Alternatively, access the admin panel directly — logged-in admins can bypass maintenance mode

Performance Tips

  • Enable caching in production ('cache_enabled' => true)
  • Use PHP OPcache for bytecode caching
  • Enable gzip/brotli compression on your web server
  • Set appropriate cache_ttl based on how often content changes
  • Tailwind CSS is pre-built and minified — no runtime compilation overhead
  • TinyMCE and Chart.js are lazy-loaded only on pages that need them, reducing initial page weight
  • Responsive image variants with srcset let browsers load appropriately sized images
  • Use a CDN for static assets if serving high traffic

Debug Mode

Warning Never enable debug mode ('debug' => true) in production. It exposes detailed error messages, stack traces, and potentially sensitive information to visitors. Use it only during development or troubleshooting, then immediately disable it.

Changelog

Version 1.0.0 Initial Release

Release Date: 2026

  • Email System — Built-in SMTP mailer (core/Mailer.php) with TLS/SSL, HTML templates, and send_email() helper
  • Page Revisions — Full revision history for pages (matching the existing post revision system)
  • Revision Diff & Compare — Word-level LCS diff algorithm with side-by-side comparison modal for both posts and pages
  • Post Autosave — Automatic draft saving at regular intervals via AJAX
  • Media Library Enhancements — Grid/list toggle, type filtering (images/docs), bulk delete, inline alt text editing with debounce, thumbnail optimization
  • Responsive Images — Automatic generation of 4 image variants (original, thumb 150×150, medium 600×400, large 1200×800) with srcset attributes
  • Production Tailwind CSS — Standalone CLI (v3.4.17) producing minified builds for both admin and frontend
  • Lazy-Loaded Assets — TinyMCE and Chart.js loaded on demand only on pages that need them
  • Search Improvements — Enhanced search with better relevance and AJAX autocomplete
  • Previous/Next Navigation — Redesigned post navigation with thumbnail previews
  • Dashboard Improvements — Enhanced admin dashboard with better statistics and quick actions
  • User Profile Page — Dedicated profile page accessible to all roles at /profile with avatar upload, password change, bio editing, and 2FA management
  • Notification System — Real-time admin notification bell with 60-second AJAX polling. Tracks pending comments, unread contact messages, new subscribers, and scheduled posts
  • Layout Switcher — Post listing pages include a 3-mode layout switcher: Grid, List, and Magazine views. Preference persisted in localStorage
  • 3-Level Navigation — Frontend header menus support three levels of nesting on both desktop and mobile
  • Social Sharing — Single post pages include share buttons for Twitter/X, Facebook, LinkedIn, and Copy Link
  • Reading Progress Bar — Visual progress indicator at the top of single post pages
  • Table of Contents — Auto-generated from article headings on single post pages
  • Author Bio Box — Author information card displayed below post content
  • Related Posts — Up to 4 related posts from the same category shown below article content
  • Config Recovery — 3-tier config recovery system prevents lockouts during deployment
  • Demo Mode — Built-in read-only demo role for live preview environments with router-level middleware
  • Hero Slider — Homepage auto-rotating featured post carousel with navigation and responsive layout
  • Premium Design System — Unified Outfit + Plus Jakarta Sans + Fira Code typography with Ink/Rose-Gold color palette
  • Complete CMS core — Posts, pages, categories, tags, comments, media, menus, users, newsletter, contact, SEO, backup, cache, maintenance mode
  • Security — CSRF protection, prepared statements, rate limiting, IP blocking, CSP headers, TOTP two-factor authentication
  • Web-based installer — Database setup and demo data seeding with install lock

Credits

Third-Party Libraries (CDN)

LibraryVersionPurposeLicense
Tailwind CSS3.4.17Admin + frontend styling (production build via standalone CLI)MIT
TinyMCE6.8.3Rich text editor (CDN, lazy-loaded)MIT
Chart.js4.4.1Dashboard analytics charts (CDN, lazy-loaded)MIT

Built With

  • PHP 8.0+ — Server-side language
  • MySQL / MariaDB — Database engine
  • PDO — Database abstraction
  • Vanilla JavaScript — Frontend interactivity (no jQuery dependency)

Support

If you have questions, encounter bugs, or need assistance:

  • Check this documentation first
  • Review the Troubleshooting section above
  • Contact us through the Prime Core website
Thank You Thank you for choosing Prime Core CMS! We hope you enjoy building with it. Visit primecorecms.com for updates, support, and more.