Architecture
Architecture
Manager System (backend classes in lib/)
- PluginManager — handles plugin discovery, enable/disable, hook registration/execution
- ThemeManager — handles theme discovery, activation, and CSS URL/path resolution
- UpdateManager — handles version tracking and update checks for core, plugins, and themes
All managers are instantiated in index.php (after the bootstrap) and are fully integrated into the routing layer and admin panel.
Layered Structure (no framework, zero dependencies)
The application is still a single upload with no Composer, no Docker, no build step — but the old single index.php has been split into small, focused files under src/:
index.php— the thin front controller. It only wires the bootstrap, database, managers and router, then delegates request handling tosrc/actions.php.src/bootstrap.php— session start, install check,config.phpload, i18n setup (t()/pt()/tt()) and a hand-written PSR-4 autoloader for theBulletin\namespace (no Composer needed).src/helpers.php— pure helper functions:slugify(),url(),escape(),base_url(), CSRF helpers, presentation helpers (time_ago(),render_avatar(),fetch_threads(), …) andsend_email().src/Router.php— maps the incoming request path to$_GET['action'](pretty URLs).src/setup.php— ensures directories exist and initialises the database (SQLite/MySQL schema, defaults).src/actions.php— the request dispatch / routing table. Contains the per-action logic (home, thread, login, admin panels, …).
Key traits that remain unchanged:
- SQLite by default, MySQL configurable via
config.php - Session-based authentication
- Routing via
$_GET['action'], resolved from pretty URLs bysrc/Router.php - SEO-friendly URLs via
.htaccessrewrite rules
SEO-Friendly URLs
Clean URLs are supported via .htaccess rewrite rules:
/thread/{id}-{slug}— single thread view/category/{id}-{slug}— category view/u/{username}— user profile
Old query-string URLs (?action=thread&id=1) still work internally.
Directory Structure
/bulletinbored/
├── config.php # Configuration (database, email, site, theme, localization)
├── index.php # Thin front controller (bootstrap + routing only)
├── router.php # Router for PHP built-in server (dev)
├── .htaccess # SEO-friendly URL rewrites
├── lib/ # Backend managers (PluginManager, ThemeManager, UpdateManager)
│ ├── BbPdo.php # PDO wrapper used by the data layer
│ ├── repo_install.php # Repository-based install/upgrade helpers
├── src/ # Application core (no framework)
│ ├── bootstrap.php # session, config, i18n, PSR-4 autoloader
│ ├── helpers.php # slugify, url, escape, base_url, CSRF, fetch_threads, send_email, ...
│ ├── Router.php # Bulletin\Router — pretty-URL → $_GET['action']
│ ├── setup.php # directory checks + database initialisation
│ └── actions.php # request dispatch / routing table
├── views/ # Template files
│ ├── header.php # Shared frontend header/footer (loads theme CSS)
│ ├── home.php # Thread listing with sidebar categories + pagination
│ ├── thread.php # Thread view with replies, attachments, pagination
│ ├── new_thread.php # New thread form with category + file upload
│ ├── edit_post.php # Edit post form
│ ├── login.php # Login form with "Forgot Password" link
│ ├── register.php # Registration form with email field
│ ├── profile.php # User profile page with avatar, role badge, threads
│ ├── edit_profile.php # Edit profile form (username, email, password, avatar)
│ ├── admin.php # Admin dashboard (Bootstrap 5)
│ ├── admin_header.php # Admin panel header
│ ├── admin_footer.php # Admin panel footer
│ ├── admin_moderation.php # Moderation queue
│ ├── admin_categories.php # Category management
│ ├── admin_users.php # User management
│ ├── admin_settings.php # Site settings
│ ├── admin_plugins.php # Plugin manager
│ ├── admin_themes.php # Theme manager
│ ├── admin_langs.php # Language file manager
│ ├── admin_updates.php # Update manager
│ ├── forgot_password.php # Password reset request form
│ └── reset_password.php # Password reset form with token
├── themes/ # Theme system (like plugins)
│ └── freshbored/
│ └── style.css # Default theme styles
├── plugins/ # Plugin system (empty by default)
├── uploads/ # File upload storage (auto-created)
│ └── avatars/ # User avatar uploads
├── data/ # SQLite database storage (auto-created)
├── lang/ # Localization files
│ ├── en.php # English translations
│ └── it.php # Italian translations
└── README.md
Theme System
Themes work like plugins — each theme is a folder in themes/ with a style.css file:
- Configure active theme in
config.php:'theme' => 'freshbored' - Create custom themes by adding folders in
themes/ - Theme CSS is automatically loaded by
views/header.php - All frontend pages use the active theme
- Admin panel uses Bootstrap 5 default styles
Plugin System
Plugins are PHP files in plugins/ that define an {name}_init() function:
$pluginManager->addHook('event', $callback)— register a hook$pluginManager->runHook('event', ...$args)— fire a hook- Plugins are auto-loaded on every request
Example plugin in plugins/hellobored/hellobored.php demonstrates the pattern.