Links:
Dependencies:
A modern, database-backed Content Management System for PHP 8.4+ built on the Neuron framework. Provides a complete content platform with a blog, CMS-managed pages, an events calendar with registration, contact forms, reusable content shortcodes/widgets, user authentication, and a full admin panel.
User Authentication & Authorization
Member Registration & Management
Blog System
Pages
/pages/:slugEvents & Calendar
/calendar with month and category views[featured-event] shortcodeEvent Registration
[event-registration] shortcode (single event or "next upcoming dates" of a category)Contact Forms
[contact] shortcodeShortcodes & Widgets
[latest-posts], [calendar], [featured-event], [event-registration], [contact]Media Library
Content Revisions
Admin Panel
Maintenance Mode
Email System
Scheduling & Background Jobs
Database Support
All three databases are fully supported with identical behavior across platforms:
Foreign Key Constraints: Properly enforced on all databases (including SQLite)
Timestamp Management: created_at and updated_at handled at application level
Transactions: Full ACID compliance
Database-Specific Optimizations:
Performance Notes:
All databases are tested in CI on every commit to ensure consistent behavior.
composer require neuron-php/cms
The cms:install command sets up everything automatically:
php neuron cms:install
The installer will:
That's it. The installer handles all setup automatically.
After updating the package with Composer, run the upgrade command to copy any new migrations and resources into your installation:
composer update neuron-php/cms
php neuron cms:upgrade
Useful flags:
--check - show available updates without applying them--migrations-only - copy only new migration files--skip-views - don't touch published views--run-migrations - run database migrations automaticallyThe upgrade command preserves your customizations (it won't overwrite views by default) and reports any version-specific notes or breaking changes.
After running cms:install, your project will have the following structure:
your-project/
├── app/
│ ├── Controllers/ # Your custom controllers
│ ├── Events/ # Custom event classes
│ ├── Initializers/ # Application initializers
│ │ ├── AuthInitializer.php
│ │ ├── MaintenanceInitializer.php
│ │ ├── PasswordResetInitializer.php
│ │ └── ViewDataInitializer.php
│ ├── Jobs/ # Background jobs
│ ├── Listeners/ # Event listeners
│ ├── Models/ # Domain models
│ ├── Repositories/ # Data repositories
│ └── Services/ # Business logic services
│
├── config/
│ ├── auth.yaml # Authentication configuration
│ ├── neuron.yaml # Main application config
│ ├── event-listeners.yaml # Event listener configuration
│ └── routing.yaml # Routing configuration (URL rewrites, controller paths)
│
├── db/
│ ├── migrate/ # Database migrations
│ │ ├── *_create_users_table.php
│ │ ├── *_create_posts_table.php
│ │ ├── *_create_pages_table.php
│ │ ├── *_create_categories_table.php
│ │ ├── *_create_tags_table.php
│ │ ├── *_create_events_table.php
│ │ ├── *_create_event_categories_table.php
│ │ ├── *_create_event_registrations_table.php
│ │ ├── *_create_contact_submissions_table.php
│ │ └── *_create_queue_tables.php
│ └── seed/ # Database seeders
│
├── public/
│ ├── index.php # Front controller
│ └── icon.png # Default favicon
│
├── resources/
│ └── views/
│ ├── admin/ # Admin panel templates
│ │ ├── categories/
│ │ ├── dashboard/ # Dashboard views
│ │ ├── posts/ # Post management
│ │ ├── pages/ # Page management
│ │ ├── events/ # Event management
│ │ ├── event_categories/
│ │ ├── event_registrations/
│ │ ├── contact_submissions/
│ │ ├── media/
│ │ ├── profile/
│ │ ├── tags/
│ │ └── users/
│ ├── auth/ # Login/password reset
│ ├── blog/ # Public blog views
│ ├── calendar/ # Public calendar/event views
│ ├── pages/ # Public CMS page views
│ ├── member/ # Member registration & dashboard
│ │ ├── dashboard/
│ │ ├── profile/
│ │ └── registration/
│ ├── content/ # Content pages
│ ├── emails/ # Email templates
│ ├── http_codes/ # Error pages
│ └── layouts/ # Layout templates
│
├── storage/
│ ├── cache/ # Cache storage
│ ├── logs/ # Application logs
│ └── database.sqlite3 # SQLite database (if using SQLite)
│
└── composer.json
After running cms:install, you're ready to go!
php -S localhost:8000 -t public
Visit:
http://localhost:8000/bloghttp://localhost:8000/adminhttp://localhost:8000/registerhttp://localhost:8000/member (after registration)Log in with the admin credentials you created during installation.
For background jobs and scheduled tasks:
vendor/bin/neuron jobs:run
This runs both the scheduler (for scheduled tasks) and worker (for email sending and background jobs).
If you need to customize settings, edit config/neuron.yaml:
site:
name: My Blog
title: Welcome to My Blog
description: A blog about technology
url: https://example.com
database:
adapter: sqlite # or mysql, pgsql
name: storage/database.sqlite3
All routing, authentication settings, and event listeners are pre-configured by the installer.
/adminAdmin users can:
The CMS supports public member registration with email verification:
Enable Registration: Configure in config/neuron.yaml:
member:
registration_enabled: true
require_email_verification: true
Registration Flow:
/register to create an account/member dashboard/member (requires authentication)/member/profileCreate CMS-managed pages in the admin panel (Pages → New Page); they're served at /pages/:slug. Page and post bodies support shortcodes that render dynamic widgets:
| Shortcode | Renders |
|---|---|
[latest-posts] |
The most recent blog posts |
[calendar] |
An events calendar/list |
[featured-event] |
The next available featured event |
[event-registration] |
A registration form for an event or event category |
[contact] |
A contact form |
Examples:
[latest-posts limit="5"]
[featured-event]
[event-registration event="open-house-2026"]
[event-registration category="workshops" limit="3"]
[contact]
[featured-event], and/or enable registration on the event.[event-registration] shortcode on a page/post (single event or the next upcoming dates of a category).All view templates are in resources/views/ and can be customized:
layouts/main.php - Main site layoutblog/index.php - Blog listingblog/show.php - Individual postadmin/* - Admin panel templatesmember/* - Member registration and dashboard templates
member/registration/register.php - Registration formmember/registration/verify-email-sent.php - Email verification sent pagemember/registration/email-verified.php - Email verification success/failuremember/dashboard/index.php - Member dashboardmember/profile/edit.php - Profile editingThe CMS includes a complete job system for scheduled tasks and background processing. You can run it in three different modes:
Run both scheduler and queue worker together with a single command:
vendor/bin/neuron jobs:run
This is the easiest way to run the complete job system. It manages both the scheduler and worker in one process.
Options:
--schedule-interval=30 - Scheduler polling interval in seconds (default: 60)--queue=emails,default - Queue(s) to process (default: default)--worker-sleep=5 - Worker sleep when queue is empty (default: 3)--worker-timeout=120 - Job timeout in seconds (default: 60)--max-jobs=100 - Max jobs before restarting worker (default: unlimited)Examples:
# Run with defaults (both scheduler and worker)
vendor/bin/neuron jobs:run
# Run with custom schedule interval and specific queues (in order of priority)
vendor/bin/neuron jobs:run --schedule-interval=30 --queue=emails,notifications
Run just the scheduler for executing scheduled tasks:
vendor/bin/neuron jobs:schedule
Handles recurring tasks and scheduled jobs defined in config/schedule.yaml.
Options:
--interval=30 - Polling interval in seconds (default: 60)--poll - Run a single poll and exit (useful for cron)Run just the queue worker for processing background jobs:
vendor/bin/neuron jobs:work
Processes queued jobs including emails and background tasks.
Options:
--queue=emails - Process specific queue--sleep=5 - Seconds to sleep when queue is empty--timeout=120 - Job timeout in seconds--max-jobs=100 - Maximum jobs to process before stoppingThe installer creates config/auth.yaml with sensible defaults. You can customize:
The CMS uses attribute-based routing defined directly on controller methods. The installer creates config/routing.yaml to configure URL rewrites and controller paths.
By default, the CMS rewrites the root URL (/) to /blog. You can customize this in config/routing.yaml:
# config/routing.yaml
rewrites:
'/': '/custom/landing' # Rewrite root to your custom controller
controller_paths:
- path: 'app/Controllers' # Your controllers first (takes precedence)
namespace: 'App\Controllers'
- path: 'vendor/neuron-php/cms/src/Cms/Controllers'
namespace: 'Neuron\Cms\Controllers'
Then create your custom landing controller:
// app/Controllers/Landing.php
use Neuron\Mvc\Controller;
use Neuron\Routing\Attributes\Get;
class Landing extends Controller
{
#[Get('/custom/landing', name: 'landing')]
public function index()
{
return $this->renderHtml(OK, [], 'custom-home');
}
}
URL rewrites are transparent (no HTTP redirect) - the browser URL stays the same while the application routes to a different path internally.
The CMS provides these pre-configured routes via controller attributes:
Public blog pages:
/blog - Blog listing/blog/article/:slug - Individual post/blog/category/:slug - Category listing/blog/tag/:slug - Tag listing/blog/rss - RSS feedPages:
/pages/:slug - CMS-managed pageCalendar & events:
/calendar - Calendar/event listing/calendar/event/:slug - Individual event/calendar/category/:slug - Events by categoryEvent registration:
/events/register - Registration form submission (CSRF protected)/events/register/token - CSRF token endpoint for cached formsContact:
/contact - Contact form/contact/submit - Contact form submission (CSRF protected)Admin panel: /admin/* - Full admin interface with authentication (posts, pages, categories, tags, events, event categories, event registrations, contact submissions, media, users, jobs)
Authentication:
/login - Login form/logout - Logout handlerPassword reset:
/password/reset - Request reset form/password/reset/confirm - Reset confirmationMember registration and dashboard:
/register - Registration form/verify-email - Email verification/resend-verification - Resend verification email (rate-limited)/member - Member dashboard (requires authentication)/member/profile - Profile managementFor more information about routing configuration, URL rewrites, and attribute-based routing, see the MVC Routing Documentation.
Configure email in config/neuron.yaml:
email:
driver: smtp # smtp, sendmail, or mail
host: smtp.example.com
port: 587
username: [email protected]
password: your_password
encryption: tls # tls or ssl
from_address: [email protected]
from_name: My Blog
test_mode: false # optional - logs emails instead of sending
Event registration notifications are configured under the events.registration section of config/neuron.yaml:
events:
registration:
notify_email: "[email protected]" # admin recipient for new-registration emails
# (falls back to email.from_address when blank)
confirmation_enabled: false # also email a confirmation to the registrant
success_message: "Thank you for registering. We look forward to seeing you!"
notify_email is who receives the "New Event Registration" email; the registrant's address is set as Reply-To.notify_email is blank, it falls back to email.from_address. If neither is set, no admin email is sent (a warning is logged).email configuration (and test_mode: false) to actually deliver.The resend verification email endpoint is protected by rate limiting to prevent DOS attacks and spam. The default configuration is:
These limits are enforced server-side using the ResendVerificationThrottle service, which:
To customize rate limits, modify the throttle configuration in your application initialization:
// app/Initializers/CustomRateLimitInitializer.php
$throttle = new ResendVerificationThrottle(null, [
'ip_limit' => 10, // 10 requests per window
'ip_window' => 600, // 10 minutes
'email_limit' => 2, // 2 resends per window
'email_window' => 900 // 15 minutes
]);
The CMS registers the following neuron console commands:
Installation & upgrades
cms:install - Scaffold a new CMS project (directories, views, config, migrations, admin user)cms:upgrade - Copy new migrations/resources after a Composer update (see Upgrading)User management
cms:user:create - Create a user accountcms:user:list - List user accountscms:user:delete - Delete a user accountcms:user:reset-password - Reset a user's passwordMaintenance mode
cms:maintenance:enable - Put the site into maintenance modecms:maintenance:disable - Take the site out of maintenance modecms:maintenance:status - Show current maintenance statusRun any command with php neuron <command> (for example, php neuron cms:user:create).
neuron-php/mvc (0.8.*) - MVC frameworkneuron-php/cli (0.8.*) - CLI commandsneuron-php/jobs (0.2.*) - Background jobsphpmailer/phpmailer (^6.9) - Email sendingrobmorgan/phinx (^0.16) - Database migrationsMIT License - see LICENSE file for details