layr/builder

Layr page builder package for TypiCMS pages

Maintainers

Package info

gitlab.com/blestonbandeira/layr

Issues

Documentation

pkg:composer/layr/builder

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

Stars: 0


README

Layr is a reusable TypiCMS package that turns a TypiCMS page into a fully editable visual page, letting projects control the public look and layout of that page without baking host-specific code into the package.

What the package owns

  • page builder UI inside the TypiCMS page form
  • a configurable layr page template for public rendering
  • migrations for the builder payload fields on pages
  • package-served built assets, so the host app does not need custom Vite entries
  • configurable dynamic content sources for CMS-powered cards and carousels

Install

Preferred once the package is published to Packagist:

composer require layr/builder:^0.1
php artisan migrate

If you are installing from the GitLab repository before the first public release, use the VCS workflow below.

Install From GitLab Before Packagist

composer require layr/builder:dev-main
php artisan migrate

Compatibility:

  • TypiCMS Core 17.0+
  • PHP 8.4+

Optional:

php artisan vendor:publish --tag=layr-config

When upgrading an existing install, run php artisan migrate so the compiled public payload fields are added to pages.

Composer VCS example:

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://gitlab.com/blestonbandeira/layr.git"
        }
    ],
    "require": {
        "layr/builder": "dev-main"
    }
}

If you tag releases, prefer a version constraint such as ^0.1.

Once the package is public on Packagist, you can remove the custom repositories entry and require the tagged version directly.

After install:

  1. Open a page in TypiCMS admin.
  2. Set the page template to Layr.
  3. Build the page in the Layr panel.
  4. Save the page.

Host app contract

This package is intended to be drop-in for a stock TypiCMS installation with the standard pages module views.

The package overrides the pages view namespace to provide a thinner page integration:

  • pages::admin.create
  • pages::admin.edit
  • pages::public.layr

The admin wrappers delegate back to the original TypiCMS page form through the internal layr-pages-core namespace and then append the Layr builder panel.

If the host app already overrides pages::admin.create or pages::admin.edit, the app override will still win. In that case, include Layr using one of these partials:

  • layr::admin.page-form._integrated-form when you want the stock TypiCMS page form plus Layr
  • layr::admin.page-form._builder-panel when your host app already owns the surrounding page form markup

Layr keeps the editable builder HTML and CSS as authoring source, and compiles a sanitized public payload for frontend rendering. The builder should still only be exposed to trusted page editors, especially if you configure fixed sections that render host-defined Blade views.

Host Integration Examples

Host app owns the create or edit wrapper and wants the stock TypiCMS form plus Layr:

{!! BootForm::open()->put()->action(route('admin::update-page', $model->id))->addClass('main-content') !!}
{!! BootForm::bind($model) !!}
@include('layr::admin.page-form._integrated-form', ['model' => $model])
{!! BootForm::close() !!}

Host app already owns the surrounding form markup and only wants the Layr panel:

<div class="custom-page-editor">
    @include('layr::admin.page-form._builder-panel', [
        'model' => $model,
        'wrapperClass' => 'mt-3',
    ])
</div>

Host app defines public page wrapper content around Layr:

'public_page' => [
    'wrapper_class' => 'landing-shell',
    'before_content_view' => 'site.pages.layr.before',
    'after_content_view' => 'site.pages.layr.after',
],

Host app defines fixed sections without editing Layr internals:

'fixed_sections' => [
    'templates' => [
        'layr' => [
            [
                'key' => 'hero',
                'label' => 'Hero',
                'view' => 'site.pages.fixed.hero',
            ],
        ],
    ],
],

Architecture

Layr is intentionally split into package-owned services plus a TypiCMS adapter layer:

  • src/Support, src/Models, src/Contracts, config, database, and resources contain package behavior
  • src/TypiCms contains the TypiCMS-specific integration points such as page-form requests, page rendering, and page import workflows
  • Layr\Contracts\LocaleContext centralizes locale assumptions that would otherwise be hidden behind host helpers

There is a package-side architecture plan in docs/architecture-roadmap.md. There is a follow-up execution plan for the remaining platform work in docs/ideal-state-execution-plan.md. There is a visual redesign execution plan in docs/visual-redesign-execution-plan.md. There is an editor-shell rebuild plan in docs/editor-v2-roadmap.md.

Visual release gate

Layr now ships with a lightweight visual regression gate for the redesign workstream.

Package-level checks:

  • npm run check
  • npm run check:preview
  • npm run check:visual-fixtures
  • npm run check:visual-canvas
  • npm run check:visual-dynamic

Public screenshot capture:

  • npm run capture:visual-fixtures:public

What each command covers:

  • check:preview: source and built iframe sizing safeguards for the builder canvas
  • check:visual-fixtures: baseline screenshot presence and minimum image dimensions
  • check:visual-canvas: admin builder and device-frame geometry from the trusted baseline metadata
  • check:visual-dynamic: public dynamic books grid and carousel structure, plus placeholder-copy leaks
  • capture:visual-fixtures:public: regenerates the public visual fixtures into output/visual-fixtures/public-latest/

Current limitation:

  • Public route automation is package-owned and repeatable today.
  • Authenticated admin screenshot capture still requires a host session and remains a manual smoke test before a release candidate is tagged.

Recommended release flow for visual changes:

  1. Run the package checks above in Layr.
  2. Rebuild assets with npm run build.
  3. Regenerate public fixtures with npm run capture:visual-fixtures:public when the public rendering changed.
  4. In the host app, smoke-test the authenticated builder: page load, drag/drop, keyboard insert, save, reload, and dark theme readability.
  5. Only tag a release candidate after both the automated checks and the host smoke test pass.

Admin dark-theme accent

Layr keeps the admin shell surfaces neutral and lets the host app override the dark-theme accent color.

Default package value:

'admin_theme' => [
    'dark' => [
        'accent' => '#8fb4ff',
    ],
],

Host override example:

'admin_theme' => [
    'dark' => [
        'accent' => '#6d28d9',
    ],
],

Layr derives the active text color and soft accent states from that one value, so hosts can match their brand without turning the builder into a full theme editor.

Dynamic content sources

Dynamic cards and dynamic carousels are driven by config/layr.php.

Example:

'dynamic_sources' => [
    'books' => [
        'label' => 'Books',
        'permission' => 'read books',
        'model' => \TypiCMS\Modules\Books\Models\Book::class,
        'with' => ['image'],
        'public_scope' => 'published',
        'title_field' => 'title',
        'subtitle_field' => 'summary',
        'translated_title' => true,
        'translated_subtitle' => true,
        'image_relation' => 'image',
        'image_attribute' => 'url',
        'url_method' => 'url',
        'edit_url_method' => 'editUrl',
        'browse_route' => '{locale}::index-books',
        'sort_column' => 'updated_at',
    ],
],

Fields:

  • label: source label shown in the editor
  • permission: optional additional admin permission for that source; Layr already requires update pages before the builder APIs can access any source
  • model: Eloquent model class
  • with: relations to eager load
  • public_scope: optional scope applied when rendering public-facing dynamic blocks
  • title_field / subtitle_field: fields used in picker cards
  • translated_title / translated_subtitle: whether to use TypiCMS translations when available
  • image_relation / image_attribute: how preview images are resolved
  • url_method: public URL method for rendered cards
  • edit_url_method: admin edit URL method for picker actions
  • browse_route: optional route name, with {locale} placeholder support
  • sort_column: column used for recent ordering

Public Sanitization

Layr sanitizes the compiled public HTML and CSS before rendering:

  • dangerous tags like script, style, object, embed, and form are removed
  • inline event handlers are removed
  • links, media sources, and iframe sources are scheme-checked
  • inline styles and stylesheets are filtered to remove dangerous CSS tokens such as expression(...), javascript:, and @import

For iframe-based embeds, configure the allowed hosts in config/layr.php:

'sanitizer' => [
    'allowed_iframe_hosts' => [
        'www.youtube.com',
        'youtube.com',
        'www.youtube-nocookie.com',
        'youtube-nocookie.com',
        'player.vimeo.com',
    ],
],

Frontend build

End users do not need Node or a host-app Vite entry. The package serves its own built assets from dist/.

When maintaining the package:

npm install
npm run build

Layr's package build currently requires Node.js 20.19.0+ or 22.12.0+.

That produces:

  • dist/admin.js
  • dist/admin.css
  • dist/public.css

Package Tests

Layr owns its own PHP unit tests:

composer install
composer test

The tests run against a lightweight in-memory testbench setup inside the package, while the smoke test still verifies the full install flow against a fresh TypiCMS application.

Package Verification

Run the package verification flow from the Layr repo:

bash scripts/ci/verify-package.sh

This runs Composer validation, the package test suite, the frontend build, and the smoke install when PHP ext-redis is available.

The verification flow expects Node.js 20.19.0+ or 22.12.0+ for the frontend build step.

For host-app upgrade guidance, see UPGRADING.md.

Smoke Test

To verify Layr against a fresh stock TypiCMS app:

./scripts/ci/smoke-typicms.sh

That script creates a temporary TypiCMS install, requires Layr through a local path repository, migrates, and checks the install, page form integration, save request binding, and public render path.

Note: the stock TypiCMS bootstrap currently expects the PHP redis extension during package discovery, so the smoke app should run in an environment where ext-redis is available.