Every serious web app needs the same foundation. Joinery ships it all.
Login and logout. Password reset with secure time-limited tokens. Email verification on registration. Role-based access control on a 1–10 permission scale.
Persistent sessions, secure cookie handling, remember-me support.
Secure time-limited tokens sent via email. Argon2id hashing throughout.
On registration and email changes. Configurable enforcement.
1–10 scale (member through superadmin). Restrict any page or endpoint with one call.
Feature-gating tied to billing. Upgrades and downgrades handled automatically.
Group membership, member directory with search, activity tracking.
Define a class, get a full CRUD interface. Declare your fields and the table is created and kept in sync automatically.
Define fields in the class. The table is created on deploy. Schema changes picked up automatically.
Filterable, sortable queries with pagination. No SQL boilerplate for standard operations.
Soft delete with cascade support. Permanent delete with configurable cleanup actions.
Subscription billing, one-time products, coupons, webhooks — all built in. Zero platform fees.
Recurring billing, trial periods, proration. Webhook handling for all payment events.
Product catalog with multiple price types, order history, and management UI.
Percentage and fixed discounts. Single-use or multi-use. Time-limited or permanent.
PayPal as an alternative payment method alongside Stripe.
You keep 100% of what your payment processor pays you. No platform tax.
Stripe and PayPal webhooks handled automatically for payment lifecycle events.
Mailgun for deliverability, or any SMTP server via PHPMailer. Swap the provider in config without touching application code.
API-based sending with delivery tracking and bounce handling.
PHPMailer under the hood. Works with any provider — or your own mail server.
Reusable email templates for confirmations, resets, and notifications.
Mailing list management and bulk sending with subscriber management.
The admin dashboard follows consistent patterns across every feature. It's not a scaffold — it's a real, functional interface that runs the same system it's managing.
Search, filters, and sortable columns. Bulk operations for common actions.
Edit forms built with the same FormWriter system you use in your app.
Built-in reporting views for users, revenue, events, and activity.
All system settings editable from the admin. Plugin settings declared in plugin.json.
Every data model is accessible via the API. Key-based auth, rate limiting, CORS, JSON in and out.
Generate API keys per user. Scoped permissions and rate limiting per key.
CRUD plus action operations across all core models.
Add custom endpoints in your plugin. Same auth and routing infrastructure.
Plugins are self-contained modules with their own data models, views, admin pages, routes, and scheduled tasks. Activate and deactivate without data loss.
Create a view file in your plugin and the route works immediately. No config.
Plugin tables created automatically. Schema changes picked up on deploy.
Enable and disable plugins without data loss. Settings preserved between states.
Plugins you write are your code. Release under MIT, keep proprietary, or sell commercially — your choice.
The override chain lets you swap any view, template, or asset at the theme level without modifying core files or plugin files.
theme → plugin → base. Customize any view at the theme level — it overrides downstream automatically.
Bootstrap, Tailwind, or zero-dependency HTML5. FormWriter and the system adapt to whichever you choose.
Reusable page sections stored in the CMS. Editable by admins without touching code.
Most frameworks give you security tools and expect you to remember to use them. In Joinery, the secure path is the only path.
PDO prepared statements everywhere. No string concatenation paths exist in the codebase. The model layer is structurally incapable of passing raw input to the database.
All output through FormWriter is escaped automatically. View templates use htmlspecialchars(). You can't forget — the helpers do it.
FormWriter generates and validates CSRF tokens on every form. Zero extra setup required.
Argon2id. Not bcrypt, not MD5. The current best practice. Legacy bcrypt hashes auto-upgrade on next login.
HttpOnly, SameSite=Lax, Secure. Session cookies are inaccessible to JavaScript.
Validated by type and size, stored outside web root, served through controlled handlers — not direct URLs.
Install Joinery and all of this is already working.