Installation
This walks through a fresh composer require to publishing your first page, using a Hero component as the running example.
1. Install the package
composer require wearepixel/inlay
2. Run the installer
php artisan inlay:install
This publishes config/inlay.php and runs php artisan migrate, creating the pages, page_sections, and page_revisions tables. If you'd rather run these individually:
php artisan vendor:publish --tag=inlay-config
php artisan migrate
3. Register the admin routes
Inlay registers no routes on its own. Add one line to your own routes/web.php, after your application's own routes:
use WearePixel\Inlay\Facades\Inlay;
Inlay::routes();
This registers the packaged admin - page index, page creation, the page editor, and the preview endpoint - under config('inlay.route_prefix') (inlay by default, so /inlay/pages, /inlay/pages/create, and so on). Visit /inlay/pages and you should see an empty page index - there's nothing to compose yet, because no component is registered.
4. Set your admin middleware
Open config/inlay.php:
'middleware' => ['web'],
Stop here if your application has real content or real users. ['web'] alone means anyone who can reach your application can create, edit, and delete pages - Inlay has no authentication or authorization of its own, by design. At minimum:
'middleware' => ['web', 'auth'],
If your application uses Laravel's default auth guard and a login named route, this is enough to require a logged-in user. Layer in your own authorization if not every authenticated user should manage pages:
'middleware' => ['web', 'auth', 'can:manage-pages'],
where manage-pages is a Gate::define() or policy ability your application already defines - Inlay just needs a middleware name Laravel understands.
You don't need to do anything else to make this middleware apply to every admin action, not just the first page load. Inlay::routes() registers it as Livewire persistent middleware automatically, so it re-runs on the /livewire/update requests that every subsequent edit, publish, and reorder is dispatched through - not just the initial page load.
5. Write your first component
A component is a normal Blade class component that implements InlayComponent, a marker interface with no required methods:
// app/Inlay/Components/Hero.php
namespace App\Inlay\Components;
use Illuminate\View\Component;
use Illuminate\View\View;
use WearePixel\Inlay\Attributes\ComponentMeta;
use WearePixel\Inlay\Attributes\Text;
use WearePixel\Inlay\Contracts\InlayComponent;
#[ComponentMeta(label: 'Hero', category: 'Headers', description: 'A page heading with introductory copy.')]
final class Hero extends Component implements InlayComponent
{
public function __construct(
#[Text(label: 'Heading', maxLength: 80)]
public string $heading = 'Welcome',
#[Text(label: 'Subheading')]
public string $subheading = '',
) {}
public function render(): View
{
return view('components.hero');
}
}
{{-- resources/views/components/hero.blade.php --}}
<section class="hero">
<h1>{{ $heading }}</h1>
@if ($subheading)
<p>{{ $subheading }}</p>
@endif
</section>
Register it by handle in config/inlay.php:
'sections' => [
'hero' => \App\Inlay\Components\Hero::class,
],
The handle (hero) is what gets persisted against a page's sections, never the class name directly - renaming or moving the class later doesn't break existing pages. Reload /inlay/pages to confirm it's picked up (run php artisan config:clear first if config is cached in this environment).
6. Configure the preview
The editor's preview pane is a real iframe pointed at your own frontend. Tell Inlay which of your views renders a composition:
// app/Providers/AppServiceProvider.php
use WearePixel\Inlay\Facades\Inlay;
public function boot(): void
{
Inlay::previewView('inlay-previews.default');
}
{{-- resources/views/inlay-previews/default.blade.php --}}
<x-app-layout>
{{ $composition }}
</x-app-layout>
Your view receives $page (the Page being previewed), $composition (an Htmlable of the rendered components - safe to echo directly), and $context (reserved for future use, currently always null). If you skip this step, the preview pane still works - it falls back to a plain, clearly-labeled unstyled wrapper rather than silently pretending to be your real design.
7. Create and publish your first page
- Visit
/inlay/pagesand click New page. Give it a title - a slug is generated automatically. - In the editor, click + Add, choose Hero from the picker, and edit its heading in the settings sidebar.
- Watch the preview pane update.
- Click Publish.
8. Render it on your site
Inlay doesn't register a public route for you - wire the page into your own routing however you already do:
// routes/web.php
use WearePixel\Inlay\Models\Page;
Route::get('/{page:slug}', function (Page $page) {
return view('pages.show', ['page' => $page]);
});
{{-- resources/views/pages/show.blade.php --}}
<x-app-layout>
<x-inlay::render :page="$page" />
</x-app-layout>
Visit the page's slug on your site and you should see the published Hero component, styled by your own application's CSS - not Inlay's.
Next steps
- Registering components - the full component-authoring reference.
- The editor - the editor-facing workflow.
- Current limitations - what this release deliberately doesn't include yet.