n2ns / laravel-post2site
Laravel backend package for the N2N Post2Site Content Publishing API Contract.
Fund package maintenance!
Requires
- php: ^8.2
- illuminate/bus: ^12.0 || ^13.0
- illuminate/console: ^12.0 || ^13.0
- illuminate/database: ^12.0 || ^13.0
- illuminate/hashing: ^12.0 || ^13.0
- illuminate/http: ^12.0 || ^13.0
- illuminate/queue: ^12.0 || ^13.0
- illuminate/routing: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
- illuminate/validation: ^12.0 || ^13.0
Requires (Dev)
- laravel/pint: ^1.18
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^11.5
Suggests
- austintoddj/canvas: Enables the POST2SITE_PRESET=austintoddj_canvas adapter for Canvas posts.
- bjuppa/laravel-blog: Enables the POST2SITE_PRESET=bjuppa_laravel_blog configurable publishing target.
- n2ns/laravel-saas-kit: Enables the POST2SITE_PRESET=laravel_saas_kit first-party adapter for SaaS Kit blog posts and product guides.
- stephenjude/filament-blog: Enables the POST2SITE_PRESET=stephenjude_filament_blog configurable publishing target.
README
Laravel backend package for the N2N Post2Site Content Publishing API Contract. It lets a Laravel site securely accept content from the n2n-post2site MCP client.
It provides protected publishing routes, package-owned staging tables for drafts and translations, optional configurable publishing into host Eloquent models, custom PublicationTarget adapters for complex sites, and optional IndexNow submission after posts are published.
The package is generic: content_scope is opaque kind:key metadata, and URL shape, scope validation, scope context, the publish target, and indexing are all host-bindable contracts. No host-specific categories are baked in.
For common sites, Post2Site can also be activated through presets. The first-party preset is laravel_saas_kit, which publishes into SaaS Kit's blog_posts and blog_post_translations tables and supports product guides through product:{code} content scopes.
๐ Requirements
- PHP 8.2+ with Laravel 12.
- PHP 8.3+ with Laravel 13.
The Composer constraints allow Laravel 12 and 13. The current locked test baseline validates Laravel 12; keep Laravel 13 host integrations under explicit project verification until a Laravel 13 CI matrix is added.
๐ Installation
composer require n2ns/laravel-post2site
php artisan vendor:publish --tag=post2site-config
php artisan migrate
php artisan post2site:key "Production MCP"
The command prints the plaintext API key once โ store it as the MCP client's CONTENT_API_KEY. Point the client's CONTENT_API_BASE_URL at https://your-host/<route_prefix> (default route prefix api/v1/mcp).
Configure the n2n-post2site MCP client to point at this host:
{
"mcpServers": {
"n2n-post2site": {
"command": "npx",
"args": ["-y", "n2n-post2site"],
"env": {
"CONTENT_API_BASE_URL": "https://your-host/api/v1/mcp",
"CONTENT_API_KEY": "the-key-printed-above"
}
}
}
}
๐ฐ Publishing modes
Set POST2SITE_PUBLISHING_MODE (or post2site.publishing.mode):
review(default) โ mark drafts published in the staging tables with zero host code. The publiclinkis generated frompublic_url.pattern.configurableโ map fields to a host Eloquent model via config; no PHP class needed.adapterโ bind a customPublicationTargetfor relations, taxonomy, external CMS, etc.
See the Host Integration Guide for each mode.
๐งฉ Blog targets
Current presets:
laravel_saas_kitโ first-party adapter. Supports blog posts and product guides. Target app currently uses Laravel 12.austintoddj_canvasโ adapter preset foraustintoddj/canvas.bjuppa_laravel_blogโ configurable preset forbjuppa/laravel-blog.stephenjude_filament_blogโ configurable preset forstephenjude/filament-blog5.x. Hosts still need to ensure author/category requirements fit their schema.
๐ Key behavior
- Auth โ database-driver API keys are stored as deterministic SHA-256 hashes and matched via a unique index (O(1)); the static driver compares a single configured key.
- Rate limiting โ every route is throttled. Tune via
POST2SITE_RATE_LIMIT(max,minutes, default60,1). - Search โ
?q=uses aFULLTEXTindex on MySQL/MariaDB (created by the migration on those drivers) and falls back toLIKEelsewhere (e.g. SQLite). - content_scope โ optional
kind:key; required for the types incontent.scoped_types(default['guide']) and prohibited for others. Kinds and key resolution are host-configurable.
๐งฉ Extension contracts
Bound from post2site.bindings and overridable: PostRepository, PublicationTarget, PublicUrlResolver, ContentScopeValidator, ScopeContextProvider, IndexingNotifier. See Architecture.
๐งช Testing
composer test # PHPUnit composer pint:test # code style
๐ฆ Composer Metadata
Packagist shows Composer link fields from composer.json:
- suggests โ optional packages that work with this package but are not required. Post2Site uses this for supported optional targets such as SaaS Kit, Canvas, and known blog packages.
- provides โ virtual packages implemented by this package. Post2Site does not currently implement a shared virtual package, so this stays empty.
- conflicts โ packages or versions that cannot be installed together with this package. Leave empty unless a real incompatibility is verified.
- replaces โ packages whose code is shipped/replaced by this package. Post2Site does not replace another package, so this stays empty.
๐ Documentation
๐ License
This project is licensed under the MIT License.
Built by N2NS Lab, an open-source lab for practical AI developer tools.