Technical Documentation
A bespoke full-stack content management system built from scratch — public PHP site, local Python admin backend, dual-mode storage
This system was built for a non-profit operating in a hostile political environment. I was genuinely worried about retaliation, hacking, and exposure — so the architecture started from a question: what's the safest possible publishing setup for an organization that can't afford to be compromised? The answer was local-first. If the admin never runs in the cloud, there's nothing to breach remotely. Every other decision followed from that constraint.
This is a purpose-built content management system designed around a specific operational constraint: a single operator managing a public-facing website entirely from a local machine, with no cloud CMS, no third-party admin interface, and no unnecessary dependencies. Every part of the system — from the storage layer to the publish workflow — was designed to serve that constraint precisely.
The public site is intentionally lightweight: PHP, JSON, and vanilla JavaScript. The local admin panel is a sophisticated browser UI backed by a Python standard-library HTTP server with modular handlers, a dual-mode SQLite/JSON storage adapter, and an extensive suite of utility scripts covering post ingestion, media backup, QR tracking, access log analytics, resource management, and publishing.
The architecture was shaped by a deliberate choice to avoid external dependencies wherever possible. The Python backend uses only the standard library. The public site consumes static JSON files. The admin panel runs locally and publishes to a remote PHP host — a workflow that influenced every design decision in the system.
The codebase includes Python unit tests via pytest, frontend tests via Jest, and documentation covering current architecture, admin workflows, operations and maintenance, and a full configuration reference.
site/ Public website site/posts.json Published posts data site/action/action-items.json Published action artwork and download data site/resources/resources.json Published resources sections and cards site/wikipedia-tracker/ Public Wikipedia tracker config, cache, PHP API admin-panel/ Local admin UI admin-panel/index.html Admin shell and tab markup admin-panel/_resources/js/ Admin ES modules and Jest tests admin-panel/_resources/python/ Python backend, scripts, handlers, tests admin-panel/_resources/data/ SQLite database and QR history data _commands/ macOS command launchers, test helpers, migrations _config/ Templates and local configuration examples _assets/docs/ Current docs and historical plans and reports _production_logs/ Local synced access log input
The backend uses a dual-mode storage adapter that supports both SQLite and JSON, selectable via
configuration. Active admin operations prefer SQLite; the public site consumes JSON files under
site/
. Handlers that mutate SQLite state sync back to JSON as part of the publish workflow.
db_adapter.py
is the public data access layer for all handlers, abstracting the storage mode from handler logic
config.json
controls the active storage mode via
"migration": { "use_database": true }
db_layer.py
when the database is opened — no manual migration steps required
The ingestion pipeline handles the full lifecycle of bringing a new post into the system. Each step is automated where possible and logged where not:
| Public site | PHP, JSON, vanilla JavaScript |
| Admin UI | HTML, CSS, ES modules (vanilla JS) |
| Admin backend | Python 3, standard library HTTP server |
| Storage | SQLite (primary), JSON (legacy / public consumption) |
| Frontend tests | Jest |
| Backend tests | pytest |
| Platform | macOS (local admin), Apache (production host) |
The Python backend is built entirely on the standard library — no Flask, no Django, no third-party web framework. The HTTP server dispatches requests to modular handlers, each responsible for a discrete feature area. This architecture makes it straightforward to add, test, or remove handlers independently.
cd admin-panel/_resources/python ./setup_venv.sh python3 simple_server.py
The configured admin start port is 5500, with up to 10 attempts for the next free port.
open "_commands/ports_and_servers/servers/launch_PHP.command"
open "_commands/CLEAN+LAUNCH.command"
# Python backend tests cd admin-panel/_resources/python python3 -m pytest # Frontend tests cd admin-panel/_resources/js npm test
The project maintains a layered documentation system covering current state, historical decisions, and operational procedures:
_assets/docs/README.md
— documentation index and status of every Markdown file
CURRENT_SYSTEM_REFERENCE.md
— current feature and architecture reference
ADMIN_PANEL_WORKFLOWS.md
— detailed admin UI and feature workflows
OPERATIONS_AND_MAINTENANCE.md
— testing, deployment, backup, link-checking, and maintenance procedures
admin-panel/_resources/python/README.md
— Python backend reference
CONFIG_REFERENCE.md
— full configuration reference
README-DURATION.md
— duration extraction feature notes
_commands/_commands_analysis.md
— command launcher inventory
_assets/docs/history/
— completed code-review records, audits, migration notes, and superseded implementation summaries
The admin panel is designed to run locally or behind trusted network controls. A code review identified the
absence of active admin authentication in
simple_server.py
. The following are documented as required before any public or network exposure:
None of these represent an architectural constraint — they are known gaps, deliberately deferred given the local-only operational model, and clearly documented for any future deployment that changes that assumption.