PHPackages                             duon/cms - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. duon/cms

ActiveLibrary[Framework](/categories/framework)

duon/cms
========

Duon content management system and framework

0.1.0-beta.2(3mo ago)089[1 PRs](https://github.com/duonrun/cms/pulls)1MITPHPPHP ^8.5CI failing

Since Feb 1Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/duonrun/cms)[ Packagist](https://packagist.org/packages/duon/cms)[ Docs](https://duon.run/cms)[ RSS](/packages/duon-cms/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (12)Versions (4)Used By (1)

Duon Content Management Framework
=================================

[](#duon-content-management-framework)

> **Note**: This library is under active development, some of the listed features are still experimental and subject to change. Large parts of the documentation are missing.

Defining content types
----------------------

[](#defining-content-types)

Content types (nodes) are plain PHP classes annotated with attributes. There is no base class to extend. Dependencies are autowired from the Registry via `duon/wire`.

```
use Duon\Cms\Field\Text;
use Duon\Cms\Field\Grid;
use Duon\Cms\Field\Image;
use Duon\Cms\Field\Meta\Label;
use Duon\Cms\Field\Meta\Required;
use Duon\Cms\Field\Meta\Translate;
use Duon\Cms\Cms;
use Duon\Cms\Schema\Name;
use Duon\Cms\Schema\Route;
use Duon\Cms\Node\Contract\Title;
use Duon\Core\Request;

#[Name('Department'), Route('/{title}')]
final class Department implements Title
{
    public function __construct(
        protected readonly Request $request,
        protected readonly Cms $cms,
    ) {}

    #[Label('Title'), Required, Translate]
    public Text $title;

    #[Label('Content'), Translate]
    public Grid $content;

    #[Label('Image')]
    public Image $clipart;

    public function title(): string
    {
        return $this->title?->value()->unwrap() ?? '';
    }
}
```

### Derived behavior

[](#derived-behavior)

SignalBehavior`#[Route('...')]` is presentNode is routable and has URL path settings`#[Render('...')]` is presentExplicit renderer id is used`#[Render]` is absentNode handle is used as renderer id### Metadata attributes

[](#metadata-attributes)

AttributePurpose`#[Name('...')]`Human-readable display name`#[Handle('...')]`URL-safe identifier (auto-derived if omitted)`#[Route('...')]`URL pattern for routable nodes`#[Render('...')]`Template name override`#[Title('...')]`Field name to use as title`#[FieldOrder('...')]`Admin panel field order`#[Deletable(false)]`Prevent deletion in admin panel (default: `true`)### Behavioral interfaces

[](#behavioral-interfaces)

InterfaceMethodPurpose`Title``title(): string`Computed title (takes precedence over `#[Title]`)`HasInit``init(): void`Post-hydration initialization hook`HandlesFormPost``formPost(?array $body): Response`Frontend form submission handling`ProvidesRenderContext``renderContext(): array`Extra template variables### Rendering by uid

[](#rendering-by-uid)

Render a node by uid from templates with the neutral cms API:

```
