⌘K

File Structure

Front-end root /

FileRole
index.phpMain front-end router
functions.phpFront-end utilities — includes core-functions, data-functions, theme-api, data-layer, plugin-api
core-functions.phpRouting, breadcrumbs, galleries, search helpers
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)
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
install.phpFirst-run installer
lang-cache.phpi18n cache and locale management (__t(), _e(), lang_js_bridge())
lang-switch.phpFront-end language switching handler
search.phpSearch endpoint (JSON, mb_* safe)
contact-process.phpContact form handler (CSRF, rate-limit, hCaptcha, header injection guard)
feed.phpRSS feed
settings.jsonSite settings flat-file database
plugins.jsonPlugin activation registry — { "slug": { "active": bool } }, created on first activation
version.jsonCurrent CMS version

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})

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.jsonRate-limiting data per IP (max 5/hour, SHA-256 hashed IPs)
/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)
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)
theme-upload.phpZIP theme import endpoint
plugin-upload.phpZIP plugin import endpoint — mirrors theme-upload.php's validation pipeline, reads plugin.json instead of theme.json
autosave.phpDraft autosave AJAX endpoint
auth.phpAuthentication (login/logout)
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 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

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 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.

Distribution

export-release.sh excludes /plugins/ and plugins.json from the public core release ZIP — plugins ship and update independently of core version releases, each as its own downloadable .zip from the Plugins 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

Theme code using the standard API (render_header_scripts(), __t(), _e()) is unaffected — paths are resolved internally.