blackcube/starter

Blackcube CMS starter

Maintainers

Package info

github.com/blackcubeio/starter

Type:project

pkg:composer/blackcube/starter

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-05-04 18:00 UTC

This package is auto-updated.

Last update: 2026-05-04 18:01:19 UTC


README

Demonstration application for Blackcube CMS on Yii3. Use as a starting point with composer create-project.

License

Requirements

  • PHP 8.4+
  • MySQL / MariaDB
  • Composer
  • Node.js (for frontend assets)

Installation

composer create-project blackcube/starter my-project
cd my-project
cp .env.example .env

Create oauth2 keys:

# private key (2048 bits minimum, 4096 recommanded)
openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:4096

# public key
openssl rsa -in private.pem -pubout -out public.pem

and copy the keys in config/keys/

Edit .env with your database credentials:

DB_DRIVER=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=myapp
DB_USER=myapp
DB_PASSWORD=myapp

and all needed conf vars

Run the migrations:

php yii.php migrate:up

Stack

Configuration

Parameters — config/common/params.php

'blackcube/ssr' => [
    'scanAttributes' => true,
    'scanAliases' => ['@src/Handlers'],
],
Parameter Description
scanAttributes Scan handler classes for #[RoutingHandler] attributes
scanAliases Yii aliases pointing to directories containing handlers

Middleware — config/web/di/application.php

SsrRoutingMiddlewareInterface::class => YiiSsrRoutingMiddleware::class,
static function (SsrRoutingMiddlewareInterface $middleware) use ($params): SsrRoutingMiddlewareInterface {
    return $middleware
        // ->withExcludedPrefixes('dboard/', 'api/graphql')
        ->withXeo()
        ->withMdAlternate();
},

Pipeline order:

ErrorCatcher → Session → CookieLogin → CSRF → SsrRoutingMiddleware → Router

Handlers

A handler renders CMS content. The SSR middleware resolves the handler via the Type's handler field: a Type with handler: 'article' dispatches to the class carrying #[RoutingHandler(route: 'article')].

Place handler classes in src/Handlers/:

#[RoutingHandler(route: 'landing')]
final class LandingHandler implements RequestHandlerInterface
{
    public function __construct(
        private readonly Content|Tag $element,
        private readonly WebViewRenderer $viewRenderer,
    ) {}

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        // $this->element is the Content or Tag resolved from the slug
        // $this->viewRenderer carries Xeo injections (meta, OG, JSON-LD)
    }
}

The CMS entity and Yii services are injected in the constructor. The request is passed to handle().

Error handlers

#[RoutingHandler(route: 'not-found', errorCode: 404)]
final class NotFoundHandler implements RequestHandlerInterface { }

#[RoutingHandler(route: 'server-error', errorCodesRange: [500, 599])]
final class ServerErrorHandler implements RequestHandlerInterface { }

Special routes

Handled automatically by the SSR package — no code needed:

Route Content-Type Source
/sitemap.xml application/xml Active CMS slugs with sitemap metadata
/robots.txt text/plain GlobalXeo "Robots" entry
/llms.txt text/plain LlmMenu navigation tree
/llms-full.txt text/plain LlmMenu tree with full markdown content
/{slug}.md text/markdown Markdown export of any CMS page
Redirects 301/302 Slugs with a target URL

License

BSD-3-Clause. See LICENSE.md.

Author

Philippe Gaultier philippe@blackcube.io