Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Ahondev/portfolio-v2/llms.txt

Use this file to discover all available pages before exploring further.

WP SSR Framework ships two completely independent routers: a Web Router that intercepts every front-end request before WordPress ever renders a template, and an API Router built on top of the WP REST API that exposes a clean /api/v1/ namespace. Both are configured in plain PHP files you edit directly — no admin UI, no database rows, no rewrite-rule archaeology.

Web Router

The Web Router owns every non-WordPress URL. On every request WebRouter::handleRequest() runs early in the WordPress boot cycle and either serves a response or returns false to fall through to normal WordPress processing.Routes are registered in configuration/routes/web.php using the WebRoute facade (aliased as Route inside that file).

Static routes

// configuration/routes/web.php
use Ahon\WPCMS\Routing\Web\WebRoute as Route;

Route::get('/', 'Accueil', [HomeController::class, 'home']);
Route::get('/agence', 'Agence', [HomeController::class, 'agence']);
Route::get('/devis', 'Devis', [HomeController::class, 'devis']);
Route::get('/contact', 'Contact', [HomeController::class, 'contact']);
WebRoute::get() signature:
WebRoute::get(string $path, string $name, array $controller): WebRouteDefinition
ParameterTypeDescription
$pathstringAbsolute URL path, e.g. /contact
$namestringHuman-readable page title used for WP registration
$controllerarrayTwo-element array: [ControllerClass::class, 'method']
WebRoute::post() signature:
WebRoute::post(string $path, string $controller, string $name, bool $auth = false): WebRouteDefinition
ParameterTypeDescription
$pathstringAbsolute URL path, e.g. /submit
$controllerstringController class name
$namestringHuman-readable route name
$authboolWhen true, requires an active WordPress session
Both methods return a WebRouteDefinition object, which stores the HTTP method, path, controller class, and action name.

CPT routes

Route::CPT() is a convenience helper that binds an archive and a single route for a Custom Post Type in one call. The path serves as the base URL prefix.
Route::CPT('/services', Service::class, ServiceController::class);
Route::CPT('/realisations', Realisation::class, RealisationController::class);
Route::CPT('/blog', Article::class, BlogController::class);
Signature:
WebRoute::CPT(string $path, string $postType, string $controller): void
ParameterTypeDescription
$pathstringBase URL prefix, e.g. /blog
$postTypestringEloquentCPT class that exposes a $model static property
$controllerstringController class implementing CPTControllerInterface
At runtime:
  • GET /blog → calls BlogController::archive()
  • GET /blog/my-article-slug → looks up the post by slug, then calls BlogController::single(?EloquentCPT $post)

Route groups

Use Route::group() to apply a shared prefix to several routes at once:
Route::group('/admin', [
    Route::get('/dashboard', 'Dashboard', [AdminController::class, 'dashboard']),
    Route::get('/settings', 'Settings', [AdminController::class, 'settings']),
]);
Signature:
WebRoute::group(string $prefix, array $route_ids): void

Dispatch flow

WebRouter::handleRequest() executes the following logic on every inbound request:
1

Skip WordPress-owned paths

Requests starting with /wp/, /api/, /uploads/, /admin, or /client are ignored immediately — WordPress handles them normally.
2

Bot detection & static cache

BotDetector::isBot() inspects the User-Agent. If a bot is detected, the router looks for a pre-generated HTML file under cache/client/static/{slug}.html. When found, it streams the file with X-SSG-Cache: HIT and exits. The ?json=1 query param bypasses the cache even for bots.
3

Static route lookup

The current URI is matched against the $routes hash map. If an exact match is found the corresponding controller method is called and its output echoed.
4

CPT route matching

Each registered CPT base path is checked. An exact match dispatches to archive(); a path that starts with the base followed by a slug segment dispatches to single() after fetching the matching WP_Post by slug.
5

Fall through

If no route matched, handleRequest() returns false and WordPress renders the request normally.

Dev-mode auto page registration

When WP_ENV=development, every call to addRoute() also calls registerPage() internally. This inserts a WordPress Page post whose slug mirrors the route path, so that ACF field groups scoped to post_type = page are always available for the route in the WordPress admin — without you having to create pages by hand.
// Happens automatically in development — no action required
$router->registerPage($route); // wp_insert_post([...]) if page doesn't exist

Build docs developers (and LLMs) love