⌘K

File Structure

Front-end root /

FileRole
index.phpMain front-end router
install.phpFirst-run installer
config.jsonSite settings flat-file database
plugins.jsonPlugin activation registry — { "slug": { "active": bool } }, created on first activation
version.jsonCurrent CMS version

ℹ️

config.json was renamed from settings.json as part of the v1.3.3 core restructure. Existing installs are migrated automatically on first load — no manual action needed.

Core libraries /core/

As of v1.3.3, all front-end PHP libraries live under /core/ instead of the CMS root. This keeps the root directory limited to entry points and config, and makes the core/theme/plugin boundary explicit at a glance.

FileRole
functions.phpBootstrap loader — includes every file below, in order
core-functions.phpRouting helpers, breadcrumbs, galleries, search helpers, resolve_admin_dir()
data-functions.phpRouting, SEO, category/tag page rendering, parseRequestUri()
data-layer.phpRead-only split-file layer (sl_* functions, internal $GLOBALS cache)
admin-data-layer.phpWrite split-file layer (sl_admin_* functions, atomic operations)
plugin-api.phpPlugin registry, activation state, admin-menu registration, and the pl_* hook system (see Plugins below)
lang-cache.phpi18n cache and locale management (__t(), _e(), __n(), lang_js_bridge())
search.phpSearch endpoint (JSON, mb_* safe)
contact-process.phpContact form handler (CSRF, rate-limit, hCaptcha, header injection guard)
feed.phpRSS feed

Rendering /core/render/

Rendering-specific files are grouped one level deeper:

FileRole
tf-page.phpPage renderers: SEO tags, header scripts, logo/favicon, featured image, date, category, tags, footer, social icons, search UI
tf-cards.phpCard renderers: article/project cards, homepage sections, article summary, related items, custom fields
tf-shortcodes.phprender_content_html() pipeline, all shortcode render functions, contact form, excerpt helpers
tf-navigation.phpNavigation and menu rendering: render_menu(), renderHierarchicalMenu(), renderDefaultMenu()
tf-markdown.phpMarkdown parser: _md_to_html(), _md_inline(), container directives (:::type)
theme-api.phpHooks, filters, theme options system

Data directory /data/

data/
├── articles/
│   ├── _index.json        — Lightweight index (metadata only)
│   ├── my-article.json    — Full article data (content, SEO, galleries, all fields)
│   └── other-article.json
├── pages/
│   ├── _index.json
│   └── my-page.json
├── projects/
│   ├── _index.json
│   └── my-project.json
├── categories.json        — Category store (slug → {name, parent, description})
└── tags.json              — Tag store (slug → {name, description})

Compiled cache /cache/

A dedicated /cache/ directory at the CMS root (separate from /admin/cache/, see below) holds runtime-generated files. None of these are meant to be edited directly, and all are safe to delete — they rebuild automatically on the next request:

PathContains
/cache/lang/front/{locale}.phpCompiled, OPcache-friendly front-end locale strings
/cache/lang/admin/{locale}.phpCompiled admin locale strings
/cache/sl_idx_article.cache, sl_idx_page.cache, sl_idx_project.cacheCompiled index caches for the split-file data layer
/cache/sl_categories.cache, sl_tags.cacheCompiled category/tag store caches
/cache/media-stats.jsonCached media library statistics

Other key directories

PathPurpose
/assets/css/System CSS (gallery layouts, lightbox, search, shortcodes)
/assets/js/main.jsFront-end JS (search engine, UI)
/bckps/Database backups and template editor backups — direct access blocked by .htaccess
/bckps/templates/Template editor backups, organised by theme name
/files/Media uploads
/lang/front/Front-end locale files (en.json, fr.json, es.json…)
/lang/admin/Admin panel locale files
/private/contact.secret32-byte HMAC key for contact form CSRF tokens
/private/contact_rate.jsonContact form rate-limiting data per IP (max 5/hour, SHA-256 hashed IPs). Created on the first contact form submission — absent on installs that haven't received one yet
/private/auth_rate.jsonAdmin login rate-limiting data — a separate store from the contact form, tracking failed login attempts per IP
/theme/Themes directory
/plugins/Installed plugins — see Plugins below
/admin/drafts/Autosave draft files (draft_*.json)

Admin panel /admin/

FileRole
index.phpAdmin router (dispatches via ?action=) — also routes ?action=plugin_page to a plugin's own admin page (see Plugins)
admin-credentials.phpHashed admin password, written at install time
dashboard.phpDashboard page
content.phpContent management hub
file-manager.phpMedia manager (drag & drop)
template-editor.phpTemplate editor — browse and edit all active theme files (PHP, CSS, JS, JSON) with per-file backups
batch-optimize.phpBatch image optimisation and WebP conversion
seo-overview.phpSEO overview for all published content
sitemap-generator.phpSitemap generator
settings.phpSettings handler
theme-preview.phpLive theme preview (HMAC token-based)
extension-upload.phpZIP theme and ZIP plugin import endpoint (read plugin.json or theme.json)
autosave.phpDraft autosave AJAX endpoint
auth.phpAuthentication (login/logout, IP-based rate limiting)
alt-text-assistant.phpGallery image alt text and caption management
backup-dl.phpSecure backup download proxy
list-content.phpAJAX endpoint for server-side pagination, search, and sorting
preview.phpPost preview (published and unpublished, HTML and Markdown)
forgot-password.phpPassword reset request with email link
reset-password.phpPassword reset form
change-password.phpIn-admin password change
translations-api.phpAJAX endpoint for the translation editor (read/write locale files)
file-upload.phpFile upload endpoint for the media manager
image-optimization.phpSingle image optimisation and WebP conversion endpoint
get-files.phpFile listing endpoint for the media manager
save-profile.phpAccount profile save endpoint
progress-helpers.phpServer-sent events helper for batch operation progress

Admin includes /admin/includes/

Shared admin scaffolding, separate from the single-purpose files above and from /admin/templates/:

FileRole
admin-functions.phpShared admin helper functions
backup-functions.phpBackup creation/restore logic
extension-update-functions.phpTheme/plugin update-check logic
session-config.phpShared session cookie configuration (also required by the front-end index.php for the admin bar)
header.php, footer.php, layout.php, sidebar.phpAdmin panel chrome

Admin cache /admin/cache/

Distinct from the root-level /cache/ — holds admin-only runtime data:

FileContains
extensions-check.jsonCached plugin/theme update-check results
update-check.jsonCached core version update-check result
news-cache.jsonCached admin dashboard news feed

Admin templates /admin/templates/

TemplateRenders
content-add.phpAdd content form
content-edit.phpEdit content form
content-list.phpContent list table
menu-builder.phpVisual menu builder
settings-view.phpSettings page
theme-manager.phpTheme manager with live preview
categories-manage.phpCategory management
tags-manage.phpTag management
drafts.phpDrafts list
backup.phpBackup management
account.phpAccount settings (name, password)
translations.phpTranslation editor
update.phpAuto-update interface
plugins-manager.phpExtensions page — install, activate/deactivate, delete plugins
contact.phpContact form submissions viewer

Plugins

A plugin is a self-contained folder under /plugins/ — its own PHP files, its own JSON data storage, and optionally its own admin page. Plugins never modify core files; installing or deleting one is a matter of adding or removing its folder.

plugins/
└── my-plugin/
    ├── plugin.json          — Manifest: name, slug, version, entry file.
    │                          Must contain "synaptik_plugin": true or the
    │                          folder is ignored by the plugin scanner.
    ├── my-plugin-init.php    — Entry file (declared in plugin.json).
    │                          Registers the admin_menu hook and any
    │                          front-end behaviour.
    ├── data/                 — Plugin's own data store, .htaccess-protected,
    │                          created automatically on first write
    ├── private/              — CSRF secrets, rate-limit stores, etc.,
    │                          .htaccess-protected
    ├── admin/
    │   ├── admin-page.php    — Exposes "{slug}_render_admin_page($view)",
    │   │                       the contract read by admin/index.php's
    │   │                       plugin_page router
    │   └── actions.php       — POST-only endpoint for state-changing
    │                           admin operations (CSRF-protected)
    ├── assets/               — Plugin-specific CSS/JS
    └── lang/                 — Translations, front + admin

How plugins are tracked

plugins.json at the CMS root is the activation registry: { "slug": { "active": true|false } }. A plugin present in /plugins/ but absent from this file (or marked inactive) is installed but dormant — none of its code runs. Activating a plugin from Admin → Extensions is what actually loads it on every request, via pl_load_active_plugins() (called once from core/functions.php).

How plugins integrate with the CMS

  • Admin sidebar — a plugin registers its own entry via the admin_menu hook (pl_on_admin_menu() in plugin-api.php). Its admin page then renders inside the standard admin layout (same sidebar, top bar, footer) through admin/index.php?action=plugin_page&slug={slug}.
  • Front-end output — the core's shortcode pipeline (render_content_html()) has no filter hook for third-party shortcodes, so a plugin adding one (e.g. [newsletter_signup]) buffers the full page output and resolves its own shortcode string directly, only on genuine front-end HTML responses.
  • Data storage — each plugin owns its own flat JSON files under its data/ folder, entirely separate from /data/ (CMS content). Deactivating a plugin preserves this data; deleting the plugin folder removes it permanently.
  • Security — plugins do not depend on the core's CSRF/session internals beyond reusing $_SESSION['admin'] for auth. CSRF tokens, rate-limit stores, and any HMAC secrets are generated and stored inside the plugin's own private/ folder.

Themes

To learn how themes are structured, please visit the Theme Structure page.

Path changes in v1.2

The following directories were moved in version 1.2. If you are upgrading from 1.1 or earlier and have hardcoded any of these paths in a theme or external script, update them accordingly.

Before 1.2From 1.2
/css//assets/css/
/js//assets/js/
/lang/en.json, /lang/fr.json/lang/front/en.json, /lang/front/fr.json

Path changes in v1.3.3

The following changes ship in v1.3.3's core restructure. Existing installs are migrated automatically (config key rename, file cleanup) on the first request after upgrading — no manual action needed.

Before 1.3.3From 1.3.3
settings.json (root)config.json (root)
functions.php, core-functions.php, data-functions.php, data-layer.php, admin-data-layer.php, plugin-api.php, lang-cache.php, search.php, contact-process.php, feed.php (root)/core/
tf-page.php, tf-cards.php, tf-shortcodes.php, tf-navigation.php, tf-markdown.php, theme-api.php (root)/core/render/

/private/contact_rate.json is unchanged — still written by contact-process.php on the first contact form submission. It sits alongside the new /private/auth_rate.json, which is a separate store introduced for admin login rate-limiting; the two do not overlap.

Theme code using the standard API (render_header_scripts(), __t(), _e(), etc.) is unaffected by any of the above — paths are resolved internally and no theme-facing function signature changed.