PHPackages                             n-ramos/celebrimbor-bundle - 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. [Database &amp; ORM](/categories/database)
4. /
5. n-ramos/celebrimbor-bundle

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

n-ramos/celebrimbor-bundle
==========================

Symfony bundle connecting a Doctrine entity to the Celebrimbor visual page builder, with interface contracts and a Doctrine trait for the model, a Form type wired to Symfony UX/Stimulus, and a Twig per-block preview renderer.

v0.1.0(today)00MITPHPPHP ^8.2CI passing

Since Jun 9Pushed todayCompare

[ Source](https://github.com/n-ramos/celebrimbor-bundle)[ Packagist](https://packagist.org/packages/n-ramos/celebrimbor-bundle)[ RSS](/packages/n-ramos-celebrimbor-bundle/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (13)Versions (2)Used By (0)

Celebrimbor Bundle
==================

[](#celebrimbor-bundle)

Symfony bundle that connects a Doctrine entity to the [Celebrimbor](https://github.com/n-ramos/celebrimbor) headless visual page builder. It ships **no blocks** — you bring your own JS block registry. The bundle provides the PHP plumbing:

- a **contract** (`HasPageBuilderContent`) + **Doctrine trait** for your model,
- a **Form type** (`PageBuilderType`) wired to the Symfony UX / Stimulus controller from [`@n-ramos/celebrimbor-symfony`](https://www.npmjs.com/package/@n-ramos/celebrimbor-symfony),
- a **per-block Twig preview renderer** (`CelebrimborRenderer`) and an `AbstractPreviewController` you extend with a single route.

The JavaScript half (the `` web component, the Stimulus controller, your block registry) lives in the npm package `@n-ramos/celebrimbor-symfony`, installed via AssetMapper/importmap.

Install
-------

[](#install)

```
composer require n-ramos/celebrimbor-bundle
php bin/console importmap:require @n-ramos/celebrimbor-symfony
```

Register your blocks once in your AssetMapper entry (e.g. `assets/app.js`):

```
import { defineCelebrimbor } from "@n-ramos/celebrimbor-symfony";
import "@n-ramos/celebrimbor-symfony/styles.css";
import { createBlockRegistry } from "@n-ramos/celebrimbor-core";

const registry = createBlockRegistry();
// registry.register(myHeroBlock); ...
defineCelebrimbor({ registry });
```

1. The model
------------

[](#1-the-model)

Implement the contract and use the trait. The trait maps a nullable JSON `document` column and stores the editor payload raw.

```
use Doctrine\ORM\Mapping as ORM;
use NRamos\CelebrimborBundle\Concern\InteractsWithPageBuilderContent;
use NRamos\CelebrimborBundle\Contract\HasPageBuilderContent;

#[ORM\Entity]
class Page implements HasPageBuilderContent
{
    use InteractsWithPageBuilderContent;

    // ... your own id, title, slug, etc.
}
```

Override `pageBuilderFormat()` to return `PageBuilderFormat::Document` if you store the full `PageDocument` instead of the default portable block list.

2. The form
-----------

[](#2-the-form)

```
use NRamos\CelebrimborBundle\Form\PageBuilderType;

$builder->add('document', PageBuilderType::class, [
    // 'format' => PageBuilderFormat::Document,
    'preview_url' => $this->generateUrl('admin_page_preview', ['id' => $page->getId()]),
]);
```

The field renders `` with the `celebrimbor--page-builder`Stimulus controller and transforms the document array ⇄ JSON automatically. The bundle auto-registers its form theme; if you disabled auto theming, add `@Celebrimbor/form/celebrimbor_form_theme.html.twig` to `twig.form_themes`.

3. The preview
--------------

[](#3-the-preview)

A preview is just a controller calling the bundle. Two strategies:

```
use NRamos\CelebrimborBundle\Preview\AbstractPreviewController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class PagePreviewController extends AbstractPreviewController
{
    #[Route('/admin/pages/{id}/preview', name: 'admin_page_preview')]
    public function __invoke(Page $page): Response
    {
        // A) Native Twig — one template per block (blocks/.html.twig):
        return $this->renderPreview($page);

        // B) Same JS renderer as the editor (faithful to production):
        // return $this->renderJsPreview($page);
    }
}
```

For strategy **A**, create one template per block type under your configured prefix (default `blocks/`), e.g. `templates/blocks/hero.html.twig`:

```

    {{ title }}
    {{ subtitle }}
    {{ children }}

```

Each block template receives the block fields spread at top level, plus `fields`, `settings`, `children` (pre-rendered) and `block`.

For strategy **B**, override `templates/bundles/CelebrimborBundle/preview/js_preview.html.twig` to add an AssetMapper entry that calls `mountCelebrimborPreview({ registry })`.

Configuration
-------------

[](#configuration)

```
# config/packages/celebrimbor.yaml
celebrimbor:
    default_format: portable          # portable | document
    blocks_template_prefix: blocks    # /.html.twig
    render_missing_comment: false     # emit an HTML comment for unmapped blocks
```

License
-------

[](#license)

MIT.

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/073baf600fe8a476ff667b4fccd359a79c0944c94c7809323a19f8e50d4a8c3e?d=identicon)[nramos](/maintainers/nramos)

---

Tags

celebrimbordoctrinepage-builderstimulussymfonysymfony-bundlesymfony-uxsymfonysymfony-uxdoctrineSymfony Bundlepage builderstimuluscelebrimbor

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/n-ramos-celebrimbor-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/n-ramos-celebrimbor-bundle/health.svg)](https://phpackages.com/packages/n-ramos-celebrimbor-bundle)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
