Comprehensive Documentation - Version 2.0
composer install to install dependencies..env file to configure environment and database settings.
database.default.hostname = localhost
database.default.database = igniter_cms_db
database.default.username = root
database.default.password = db_password
database.default.DBDriver = MySQLi
database.default.DBPrefix =
database.default.port = 3306
.env file. app.baseURL = 'http://localhost/igniter-cms/'php spark generate:key. This command will generate/update the application key (APP_KEY) in .env file.php spark recreate:tables.https://localhost/igniter-cms/.
Note: To reset database you can use these commands php spark recreate:tables
htdocs, www, or public_html).
http://localhost/igniter-cms-installer/).
.env file, set up the database, install dependencies
/install folder should be deleted after installation. Note it would be automatically removed in "production" environment for security.
Ensure writable and public/uploads directories are writable by the web server.
The dashboard is the landing page of the backend and includes the following features:
The CMS module allows you to manage the website's content, including blogs, pages, and navigations.
Create, update, and remove blogs. Features include:
Manage blog categories. Features include:
Create, update, and remove pages. Features include:
Organize and manage structured data entries for various purposes. Features include:
The Form Manager provides a robust toolset for creating, managing, and tracking various types of user-submitted forms directly from the admin panel.
Use to manage contact form submissions
Use to manage booking form submissions
Use to manage subscription form submissions
Upload, manage, and organize files, including images and documents.
Manage application themes here. Add, Active or remove themes.
Edit theme files here. Uses code editor to edit file contents.
The CMS includes a built-in versioning system for your theme files, allowing you to experiment with code changes safely and revert to previous versions if something goes wrong.
Revisions are created automatically whenever you save a file in the Theme Editor:
/account/appearance/theme-editor)._layout.php or site.css).To view your history or restore an old version of your theme, navigate to Appearance > Revisions (/account/appearance/theme-editor/revisions).
This is the module for managing your account details and changing passwords
Update your account information (name, bio, etc.).
Change your account password.
The Admin module provides features for managing users, system configurations, and website functionality.
Create, edit, and manage user accounts and their permissions.
| Module | Admin | Manager |
|---|---|---|
| Dashboard | ||
CMS
|
||
| File Manager | ||
Settings
|
||
Admin
|
||
| Manage Themes | ||
| Plugins | ||
| Documentation | ||
| AI Assistance |
Adjust application settings and configurations to suit your needs.
Edit header and footer JavaScript as well as custom CSS.
Generate and manage API keys for accessing CMS data via the API.
View a history of user actions and system events for tracking changes.
Track system events and actions with detailed logs. Features include:
Analyze website traffic statistics and view detailed analytics.
Manage and restrict access from unwanted IP addresses. Features include:
Allow specific IP addresses for privileged access. Features include:
Create and manage backups for the database and website files.
Edit theme files directly within the admin panel (use this feature with caution).
Manage installed plugins.
Manage plugin's configuration data.
Enhance productivity and streamline workflows with AI-powered features tailored for Igniter CMS.
Get instant AI-powered assistance for any questions related to Igniter CMS. Features include:
Generate content dynamically to improve site efficiency and SEO ranking. Features include:
Leverage AI to gain insights into site performance and operational data. Features include:
This section outlines various methods to deploy your Igniter CMS application to a live server. Regardless of the deployment method chosen, you will always need to create and restore your database on the server.
cPanel).Deploying via FTP involves manually transferring files and setting up your database.
cPanel).phpMyAdmin (or your preferred database management tool).phpMyAdmin in your hosting control panel and import the exported database file into the newly created database.FileZilla) with your FTP credentials.public_html or a subdirectory)..env file in your uploaded project root on the server and update the database connection details (database name, username, password).app/Config/Database.php on the server and ensure the database connection settings are correct.app/Config/App.php on the server and set the baseURL to your domain (e.g., https://your-domain.com/).This method leverages a Continuous Integration/Continuous Deployment pipeline using GitHub Actions for automated deployment.
.github/workflows/ directory in your local Igniter CMS project.main.yaml.txt to main.yaml.main.yaml file.# symbol from the beginning of relevant lines.server key with your FTP server address (e.g., server: ftp.your-domain.com).server-dir key with the path to your website's directory on the server (e.g., server-dir: /your-site-path).FTPUSERNAME and FTPPASSWORD, using your FTP account details..env file with the production database connection details.app/Config/Database.php with the production database connection settings.baseURL in your local app/Config/App.php to your domain.vendor folder (e.g., vendor.zip).vendor.zip to your server's deployment directory (e.g., using FTP or File Manager).vendor.zip file in the server's deployment directory. The vendor folder is typically not pushed to Git due to its size and dynamic nature..env File:
.env file directly on your server in the root of your deployed application directory. This file will not be pushed by Git. Configure it with your production environment variables, especially database credentials.main.yaml and updated configurations).cPanel).phpMyAdmin (or your preferred database management tool).phpMyAdmin in your hosting control panel and import the exported database file into the newly created database.This method utilizes your hosting provider's file manager to upload your entire project as a compressed archive.
.env file with the production database connection details.app/Config/Database.php with the production database connection settings.baseURL in your local app/Config/App.php to your domain.cPanel).phpMyAdmin (or your preferred database management tool).phpMyAdmin in your hosting control panel and import the exported database file into the newly created database.cPanel).public_html or a specific subdirectory).0755 for directories and 0644 for filesYou can set the CMS as a headless CMS or use the Views to render data. To set the format for frontend, got the Admin > Configurations and search FrontEndFormat. Set it to either MVC or API
The app includes fetch-only APIs for retrieving CMS data.
/api/{api-key}/get-model-data?model=navigations&take=10&skip=0: Generic - Fetch navigations (10 items, skip 0)./api/{api-key}/get-model-data?model=categories&where_clause={"status":1}: Generic - Fetch filtered categories (e.g., status = 1)./api/{api-key}/get-model-data?model=blogs&where_clause={"blog_id":"{blog-id}"}: Generic - Fetch filtered blogs (e.g., blog_id = {blog-id})./api/{api-key}/get-model-data?model=blogs&where_clause={"blog_id":"{blog-id}","status":1}: Generic - Fetch multiple filtered blogs (e.g., blog_id = {blog-id} and status = 1).| Model Name | Corresponding Model |
|---|---|
| blockedIPsModel | App\Models\BlockedIPsModel |
| blogs | App\Models\BlogsModel |
| categories | App\Models\CategoriesModel |
| codes | App\Models\CodesModel |
| contentBlocks | App\Models\ContentBlocksModel |
| dataGroupsModel | App\Models\DataGroupsModel |
| navigations | App\Models\NavigationsModel |
| pages | App\Models\PagesModel |
| themes | App\Models\ThemesModel |
| whitelistedIPsModel | App\Models\WhitelistedIPsModel |
| Model Name | Model Fields |
|---|---|
| BlogsModel |
blog_id(VARCHAR), title(VARCHAR), slug(VARCHAR), featured_image(VARCHAR), excerpt(VARCHAR),
content(TEXT), category(VARCHAR), tags(VARCHAR), is_featured(BOOLEAN), status(INT), meta_title(VARCHAR),
meta_description(TEXT), meta_keywords(TEXT), created_by(DATETIME), updated_by(DATETIME)
|
| BlockedIPsModel |
blocked_ip_id(VARCHAR), ip_address(VARCHAR), country(VARCHAR), block_start_time(DATETIME),
block_end_time(DATETIME), reason(VARCHAR), notes(VARCHAR), page_visited_url(VARCHAR)
|
| CategoriesModel |
category_id(VARCHAR), title(VARCHAR), description(VARCHAR), group(VARCHAR), parent(VARCHAR),
link(VARCHAR), new_tab(BOOLEAN), order(INT), status(INT), created_by(DATETIME), updated_by(DATETIME)
|
| CodesModel |
code_id(VARCHAR), code_for(VARCHAR), code(VARCHAR), deletable(VARCHAR),
created_by(DATETIME), updated_by(DATETIME)
|
| ContentBlocksModel |
content_id(VARCHAR), identifier(VARCHAR), author(VARCHAR), title(VARCHAR), description(VARCHAR),
content(TEXT), icon(VARCHAR), group(VARCHAR), image(VARCHAR), link(VARCHAR), new_tab(BOOLEAN),
order(INT), custom_field(VARCHAR), created_by(DATETIME), updated_by(DATETIME)
|
| DataGroupsModel |
data_group_id(VARCHAR), data_group_for(VARCHAR), data_group_list(VARCHAR),
deletable(VARCHAR), created_by(VARCHAR), updated_by(VARCHAR)
|
| ThemesModel |
theme_id(VARCHAR), name(VARCHAR), path(VARCHAR), primary_color(VARCHAR), secondary_color(VARCHAR), other_color(VARCHAR),
image(VARCHAR), theme_url(VARCHAR), footer_copyright(VARCHAR), category(VARCHAR), sub_category(VARCHAR), selected(BOOLEAN),
deletable(BOOLEAN), home_page(VARCHAR), created_by(DATETIME), updated_by(DATETIME)
|
| WhitelistedIPsModel |
whitelisted_ip_id(VARCHAR), ip_address(VARCHAR), reason(VARCHAR)
|
Customize the messages in the app in app/Config/CustomConfig.php.
class CustomConfig extends BaseConfig
{
#--------------------------------------------------------------------
# MESSAGES
#--------------------------------------------------------------------
public $wrongCredentialsMsg = 'Sign In Failed. The provided username/email or password is incorrect.';
public $loginSuccessMsg = 'Login successful.';
public $logoutSuccessMsg = 'You have been successfully logged out.';
public $pendingActivationMsg = 'Your account has not been activated yet or is no longer active. Please contact the administrator.';
public $tooManyFailedLogins = 'Too many failed login attempts. Your IP has been blocked for 1 hour.';
public $invalidAccessMsg = 'You do not have access to this area.';
public $createSuccessMsg = 'Record created successfully.';
public $editSuccessMsg = 'Record updated successfully.';
public $deleteSuccessMsg = 'Record removed successfully.';
public $missingRequiredInputsMsg = 'There are validation errors. Possible missing required inputs.';
public $sentContactMsg = 'Message sent successfully.';
public $failedContactMsg = 'Form submission failed.';
public $notFoundMsg = 'Record not found.';
public $alreadyExistMsg = '[Record] already exists in table.';
public $errorMsg = 'Oops! Something went wrong. Please try again later.';
public $resetLinkMsg = 'A password reset link has been sent to your email address. Please check your inbox and follow the instructions to reset your password. If you do not see the email in your inbox, please check your spam or junk folder.';
public $invalidResetLinkMsg = 'Invalid or expired password reset link.';
public $passwordResetRequiredMsg = 'For security reasons, you need to change your password before continuing. Your current password was either set by an administrator or is a default password.';
public $passwordResetSuccessfulMsg = 'Your password has been reset successfully. You can now log in with your new password.';
public $passwordResetFailedMsg = 'Unable to reset password. Please try again';
public $nonExistingResetEmailMsg = 'We are sorry, but the email address you entered is not associated with any account. Please check the email address and try again.';
public $exceptionMsg = 'There was an error processing your request. Please try again. If this error persists, please see or send an email to system administrator.';
public $contactMessageSuccessful = 'Your message has been sent successfully.';
public $contactMessageFailed = 'Oops! Something went wrong with your message submission. Please try again later.';
public $bookingSuccessful = 'Your booking has been made successfully.';
public $bookingFailed = 'Oops! Something went wrong with your booking submission. Please try again later.';
public $subscriptionSuccessful = 'You have successfully subscribed!';
public $subscriptionFailed = 'Sorry, something went wrong with your subscription. Please try again.';
#--------------------------------------------------------------------
# THEME CATEGORIES
#--------------------------------------------------------------------
public $themeCategories = [
'Business' => 'Business & Corporate',
'Ecommerce' => 'Ecommerce',
'Portfolio' => 'Portfolio & Resume',
'News' => 'Blog & News',
'Events' => 'Event & Booking Websites',
'Educational' => 'Educational & Membership Websites',
'Restaurant' => 'Restaurant & Hospitality Websites',
'Health' => 'Health & Wellness Websites',
'Directory' => 'Directory & Listing Websites',
'Entertainment' => 'Entertainment Websites',
'General' => 'General',
];
#--------------------------------------------------------------------
# USER ROLES
#--------------------------------------------------------------------
public $userRoles = [
'Admin' => 'Admin',
'Manager' => 'Manager',
'User' => 'User',
];
}
Customize the data for activity types in logs in app/Constants/ActivityTypes.php.
class ActivityTypes
{
//AUTH LOGS
const USER_REGISTRATION = 'user_registration';
const FAILED_USER_REGISTRATION = 'failed_user_registration';
const USER_LOGIN = 'user_login';
const USER_LOGOUT = 'user_logout';
const FAILED_USER_LOGIN = 'failed_user_login';
//CONTACT LOGS
const CONTACT_CREATION = 'contact_created';
const FAILED_CONTACT_CREATION = 'failed_contact_creation';
const CONTACT_UPDATE = 'contact_updated';
const FAILED_CONTACT_UPDATE = 'failed_contact_update';
const CONTACT_DELETION = 'contact_delete';
//USER LOGS
const USER_CREATION = 'user_created';
const FAILED_USER_CREATION = 'failed_user_creation';
const USER_UPDATE = 'user_updated';
const FAILED_USER_UPDATE = 'failed_user_update';
const USER_DELETION = 'user_delete';
.........................................................
/**
* Gets the description for a given activity type.
*
* @param string $type The activity type.
* @return string The description of the activity type, or "Unknown Activity" if not found.
*/
public static function getDescription($type)
{
$descriptions = [
//Auth
self::USER_REGISTRATION => 'User Registration',
self::FAILED_USER_REGISTRATION => 'User Registration Failed',
self::USER_LOGIN => 'User Login',
self::USER_LOGOUT => 'User Logout',
self::FAILED_USER_LOGIN => 'Failed User Login',
//Contact
self::CONTACT_CREATION => 'Contact Creation',
self::FAILED_CONTACT_CREATION => 'Contact Creation Failed',
self::CONTACT_UPDATE => 'Contact Update',
self::FAILED_CONTACT_UPDATE => 'Contact Update Failed',
self::CONTACT_DELETION => 'Contact Deletion',
//User
self::USER_CREATION => 'User Creation',
self::FAILED_USER_CREATION => 'User Creation Failed',
self::USER_UPDATE => 'User Update',
self::FAILED_USER_UPDATE => 'User Update Failed',
self::USER_DELETION => 'User Deletion',
.........................................................
];
return $descriptions[$type] ?? 'Unknown Activity';
}
}
Customize the files by going to app/Views/front-end/themes/{theme-folder}.
Igniter CMS includes a built-in CRON controller to automate background tasks. These tasks are managed in app/Controllers/CronController.php.
Define a strong secret key in your .env file to prevent unauthorized access:
CRON_SECRET_KEY = "your-strong-secret-key-here-12345"
Choose one of the following methods to trigger your CRON tasks every minute:
If you are on shared hosting or don't want to touch server logs, use a free service like cron-job.org or EasyCron.
https://yourdomain.com/cron/run?key=your-secret-keyAdd this line to your server's crontab file to trigger the script internally:
* * * * * curl -s "https://yourdomain.com/cron/run?key=your-secret-key" > /dev/null 2>&1
When the CRON runs successfully, it returns a JSON response and logs the activity:
{
"status": "success",
"message": "Cron job(s) executed successfully",
"timestamp": "2026-02-17 13:22:23"
}
Igniter CMS integrates with Google Gemini to provide advanced AI features, including blog generation assistance and automated data analysis for site logs and visits.
To begin, you must add your Gemini API credentials to your .env file. You can obtain a key from the Google AI Studio.
GEMINI_REQUEST_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent"
GEMINI_REQUEST_KEY = "your-gemini-key-here"
Once your credentials are set, you must enable the features within the Admin Dashboard:
/account/admin/configurations).Yes to activate the AI "Generate" buttons in the blog and content editors.Yes if you want the system to use AI to analyze site traffic, error logs, and user behavior. Set to No to disable data processing while keeping text generation active.gemini-3-flash-preview model by default for its high speed and low latency, making it ideal for real-time content generation.
Igniter CMS themes are modular and separated into logic (PHP), presentation (Views), and static assets. Themes are located in app/Views/front-end/themes/{theme-folder}/. You can download the starter template below to begin building your own custom design.
A theme directory consists of three primary components:
theme-name/
├── assets/ # Static files (CSS, JS, Images)
│ ├── css/
│ │ └── site.css # Theme-specific styles (excludes root variables)
│ ├── js/
│ │ └── site.js # Theme-specific JavaScript
│ └── images/
│ └── preview.png # Theme preview thumbnail (400x300 recommended)
├── views/ # PHP template files
│ ├── blogs/
│ ├── home/
│ ├── includes/
│ ├── layout/
│ ├── pages/
│ └── search/
└── theme.json # Theme metadata and configuration
The theme.json file defines your theme's metadata, color scheme, and system requirements. This file is required for the theme to appear in the admin panel.
{
"name": "Default",
"path": "default",
"description": "A sleek and modern Igniter theme for businesses.",
"default_color": "#6c757d",
"heading_color": "#212529",
"accent_color": "#0d6efd",
"surface_color": "#f8f9fa",
"contrast_color": "#0d6efd",
"background_color": "#f2f7f7",
"version": "1.0.0",
"author": "IgniterCMS",
"email": "info@ignitercms.com",
"author_url": "https://ignitercms.com/",
"theme_url": "https://previews.ignitercms.com/default/",
"image": "preview.png",
"category": "Business",
"sub_category": "Agency",
"use_static_theme_nav": 1,
"plugins_required": "",
"license": "GPL",
"requires": {
"php": ">=8.0",
"igniter-cms": ">=2.0"
}
}
| Property | Type | Description |
|---|---|---|
name | string | Display name of the theme. |
path | string | Folder name (must match directory name exactly). |
description | string | Short description for the theme selector. |
default_color | hex | Primary text color (CSS variable: --default-color). |
heading_color | hex | Heading text color (CSS variable: --heading-color). |
accent_color | hex | Primary brand color for buttons/links (CSS variable: --accent-color). |
surface_color | hex | Card/surface background color (CSS variable: --surface-color). |
contrast_color | hex | Color for text on accent backgrounds (CSS variable: --contrast-color). |
background_color | hex | Page background color (CSS variable: --background-color). |
use_static_theme_nav | integer (0/1) | If 1, uses hardcoded navigation in _layout.php. If 0, uses dynamic navigation from the CMS database. |
plugins_required | string | Comma-separated list of required plugin slugs (optional). |
requires | object | Minimum PHP and CMS version requirements. |
override_default_style is enabled in theme settings, these colors are injected as CSS variables into :root. Always use var(--accent-color) instead of hardcoded colors in your CSS to respect user customizations.
| Folder/File | Required | Description |
|---|---|---|
layout/_layout.php |
Yes | The master wrapper containing <head>, navigation, footer, and asset loading. All other views extend this file. |
includes/_functions.php |
No | Theme-specific PHP helper functions (e.g., custom navigation renderers). Auto-included by _layout.php. |
home/index.php |
Yes | The main landing page template. Must define a content section. |
blogs/index.php |
Yes | Blog listing page. Receives $blogs array, $pager object, and $total_blogs. |
blogs/view-blog.php |
Yes | Single blog post template. Receives $blog_data, $categories, and $blogs (recent posts). |
pages/view-page.php |
Yes | Static CMS page template. Receives $page_data array with title and content. |
search/index.php |
Yes | Standard search results. Receives $searchQuery, $blogsSearchResults, $pagesSearchResults. |
search/filter.php |
Yes | Filtered search results (by category, tag, or author). Receives additional $type variable. |
_layout.php)The layout file is the foundation of your theme. It must include specific elements for the CMS to function correctly.
<?php
// Get current theme folder name
$theme = getCurrentTheme();
// Fetch site configuration
$siteName = getConfigData("SiteName");
// Get theme color data and custom codes
$themeData = [
'customCSS' => getTableData('codes', ['code_for' => 'CSS'], 'code'),
'customJSTop' => getTableData('codes', ['code_for' => 'HeaderJS'], 'code'),
'customJSFooter' => getTableData('codes', ['code_for' => 'FooterJS'], 'code'),
'defaultColor' => getThemeData($theme, "default_color"),
// ... other colors
];
// Load navigation models
$navigationsModel = new \App\Models\NavigationsModel();
$topNavLists = $navigationsModel->where('group', 'top_nav')
->orderBy('order', 'ASC')
->limit(intval(env('QUERY_LIMIT_DEFAULT', 25)))
->findAll();
?>
<!-- Include theme functions -->
<?= $this->include('front-end/themes/'.$theme.'/includes/_functions.php'); ?>
<!-- Load meta tags and plugin helpers -->
<?=$this->include('front-end/themes/_shared/_load_meta_plugin_helpers.php'); ?>
<!-- Load header plugin helpers -->
<?=$this->include('front-end/themes/_shared/_load_header_plugin_helpers.php'); ?>
<!-- Main content section (required) -->
<main class="main" id="template-html">
<?= $this->renderSection('content') ?>
</main>
<!-- Load footer plugin helpers -->
<?=$this->include('front-end/themes/_shared/_load_footer_plugin_helpers.php'); ?>
The layout must conditionally inject CSS variables based on the override_default_style theme setting:
<?php
$overrideStyle = getThemeData($theme, "override_default_style");
if($overrideStyle === "1"){
// Use theme.json colors
$defaultColor = $themeData['defaultColor'];
// ... fetch other colors
?>
<style>
:root {
--default-color: <?php echo $defaultColor; ?>;
--heading-color: <?php echo $headingColor; ?>;
--accent-color: <?php echo $accentColor; ?>;
--surface-color: <?php echo $surfaceColor; ?>;
--contrast-color: <?php echo $contrastColor; ?>;
--background-color: <?php echo $backgroundColor; ?>;
}
</style>
<?php } else { ?>
<!-- Fallback to Bootstrap defaults -->
<style>
:root {
--default-color: #6c757d;
--heading-color: #212529;
--accent-color: #0d6efd;
--surface-color: #f8f9fa;
--contrast-color: #0d6efd;
--background-color: #ffffff;
}
</style>
<?php } ?>
The layout supports two navigation modes controlled by use_static_theme_nav in theme.json:
Static Navigation (Hardcoded):
<?php if ($useStaticThemeNav === "1"): ?>
<li class="nav-item">
<a class="nav-link" href="<?= base_url('/') ?>">Home</a>
</li>
<!-- Hardcode additional menu items -->
<?php else: ?>
<!-- Dynamic CMS Navigation -->
<?php if ($topNavLists): ?>
<?php foreach ($topNavLists as $navigation): ?>
<?= themef_renderNavigation($navigation, $navigationsModel) ?>
<?php endforeach; ?>
<?php endif; ?>
<?php endif; ?>
Your layout should load these core assets (load order matters):
https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.csshttps://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.csshttps://cdnjs.cloudflare.com/ajax/libs/glightbox/3.3.1/css/glightbox.csshttps://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css<?=loadSiteIcons()?> (helper function)<?= base_url('public/front-end/themes/' . $theme . '/assets/css/site.css') ?>Required JavaScript (load before closing </body>):
<?= base_url('public/front-end/themes/' . $theme . '/assets/js/site.js') ?>All content views must extend the layout and define a content section:
<?php
$theme = getCurrentTheme();
$currentPage = "home"; // Identifies the current page for analytics/menu highlighting
?>
<!-- Extend the theme layout -->
<?= $this->extend('front-end/themes/'.$theme.'/layout/_layout') ?>
<!-- Begin content section -->
<?= $this->section('content') ?>
<!-- Your page content here -->
<section class="page py-5">
<div class="container">
<h1>Page Title</h1>
<!-- Content -->
</div>
</section>
<?= $this->endSection() ?>
Place reusable theme logic in views/includes/_functions.php. The starter template includes a navigation renderer:
<?php
/**
* Renders a navigation item with optional dropdown for child items.
*
* @param array $navigation The navigation item array from database.
* @param object $navigationsModel The NavigationsModel instance.
* @return string HTML output.
*/
function themef_renderNavigation(array $navigation, object $navigationsModel): string
{
$navigationId = $navigation['navigation_id'];
$navTitle = $navigation['title'];
$parent = $navigation['parent'];
$link = getLinkUrl($navigation['link']);
$newTab = $navigation['new_tab'];
$navTarget = $newTab === "1" ? "_blank" : "_self";
// Skip child items (they are rendered by their parent)
if (!empty($parent)) {
return '';
}
// Fetch child navigations
$childNavigations = $navigationsModel->where('parent', $navigationId)
->orderBy('order', 'ASC')
->limit(intval(env('QUERY_LIMIT_DEFAULT', 25)))
->findAll();
if (empty($childNavigations)) {
return '<li class="nav-item">
<a class="nav-link" href="' . $link . '" target="' . $navTarget . '">' . $navTitle . '</a>
</li>';
} else {
// Render dropdown with children
$dropdown = '<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="dropdown-' . $navigationId . '"
data-bs-toggle="dropdown">' . $navTitle . '</a>
<ul class="dropdown-menu dropdown-menu-end">';
foreach ($childNavigations as $childNav) {
$childLink = getLinkUrl($childNav['link']);
$childTarget = $childNav['new_tab'] === "1" ? "_blank" : "_self";
$dropdown .= '<li><a class="dropdown-item" href="' . $childLink . '"
target="' . $childTarget . '">' . $childNav['title'] . '</a></li>';
}
$dropdown .= '</ul></li>';
return $dropdown;
}
}
?>
Your theme views have access to these CMS helper functions:
| Function | Description | Example |
|---|---|---|
getCurrentTheme() |
Returns the active theme folder name. | $theme = getCurrentTheme(); |
getConfigData($key) |
Fetches a configuration value from the database. | $siteName = getConfigData("SiteName"); |
getThemeData($theme, $key) |
Fetches theme-specific configuration. | $color = getThemeData($theme, "accent_color"); |
getTableData($table, $where, $select) |
Generic database query helper. | getTableData('codes', ['code_for' => 'CSS'], 'code') |
getImageUrl($path) |
Returns proper image URL or default placeholder. | getImageUrl(getConfigData("SiteLogoLink")) |
getDefaultImagePath() |
Returns path to default placeholder image. | getImageUrl(null) ?? getDefaultImagePath() |
getLinkUrl($link) |
Processes CMS links (handles internal/external URLs). | getLinkUrl($navigation['link']) |
base_url($path) |
CodeIgniter base URL helper. | base_url('blogs') |
renderAdminBar() |
Renders the admin quick-access toolbar (returns HTML). | $adminBar = renderAdminBar(); |
loadSiteIcons() |
Loads favicon and Apple touch icons. | <?=loadSiteIcons()?> |
renderBlogsGrid($blogs) |
Renders a styled blog grid (theme-agnostic). | <?= renderBlogsGrid($blogs) ?> |
renderBlogContent($blog) |
Renders single blog post content with metadata. | <?= renderBlogContent($blog_data) ?> |
renderBlogSidebar($categories, $blogs, $current) |
Renders blog sidebar with categories and recent posts. | <?= renderBlogSidebar($categories, $blogs, $blog_data) ?> |
renderSearchResults($query, $blogs, $pages) |
Renders standard search results. | <?= renderSearchResults($searchQuery, $blogs, $pages) ?> |
renderFilterSearchResults($query, $blogs, $pages, $type) |
Renders filtered search results. | <?= renderFilterSearchResults($query, $blogs, $pages, $type) ?> |
updateTotalViewCount($table, $idCol, $id) |
Increments view counter for analytics. | updateTotalViewCount("blogs", "blog_id", $blog_data['blog_id']); |
Each view receives specific data from the controller:
blogs/index.php)$blogs - Array of blog posts (paginated)$pager - CodeIgniter pagination object$total_blogs - Total count for pagination logicblogs/view-blog.php)$blog_data - Full blog post array (title, content, featured_image, etc.)$categories - Array of all blog categories$blogs - Array of recent blog posts (for sidebar)pages/view-page.php)$page_data - Page array with title, content, page_id, etc.search/index.php & search/filter.php)$searchQuery - The search term string$blogsSearchResults - Array of matching blog posts$pagesSearchResults - Array of matching CMS pages$type - Filter type: 'category', 'tag', or 'author' (filter.php only)getCurrentTheme() for pathsvar(--accent-color)) for colorsENVIRONMENT !== 'production' comments for customization hintsesc() for user-generated output$currentPage for analytics trackingupdateTotalViewCount() on single item viewscontent section in views_layout.php extensionuse_static_theme_nav settingEach starter template view includes HTML comments (visible only in development mode) explaining how to replace helper functions with custom HTML:
<?php if (ENVIRONMENT !== 'production'): ?>
<!--
CUSTOMIZATION NOTES:
-------------------
To customize the blogs grid display without using the helper function:
1. REPLACE the helper function call with your custom HTML
2. Available data variables:
- $blogs: Array of blog posts with pagination
- $pager: Pagination object
- $total_blogs: Total number of blogs
Example:
<div class="custom-blogs-grid">
<?php foreach($blogs as $blog): ?>
<!-- Your custom blog card HTML -->
<?php endforeach; ?>
</div>
-->
<?php endif; ?>
theme.json. This helps the system manage updates and prevents browser cache issues when you release updates. Use semantic versioning (e.g., 1.0.0).
default theme folder and rename it (e.g., my-theme)theme.json with your theme name, path, and colorsassets/css/site.css for your custom stylesviews/layout/_layout.php with your HTML structure_layout.phppreview.png (400x300px) for the theme selectorPlugins allow you to extend the core functionality of Igniter CMS without modifying system files. Every plugin must be self-contained within its own folder.
A standard plugin requires the following 6 files to function correctly:
plugin.json contains a unique plugin_id to avoid conflicts with existing system plugins.
Copyright (c) 2025 Abdoulie Kassama
This project is licensed under the MIT License - see the LICENSE file for details.
Blog Comments
Use to manage comment form submissions