PHPackages                             publishlayer/laravel-connector - 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. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. publishlayer/laravel-connector

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

publishlayer/laravel-connector
==============================

Sync and render PublishLayer knowledge base content inside Laravel applications.

v0.2.0(3mo ago)04MITPHPPHP ^8.2CI failing

Since Feb 19Pushed 3mo agoCompare

[ Source](https://github.com/publishlayer/laravel-connector)[ Packagist](https://packagist.org/packages/publishlayer/laravel-connector)[ Docs](https://github.com/publishlayer/laravel-connector)[ RSS](/packages/publishlayer-laravel-connector/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (9)Versions (3)Used By (0)

PublishLayer Laravel Connector
==============================

[](#publishlayer-laravel-connector)

`publishlayer/laravel-connector` lets a Laravel application receive PublishLayer content, store it locally, and either render a hosted knowledge base or expose the synced content to a custom frontend.

It is a package, not a starter app. It ships with:

- authenticated sync and health endpoints
- hosted knowledge base views with publishable Blade templates
- optional headless mode for custom frontends
- canonical Markdown delivery with `llms.txt` discovery endpoints
- signed webhook handling for PublishLayer Inbox flows
- install, diagnostics, heartbeat, and demo-content commands

Compatibility
-------------

[](#compatibility)

- PHP: `^8.2`
- Laravel components: `^11.0|^12.0`
- Testbench coverage in CI:
    - PHP 8.2 + Laravel 11
    - PHP 8.3 + Laravel 11
    - PHP 8.4 + Laravel 12

Installation
------------

[](#installation)

```
composer require publishlayer/laravel-connector
php artisan publishlayer:install --publish-config --publish-migrations --publish-views
php artisan migrate
```

For a one-command local setup after publishing files:

```
php artisan publishlayer:install --migrate
```

Quick Start
-----------

[](#quick-start)

Add the core connector settings to `.env`:

```
PUBLISHLAYER_ENABLED=true
PUBLISHLAYER_MODE=hosted_views
PUBLISHLAYER_API_KEY=your-shared-sync-key
PUBLISHLAYER_SITE_ID=your-site-id
PUBLISHLAYER_ROUTE_PREFIX=knowledge
PUBLISHLAYER_API_PREFIX=api/publishlayer
PUBLISHLAYER_LAYOUT=layouts.app
```

Optional sync signing:

```
PUBLISHLAYER_SYNC_SIGNING_SECRET=your-hmac-secret
```

Optional Markdown and hosted UI settings:

```
PUBLISHLAYER_MARKDOWN_ENABLED=true
PUBLISHLAYER_MARKDOWN_ACCEPT_NEGOTIATION=true
PUBLISHLAYER_MARKDOWN_CACHE_TTL=300
PUBLISHLAYER_CATEGORY_OVERVIEW_LIMIT=6
PUBLISHLAYER_RELATED_ARTICLES_LIMIT=4
```

Smoke test the install:

```
php artisan publishlayer:health-check
php artisan publishlayer:seed-demo-content
```

Package Modes
-------------

[](#package-modes)

### Hosted views

[](#hosted-views)

`PUBLISHLAYER_MODE=hosted_views` registers:

- `GET /llms.txt`
- `GET /llms-full.txt`
- `GET /{route_prefix}`
- `GET /{route_prefix}/categories/{slug}`
- `GET /{route_prefix}/{slug}`
- `GET /{route_prefix}/{slug}.md`

The default route prefix is `knowledge`, so the category route becomes `/knowledge/categories/{slug}`.

### Headless

[](#headless)

`PUBLISHLAYER_MODE=headless` disables the hosted knowledge base and discovery routes. Sync, health, webhook, activity, heartbeat, and inbox routes stay available while the package is enabled.

Routes and Endpoints
--------------------

[](#routes-and-endpoints)

### Sync API

[](#sync-api)

These routes use the configured API middleware and are always available while `PUBLISHLAYER_ENABLED=true`:

- `GET /api/publishlayer/health`
- `POST /api/publishlayer/sync`
- `POST /api/publishlayer/webhook`

`POST /api/publishlayer/webhook` is a compatibility alias to the same sync controller used by `/sync`.

### Webhooks and connector telemetry

[](#webhooks-and-connector-telemetry)

These routes are separate from the sync API:

- `POST /publishlayer/webhook`
- `GET|POST /publishlayer/connector/activity`
- `GET|POST /publishlayer/activity`
- `POST /publishlayer/connector/heartbeat`
- `POST /publishlayer/heartbeat`

The webhook endpoint is protected by `PUBLISHLAYER_WEBHOOK_SECRET` and is used for inbox-style events such as `draft.ready`.

### Inbox routes

[](#inbox-routes)

Inbox routes are enabled by default and use the `publishlayer_inbox.php` config:

- Portal: `GET /app/content`
- Draft detail: `GET /app/content/{draft}`
- Approve draft: `POST /app/content/{draft}/approve`
- Publish draft: `POST /app/content/{draft}/publish`
- Public draft page: `GET /content/{slug}`

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

[](#configuration)

The package publishes three config files:

- `config/publishlayer.php`
- `config/publishlayer_connector.php`
- `config/publishlayer_inbox.php`

### Core connector settings

[](#core-connector-settings)

Use `config/publishlayer.php` for:

- package enablement
- hosted vs headless mode
- sync authentication
- route prefixes
- hosted view layout
- Markdown delivery
- pagination, labels, SEO, categories, and related articles

### PublishLayer API client settings

[](#publishlayer-api-client-settings)

Use `config/publishlayer_connector.php` for:

- `PUBLISHLAYER_BASE_URL`
- `PUBLISHLAYER_WORKSPACE_ID`
- `PUBLISHLAYER_CLIENT_SITE_ID`
- `PUBLISHLAYER_SITE_KEY`
- `PUBLISHLAYER_TIMEOUT`
- `PUBLISHLAYER_CONNECTOR_PUBLIC_URL`
- `PUBLISHLAYER_WEBHOOK_SECRET`
- webhook header and queue settings
- image download behavior
- schema cache behavior

Legacy `PL_CONNECTOR_*` environment variables are still accepted for existing installs, but new public installs should use the `PUBLISHLAYER_*` names.

### Inbox settings

[](#inbox-settings)

Use `config/publishlayer_inbox.php` for:

- `PUBLISHLAYER_INBOX_ENABLED`
- `PUBLISHLAYER_INBOX_PORTAL_PREFIX`
- `PUBLISHLAYER_INBOX_PORTAL_MIDDLEWARE`
- `PUBLISHLAYER_INBOX_PUBLIC_PATH`
- `PUBLISHLAYER_INBOX_IMAGE_PATH_PREFIX`

`PUBLISHLAYER_INBOX_ENABLED` is the global default. Per-site overrides can still be stored in `publishlayer_settings`.

Authentication Model
--------------------

[](#authentication-model)

### Sync and health endpoints

[](#sync-and-health-endpoints)

The sync middleware accepts any of the following:

- `X-PublishLayer-Key: {api key}`
- the configured `PUBLISHLAYER_AUTH_HEADER`
- `Authorization: Bearer {api key}`
- HMAC signatures using `PUBLISHLAYER_SYNC_SIGNING_SECRET`

If `PUBLISHLAYER_SITE_ID` is set, incoming `site_id` values must match exactly.

### Signed webhook endpoint

[](#signed-webhook-endpoint)

`POST /publishlayer/webhook` requires:

- `X-PublishLayer-Timestamp`
- `X-PublishLayer-Signature`
- a body signature generated from `{timestamp}.{raw_body}` with `PUBLISHLAYER_WEBHOOK_SECRET`

Markdown Support
----------------

[](#markdown-support)

When `publishlayer.markdown.enabled` is on:

- `GET /knowledge/{slug}.md` returns canonical Markdown
- `GET /knowledge/{slug}` can return Markdown when `Accept: text/markdown`
- `/llms.txt` and `/llms-full.txt` expose discovery documents

Markdown is only served for locally published articles. The package fetches site-scoped Markdown from PublishLayer, caches it locally, and serves stale cache entries when the upstream API is temporarily unavailable.

Sync Payload
------------

[](#sync-payload)

Minimal working sync payload:

```
{
  "type": "knowledge_article",
  "site_id": "client-site-id",
  "article": {
    "id": "article-uuid",
    "title": "Example title",
    "slug": "example-title",
    "summary": "Short summary",
    "content_html": "Trusted synced HTML",
    "status": "published"
  }
}
```

Supported article statuses:

- `published`
- `draft`
- `archived`
- `unpublished`
- `deleted`
- `reference`

The sync service also accepts optional category and related-article payloads.

Minimal Working Example
-----------------------

[](#minimal-working-example)

```
composer require publishlayer/laravel-connector
php artisan publishlayer:install --publish-config --publish-migrations --publish-views
php artisan migrate
php artisan publishlayer:seed-demo-content
php artisan publishlayer:health-check
```

Then open `/knowledge` in hosted mode or start sending signed sync requests to `/api/publishlayer/sync`.

Typical Integration Flow
------------------------

[](#typical-integration-flow)

1. Install the package and run migrations.
2. Set `PUBLISHLAYER_API_KEY` and `PUBLISHLAYER_SITE_ID`.
3. Choose `hosted_views` or `headless`.
4. If you use inbox-style webhooks, set `PUBLISHLAYER_WEBHOOK_SECRET`.
5. Configure PublishLayer to send article sync payloads to `/api/publishlayer/sync`.
6. Optionally configure signed draft-ready webhooks at `/publishlayer/webhook`.
7. Run `php artisan publishlayer:health-check` to verify the install.

View Overrides
--------------

[](#view-overrides)

Publish the package views:

```
php artisan vendor:publish --tag=publishlayer-connector-views
```

Override them under:

- `resources/views/vendor/publishlayer/knowledge`
- `resources/views/vendor/publishlayer/inbox`

The hosted knowledge templates extend `config('publishlayer.layout', 'layouts.app')`.

Commands
--------

[](#commands)

- `php artisan publishlayer:install`
- `php artisan publishlayer:health-check`
- `php artisan publishlayer:seed-demo-content`
- `php artisan publishlayer:doctor`
- `php artisan publishlayer:webhooks:register`
- `php artisan publishlayer:heartbeat`
- `php artisan pl-inbox:toggle {siteKey} {on|off}`

Troubleshooting
---------------

[](#troubleshooting)

- `PublishLayer sync authentication is not configured.`Set `PUBLISHLAYER_API_KEY` or `PUBLISHLAYER_SYNC_SIGNING_SECRET`.
- `The provided site_id [...] does not match the configured PublishLayer site [...]`Align the inbound `site_id` with `PUBLISHLAYER_SITE_ID`.
- `PublishLayer webhook signing secret is not configured.`Set `PUBLISHLAYER_WEBHOOK_SECRET` before accepting signed webhooks.
- Hosted routes return `404`Confirm `PUBLISHLAYER_ENABLED=true` and `PUBLISHLAYER_MODE=hosted_views`.
- Markdown route returns `404`Confirm the article is locally published and `PUBLISHLAYER_MARKDOWN_ENABLED=true`.

Upgrading
---------

[](#upgrading)

This is the first public release line. Future upgrade notes and breaking changes will be recorded in this README and in `CHANGELOG.md`.

Contributing
------------

[](#contributing)

See `CONTRIBUTING.md` for local setup and pull request expectations.

License
-------

[](#license)

MIT. See `LICENSE`.

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance81

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity38

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

Every ~32 days

Total

2

Last Release

103d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/086bc460ba6810a4e29259a3e7eb64e3a4af0525bcaea87e1b967208a97a0b3b?d=identicon)[publishlayer](/maintainers/publishlayer)

---

Tags

laravelmarkdownwebhooksKnowledge Basepublishlayer

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/publishlayer-laravel-connector/health.svg)

```
[![Health](https://phpackages.com/badges/publishlayer-laravel-connector/health.svg)](https://phpackages.com/packages/publishlayer-laravel-connector)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M131](/packages/roots-acorn)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k30.0M148](/packages/laravel-cashier)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M151](/packages/laravel-mcp)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M132](/packages/laravel-pulse)[api-platform/laravel

API Platform support for Laravel

58171.8k14](/packages/api-platform-laravel)

PHPackages © 2026

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