No magic, no annotations, no framework ceremony. PHP 8, PostgreSQL, and patterns that have run in production for years. Open it, read it, modify it.
A clean, well-structured PHP application. No framework magic — just patterns that work.
Your data in a real database. Full SQL, JSONB columns, prepared statements throughout. No ORM to fight. No magic that generates surprise queries behind your back.
Front-controller routing through serve.php. Clean separation of data classes, logic files, and view templates. No autoloading mystery — you can trace exactly what loads and why.
Modern vanilla JS. No jQuery, no Webpack, no build step. Bootstrap and Tailwind are supported when you want them. FormWriter adapts to whichever you choose.
Define a class, get full CRUD. new User($id, true) loads the record. $user->save() writes it. No SQL strings for standard operations.
Self-contained modules with their own routes, data models, admin pages, and scheduled tasks. Build features in isolation. Deploy without touching core.
theme → plugin → base. Swap any view or asset at the theme level without forking anything downstream.
Most frameworks require you to remember to use security features. In Joinery, they're structural — you'd have to work to bypass them.
PDO prepared statements everywhere. There are no concatenated query strings in the codebase. The model layer is structurally incapable of passing raw input to the database.
All user-generated output is escaped via htmlspecialchars(). The FormWriter system handles output encoding automatically — individual views cannot forget to escape.
FormWriter generates and validates CSRF tokens on every form. You get it for free on every form you build with the system.
Argon2id. Not bcrypt (which PHP used to default to), not MD5, not SHA-1. The current best practice. Legacy hashes are automatically upgraded on the user's next login.
HttpOnly, SameSite=Lax, Secure. Session cookies are inaccessible to JavaScript and scoped to prevent cross-site attacks.
You can read every line of code that touches user data. No obfuscation, no compiled binaries, no trust-us black boxes.
Build integrations, automate workflows, or build your own frontend.
Generate API keys per user or per integration. Scoped permissions and per-key rate limiting.
CRUD plus action operations across all core data models. JSON in and out.
Add custom endpoints in your plugin. Same auth, routing, and rate limiting infrastructure.
Plugins are self-contained modules. Each has its own MVC structure, activated and deactivated without data loss.
No route config. Create a view file and the URL works immediately.
Plugin tables created and updated automatically on deploy. No migration files for schema changes.
Plugins you write are yours. Release under any license you choose — MIT, proprietary, commercial. No restrictions.
If you're building a custom app, you can completely replace the public-facing UI through the theme override chain, without touching anything in core or plugins.
theme → plugin → base. Customize any view at the theme level. It overrides downstream automatically.
Bootstrap, Tailwind, or zero-dependency HTML5. FormWriter and the rest of the system adapt to your choice.
Your design, your HTML, your CSS — completely replaceable without forking. Core updates don't touch your theme.
ScrollDaddy is a commercial DNS filtering service. It runs entirely on Joinery.
User accounts, device management, filter configuration, subscription billing, scheduled blocklist updates, and a REST API served to a companion Go DNS server — all built as a Joinery plugin and theme. No core modifications. Real users, real billing, real traffic. Same framework you'd download today.
11 data models, full admin interface, scheduled tasks — all in one plugin.
Full public-facing site with its own design system, no core modifications.
Feature-gated subscription tiers with real paying customers.
Device configurations served to the Go DNS server in real time.
Requirements — Ubuntu 24.04 recommended. Apache2, PHP 8.x, PostgreSQL. Standard LAMP stack, nothing exotic.
Installation — Download the release, run the install script. Apache, PHP, and PostgreSQL are configured automatically. Full guide at /install.
Updates — Automated upgrade system. One command pulls the latest release and applies any schema changes.
Source-available under the PolyForm Noncommercial license.