The CWA is in heavy development
The CWA is still in alpha and not ready for production - some code and implementations are likely to change. If you would like to try out the CWA, please enjoy what we have provided and feel free to provide feedback, or get involved on GitHub.
Api

Console Commands

Symfony console commands provided by the API Components Bundle for managing users, cleaning up data, and generating component entities.

Most commands use the silverback:api-components: prefix. Run them via the Symfony console:

php bin/console silverback:api-components:<command>

In a Docker Compose setup, prefix with the service name:

docker compose exec api php bin/console silverback:api-components:<command>

user:create

Create a user account directly from the command line, without going through the registration API. Useful for creating the first admin on a fresh installation before the front-end is set up.

php bin/console silverback:api-components:user:create

The command prompts interactively for username, email, and password. You can also pass them as positional arguments:

php bin/console silverback:api-components:user:create alice alice@example.com s3cr3t --admin

Options

OptionDescription
--adminCreate with ROLE_ADMIN
--super-adminCreate with ROLE_SUPER_ADMIN
--inactiveCreate as disabled (cannot log in until enabled)
--overwriteUpdate the user if they already exist instead of erroring

Without --admin or --super-admin, the user is created with ROLE_USER only.

refresh-tokens:expire

Expire all refresh tokens, or all tokens for a specific user. Use this to force re-login after a security incident or account change.

# Expire all tokens for all users
php bin/console silverback:api-components:refresh-tokens:expire

# Expire tokens for one user (by username)
php bin/console silverback:api-components:refresh-tokens:expire alice

# Expire by email instead of username
php bin/console silverback:api-components:refresh-tokens:expire alice@example.com --field email

clean-orphaned

Scan every ComponentGroup and AbstractComponent in the database and delete any that are no longer attached to any layout, page, or parent component.

php bin/console silverback:api-components:clean-orphaned

Run this after bulk deletions or data migrations to keep the database tidy. The command outputs a progress bar and reports how many orphaned records were removed.


Maker Commands

These commands use the standard make: prefix from Symfony MakerBundle and are only registered when MakerBundle is installed.

make:api-component

Generate a new AbstractComponent entity with the correct namespace, attributes, and optional behaviour traits wired up automatically.

php bin/console make:api-component

The command prompts interactively for the class name and which behaviours to add. You can also pass everything as arguments:

php bin/console make:api-component HeroBlock --timestamped --publishable

Options

  • --timestamped — Add #[Timestamped]: generates createdAt / updatedAt columns via TimestampedTrait
  • --publishable — Add #[Publishable]: wires up the draft/publish lifecycle via PublishableTrait
  • --uploadable — Add #[Uploadable]: includes a $file property and UploadableTrait for file handling

Example output (with all three flags)

#[Silverback\Timestamped]
#[Silverback\Publishable]
#[Silverback\Uploadable]
#[ApiResource]
#[ORM\Entity]
class HeroBlock extends AbstractComponent
{
    use TimestampedTrait;
    use PublishableTrait;
    use UploadableTrait;

    #[Silverback\UploadableField(adapter: 'local')]
    public ?File $file = null;
}

After generation, run make:migration and review the generated SQL before executing it — the traits add columns and (for publishable) self-referencing foreign keys.

make:page-data

Generate a new AbstractPageData entity with typed properties pre-wired, plus console output showing the matching nuxt.config snippet and fixture stub.

php bin/console make:page-data

The command prompts interactively for the class name and properties. You can pass everything inline:

php bin/console make:page-data ConferenceData --properties headline:?string body:?string heroImage:?string

Properties are defined as name:type pairs. Nullable types use the ? prefix.

Example output

#[ApiResource]
#[ORM\Entity]
class ConferenceData extends AbstractPageData
{
    #[ORM\Column(nullable: true)]
    public ?string $headline;

    #[ORM\Column(nullable: true)]
    public ?string $body;

    #[ORM\Column(nullable: true)]
    public ?string $heroImage;
}

After generation the command prints:

  • The nuxt.config.ts cwa.pageData.ConferenceData.properties snippet to add human-readable labels for the admin picker
  • A fixture scaffold stub: $cwa->pageData(new ConferenceData(), template: 'my-template')
  • ->pageDataPosition(ConferenceData::class, 'propertyName') calls for each property, ready to paste into a template group

After generation, run make:migration and review the generated SQL before executing it.

make:cwa-scaffold

Generate a starter AbstractCwaScaffold subclass pre-wired with a layout, a home page, and commented-out nav link stubs.

php bin/console make:cwa-scaffold

The command prompts interactively for the class name, layout reference key, and layout UI component name. You can pass everything inline:

php bin/console make:cwa-scaffold AppScaffold --layout-ref main --layout-component CwaLayoutPrimary

Options

OptionDefaultDescription
--layout-refmainReference key passed to $cwa->layout()
--layout-componentCwaLayoutPrimaryUI component name for the layout

Example output

class AppScaffold extends AbstractCwaScaffold
{
    public function build(CwaFixtureBuilder $cwa): void
    {
        $navGroup = $cwa->layout('main', 'CwaLayoutPrimary')
            ->group('top');

        $cwa->page('home', 'PrimaryPageTemplate', layout: 'main', route: '/', routeName: 'home-page',
            configure: fn (PageBuilder $page) => $page
                ->title('Home')
                ->group('primary')
        );

        // $navGroup->add(...) — nav links go here after routes exist
    }
}

After generation the command prints the config/services.yaml snippet to register the class as a Doctrine fixture:

App\DataFixtures\AppScaffold:
    tags: [doctrine.fixture.orm]

Then run php bin/console doctrine:fixtures:load to seed the database. See Data Fixtures for the full builder API.