⚠️ Documentation Under Review: This documentation is currently being updated and verified against the actual implementation. Some information may be incorrect or incomplete. Please verify all code examples against the actual source code before use.
This guide provides comprehensive instructions for installing and configuring the Neuron CMS component. Two installation methods are available: an automated installation command that handles configuration interactively, and a manual installation process for environments requiring specific customization or non-standard configurations.
pdo: Database abstraction layerpdo_sqlite, pdo_mysql, or pdo_pgsql: Database driver for chosen database systemcurl: HTTP request functionalityjson: JSON encoding/decodingmbstring: Multibyte string handlingopenssl: Cryptographic operationssession: Session managementOne of the following database systems is required:
storage/ and cache/ directoriesThe automated installation process utilizes the cms:install command to configure the system interactively.
composer require neuron-php/cms
This command installs the CMS package and its dependencies:
neuron-php/mvc (0.8.*): MVC frameworkneuron-php/cli (0.8.*): CLI command infrastructureneuron-php/jobs (0.2.*): Background job systemneuron-php/orm (0.1.*): Database ORM layerphpmailer/phpmailer (^6.9): Email delivery./vendor/bin/neuron cms:install [options]
Options:
--force or -f: Force reinstall without prompts (overwrites existing files)--use-secrets or -s: Use encrypted credentials stored in secretsThe installer executes the following operations sequentially:
Creates the application directory hierarchy:
app/
├── Controllers/
├── Events/
├── Initializers/
├── Jobs/
├── Listeners/
├── Models/
├── Repositories/
└── Services/
config/
db/
├── migrate/
└── seed/
public/
resources/
└── views/
├── admin/
├── auth/
├── blog/
├── content/
├── emails/
├── http_codes/
├── layouts/
└── member/
storage/
├── cache/
└── logs/
Publishes pre-built view templates from the package to the project's resources/views/ directory. Templates include:
Publishes application bootstrap initializers to app/Initializers/:
AuthInitializer.php: Configures authentication systemMaintenanceInitializer.php: Registers maintenance mode middlewarePasswordResetInitializer.php: Configures password reset functionalityRegistrationInitializer.php: Configures member registration systemViewDataInitializer.php: Provides global view dataCreates configuration files in config/:
neuron.yaml: Primary application configuration
system:
timezone: UTC
base_path: resources
routes_path: resources/config
logging:
destination: \Neuron\Log\Destination\File
format: \Neuron\Log\Format\PlainText
file: storage/logs/app.log
level: info
cache:
enabled: false
storage: file
path: storage/cache/views
ttl: 3600
html: true
markdown: true
json: false
xml: false
views:
path: resources/views
site:
name: Neuron CMS
url: https://localhost
description: A modern content management system built with Neuron
title: Neuron CMS
theme:
admin: vapor
subscriber: sandstone
guest: sandstone
member:
registration_enabled: true
default_role: subscriber
require_email_verification: true
verification_url: /verify-email
verification_token_expiration_minutes: 60
database:
adapter: sqlite
name: storage/database.sqlite3
auth.yaml: Authentication system configuration
auth:
default: session
session:
lifetime: 120
expire_on_close: false
cookie_name: neuron_session
cookie_httponly: true
cookie_secure: true
cookie_samesite: Lax
remember:
enabled: true
lifetime: 43200
passwords:
min_length: 8
require_uppercase: true
require_lowercase: true
require_numbers: true
require_special_chars: false
hash_algorithm: argon2id
throttle:
enabled: true
max_attempts: 5
lockout_duration: 15
routes.yaml: HTTP route definitions
Contains pre-configured routes for:
event-listeners.yaml: Event-to-listener mappings
Configures event listeners for system events.
Creates public/index.php:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use function Neuron\Mvc\Boot;
use function Neuron\Mvc\Dispatch;
$app = Boot( __DIR__ . '/../config' );
Dispatch( $app );
The installer prompts for database configuration:
For SQLite:
storage/database.sqlite3)For MySQL/MariaDB:
localhost)3306)utf8mb4)For PostgreSQL:
localhost)5432)The configuration is written to config/neuron.yaml.
Copies database migration files to db/migrate/:
Core Authentication & User Management:
20250111000000_create_users_table.php: Users table with authentication fields20250112000000_create_email_verification_tokens_table.php: Email verification tokens20251205000000_add_two_factor_and_timezone_to_users.php: Two-factor auth and timezone supportContent Management:
20250113000000_create_pages_table.php: Static pages20250114000000_create_categories_table.php: Categories for posts20250115000000_create_tags_table.php: Tags for posts20250116000000_create_posts_table.php: Blog posts20250117000000_create_post_categories_table.php: Post-category relationships20250118000000_create_post_tags_table.php: Post-tag relationships20251119224525_add_content_raw_to_posts.php: Raw content field for postsEvent Management:
20251221000000_create_event_categories_table.php: Event categories20251221000001_create_events_table.php: Calendar eventsDatabase Optimizations:
20251229000000_update_foreign_keys_to_set_null.php: Foreign key optimizationsAll migrations are copied during installation and can be executed immediately or later via ./vendor/bin/neuron db:migrate.
The installer offers to execute migrations immediately. If accepted, the following tables are created:
users table:
id: Primary keyusername: Unique usernameemail: Unique email addresspassword_hash: Hashed passwordrole: User role (admin, editor, author, subscriber)status: Account status (active, inactive, banned)email_verified: Email verification statustwo_factor_secret: 2FA secret (nullable)remember_token: Remember me token (nullable)failed_login_attempts: Failed login counterlocked_until: Account lockout timestamp (nullable)last_login_at: Last login timestamp (nullable)timezone: User timezonecreated_at: Creation timestampupdated_at: Last update timestamppassword_reset_tokens table:
id: Primary keyemail: Email addresstoken: Reset tokencreated_at: Creation timestampexpires_at: Expiration timestampemail_verification_tokens table:
id: Primary keyemail: Email addresstoken: Verification tokencreated_at: Creation timestampexpires_at: Expiration timestampThe installer prompts for initial administrative user credentials:
auth.yamlThe user is created with:
adminactivetrueManual installation provides complete control over the installation process.
composer require neuron-php/cms
mkdir -p app/{Controllers,Events,Initializers,Jobs,Listeners,Models,Repositories,Services}
mkdir -p config
mkdir -p db/{migrate,seed}
mkdir -p public
mkdir -p resources/views/{admin,auth,blog,content,emails,http_codes,layouts,member}
mkdir -p storage/{cache,logs}
Set appropriate permissions:
chmod 755 storage storage/cache storage/logs
Copy view templates from the package:
cp -r vendor/neuron-php/cms/resources/views/* resources/views/
Alternatively, symlink for easier updates:
ln -s ../vendor/neuron-php/cms/resources/views resources/views
cp -r vendor/neuron-php/cms/resources/app/Initializers/* app/Initializers/
config/neuron.yamlsystem:
timezone: America/New_York
base_path: /var/www/html/project
routes_path: /var/www/html/project/config
logging:
destination: \Neuron\Log\Destination\File
format: \Neuron\Log\Format\PlainText
file: storage/logs/app.log
level: info
cache:
enabled: true
storage: file
path: storage/cache/views
ttl: 3600
html: true
markdown: true
json: false
xml: false
views:
path: resources/views
site:
name: My Website
title: Welcome to My Website
url: https://example.com
description: A comprehensive content management system
theme:
admin: vapor
subscriber: sandstone
guest: sandstone
member:
registration_enabled: true
default_role: subscriber
require_email_verification: true
verification_url: /verify-email
verification_token_expiration_minutes: 60
database:
adapter: mysql
host: localhost
port: 3306
name: cms_database
user: cms_user
pass: secure_password
charset: utf8mb4
config/auth.yamlCopy from package:
cp vendor/neuron-php/cms/config/auth.yaml config/
Or create manually with the structure shown in the automated installation section.
config/routes.yamlCopy from package:
cp vendor/neuron-php/cms/resources/config/routes.yaml config/
config/event-listeners.yamlCopy from package:
cp vendor/neuron-php/cms/resources/config/event-listeners.yaml config/
Create public/index.php:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use function Neuron\Mvc\Boot;
use function Neuron\Mvc\Dispatch;
$app = Boot( __DIR__ . '/../config' );
Dispatch( $app );
Create the database file:
touch storage/database.sqlite3
chmod 644 storage/database.sqlite3
Ensure config/neuron.yaml contains:
database:
adapter: sqlite
name: storage/database.sqlite3
Create the database:
CREATE DATABASE cms_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'cms_user'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON cms_database.* TO 'cms_user'@'localhost';
FLUSH PRIVILEGES;
Configure in config/neuron.yaml:
database:
adapter: mysql
host: localhost
port: 3306
name: cms_database
user: cms_user
pass: secure_password
charset: utf8mb4
Create the database:
CREATE DATABASE cms_database;
CREATE USER cms_user WITH PASSWORD 'secure_password';
GRANT ALL PRIVILEGES ON DATABASE cms_database TO cms_user;
Configure in config/neuron.yaml:
database:
adapter: pgsql
host: localhost
port: 5432
name: cms_database
user: cms_user
pass: secure_password
cp vendor/neuron-php/cms/resources/database/migrate/* db/migrate/
./vendor/bin/neuron db:migrate
This creates the database schema.
./vendor/bin/neuron cms:user:create
Follow the prompts to create an administrative account with the admin role.
Configure SMTP settings in config/neuron.yaml:
email:
driver: smtp
host: smtp.gmail.com
port: 587
username: [email protected]
password: your-app-password
encryption: tls
from_address: [email protected]
from_name: My Website
test_mode: false
For development, enable test mode to log emails instead of sending:
email:
test_mode: true
Configure member registration in config/neuron.yaml:
member:
registration_enabled: true
default_role: subscriber
require_email_verification: true
verification_url: /verify-email
verification_token_expiration_minutes: 60
Enable caching for production:
cache:
enabled: true
storage: file
path: storage/cache
ttl: 3600
html: true
markdown: true
For production with HTTPS:
auth:
session:
cookie_secure: true
cookie_samesite: Strict
For development without HTTPS:
auth:
session:
cookie_secure: false
cookie_samesite: Lax
Create .htaccess in public/:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
</IfModule>
Configure virtual host:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html/project/public
<Directory /var/www/html/project/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/cms_error.log
CustomLog ${APACHE_LOG_DIR}/cms_access.log combined
</VirtualHost>
server {
listen 80;
server_name example.com;
root /var/www/html/project/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\. {
deny all;
}
}
Set secure permissions:
# Set owner
chown -R www-data:www-data /var/www/html/project
# Set directory permissions
find /var/www/html/project -type d -exec chmod 755 {} \;
# Set file permissions
find /var/www/html/project -type f -exec chmod 644 {} \;
# Writable directories
chmod -R 775 /var/www/html/project/storage
chmod -R 775 /var/www/html/project/storage/cache
chmod -R 775 /var/www/html/project/storage/logs
Create separate configuration files:
config/
├── neuron.yaml # Development
├── neuron.production.yaml # Production
└── neuron.staging.yaml # Staging
Load based on environment variable:
// public/index.php
$env = getenv( 'APP_ENV' ) ?: 'development';
$configFile = $env === 'production' ? 'neuron.production.yaml' : 'neuron.yaml';
$app = Boot( __DIR__ . '/../config', $configFile );
For HTTPS deployments:
config/auth.yaml:auth:
session:
cookie_secure: true
config/neuron.yaml:site:
url: https://example.com
Configure systemd service for job processing:
# /etc/systemd/system/neuron-jobs.service
[Unit]
Description=Neuron CMS Job Processor
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/html/project
ExecStart=/usr/bin/php /var/www/html/project/vendor/bin/neuron jobs:run
Restart=always
[Install]
WantedBy=multi-user.target
Enable and start:
systemctl enable neuron-jobs
systemctl start neuron-jobs
Create a verification script verify-installation.php:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$checks = [
'PHP Version' => version_compare( PHP_VERSION, '8.4.0', '>=' ),
'PDO Extension' => extension_loaded( 'pdo' ),
'JSON Extension' => extension_loaded( 'json' ),
'cURL Extension' => extension_loaded( 'curl' ),
'Storage Writable' => is_writable( __DIR__ . '/storage' ),
'Cache Writable' => is_writable( __DIR__ . '/storage/cache' ),
'Logs Writable' => is_writable( __DIR__ . '/storage/logs' ),
'Config Exists' => file_exists( __DIR__ . '/config/neuron.yaml' ),
];
foreach( $checks as $check => $result )
{
echo sprintf( "%-20s: %s\n", $check, $result ? 'OK' : 'FAIL' );
}
Execute:
php verify-installation.php
http://example.com/loginhttp://example.com/adminhttp://example.com/admin/usershttp://example.com/admin/posts/createhttp://example.com/blogSymptom: PDO connection exceptions
SQLite Solutions:
# Verify file exists
ls -l storage/database.sqlite3
# Check permissions
chmod 644 storage/database.sqlite3
chmod 755 storage
# Verify SQLite extension
php -m | grep pdo_sqlite
MySQL/PostgreSQL Solutions:
# Test connection
mysql -u cms_user -p -h localhost cms_database
psql -U cms_user -h localhost -d cms_database
# Verify credentials in config/neuron.yaml
# Ensure database exists
# Check firewall rules
Symptom: Unable to write to storage directory
Solution:
# Set ownership
chown -R www-data:www-data storage
# Set permissions
chmod -R 775 storage
Symptom: Cannot maintain login session
Solutions:
session.save_path in php.inicookie_secure matches HTTPS availabilitycookie_samesite compatibilitySymptom: Migration execution errors
Solutions:
# Verify database connection
./vendor/bin/neuron db:status
# Check migration syntax
php -l db/migrate/*.php
# Manual table creation
# (Execute SQL from migration files directly)
Symptom: Template file not found errors
Solutions:
# Verify views published
ls -la resources/views/admin
# Re-publish views
cp -r vendor/neuron-php/cms/resources/views/* resources/views/
# Check views.path in config/neuron.yaml
Symptom: Class not found errors
Solution:
composer dump-autoload
Symptom: PHP fatal error: Allowed memory size exhausted
Solution:
# php.ini
memory_limit = 256M
To remove the CMS:
# SQLite
cp storage/database.sqlite3 backup/
# MySQL
mysqldump -u cms_user -p cms_database > backup.sql
# PostgreSQL
pg_dump -U cms_user cms_database > backup.sql
composer remove neuron-php/cms
rm -rf resources/views/admin
rm -rf resources/views/auth
rm -rf resources/views/member
rm -rf app/Initializers
rm config/routes.yaml config/auth.yaml config/event-listeners.yaml
DROP TABLE users;
DROP TABLE password_reset_tokens;
DROP TABLE email_verification_tokens;
DROP TABLE posts;
DROP TABLE categories;
DROP TABLE tags;