File Structure
Front-end root /
| File | Role |
|---|---|
index.php | Main front-end router |
functions.php | Front-end utilities — includes core-functions, data-functions, theme-api, data-layer, plugin-api |
core-functions.php | Routing, breadcrumbs, galleries, search helpers |
data-functions.php | Routing, SEO, category/tag page rendering, parseRequestUri() |
data-layer.php | Read-only split-file layer (sl_* functions, internal $GLOBALS cache) |
admin-data-layer.php | Write split-file layer (sl_admin_* functions, atomic operations) |
plugin-api.php | Plugin registry, activation state, admin-menu registration, and the pl_* hook system (see Plugins below) |
tf-page.php | Page renderers: SEO tags, header scripts, logo/favicon, featured image, date, category, tags, footer, social icons, search UI |
tf-cards.php | Card renderers: article/project cards, homepage sections, article summary, related items, custom fields |
tf-shortcodes.php | render_content_html() pipeline, all shortcode render functions, contact form, excerpt helpers |
tf-navigation.php | Navigation and menu rendering: render_menu(), renderHierarchicalMenu(), renderDefaultMenu() |
tf-markdown.php | Markdown parser: _md_to_html(), _md_inline(), container directives (:::type) |
theme-api.php | Hooks, filters, theme options system |
install.php | First-run installer |
lang-cache.php | i18n cache and locale management (__t(), _e(), lang_js_bridge()) |
lang-switch.php | Front-end language switching handler |
search.php | Search endpoint (JSON, mb_* safe) |
contact-process.php | Contact form handler (CSRF, rate-limit, hCaptcha, header injection guard) |
feed.php | RSS feed |
settings.json | Site settings flat-file database |
plugins.json | Plugin activation registry — { "slug": { "active": bool } }, created on first activation |
version.json | Current 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
| Path | Purpose |
|---|---|
/assets/css/ | System CSS (gallery layouts, lightbox, search, shortcodes) |
/assets/js/main.js | Front-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.secret | 32-byte HMAC key for contact form CSRF tokens |
/private/contact_rate.json | Rate-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/
| File | Role |
|---|---|
index.php | Admin router (dispatches via ?action=) — also routes ?action=plugin_page to a plugin's own admin page (see Plugins) |
dashboard.php | Dashboard page |
content.php | Content management hub |
file-manager.php | Media manager (drag & drop) |
template-editor.php | Template editor — browse and edit all active theme files (PHP, CSS, JS, JSON) with per-file backups |
batch-optimize.php | Batch image optimisation and WebP conversion |
seo-overview.php | SEO overview for all published content |
sitemap-generator.php | Sitemap generator |
settings.php | Settings handler |
theme-preview.php | Live theme preview (HMAC token-based) |
theme-upload.php | ZIP theme import endpoint |
plugin-upload.php | ZIP plugin import endpoint — mirrors theme-upload.php's validation pipeline, reads plugin.json instead of theme.json |
autosave.php | Draft autosave AJAX endpoint |
auth.php | Authentication (login/logout) |
alt-text-assistant.php | Gallery image alt text and caption management |
backup-dl.php | Secure backup download proxy |
list-content.php | AJAX endpoint for server-side pagination, search, and sorting |
preview.php | Post preview (published and unpublished, HTML and Markdown) |
forgot-password.php | Password reset request with email link |
reset-password.php | Password reset form |
change-password.php | In-admin password change |
translations-api.php | AJAX endpoint for the translation editor (read/write locale files) |
file-upload.php | File upload endpoint for the media manager |
image-optimization.php | Single image optimisation and WebP conversion endpoint |
get-files.php | File listing endpoint for the media manager |
save-profile.php | Account profile save endpoint |
progress-helpers.php | Server-sent events helper for batch operation progress |
Admin templates /admin/templates/
| Template | Renders |
|---|---|
content-add.php | Add content form |
content-edit.php | Edit content form |
content-list.php | Content list table |
menu-builder.php | Visual menu builder |
settings-view.php | Settings page |
theme-manager.php | Theme manager with live preview |
categories-manage.php | Category management |
tags-manage.php | Tag management |
drafts.php | Drafts list |
backup.php | Backup management |
account.php | Account settings (name, password) |
translations.php | Translation editor |
update.php | Auto-update interface |
plugins-manager.php | Extensions 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_menuhook (pl_on_admin_menu()inplugin-api.php). Its admin page then renders inside the standard admin layout (same sidebar, top bar, footer) throughadmin/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 ownprivate/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.2 | From 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.
