Dollie Editor SDK guide
Publishing and Discovery
Render publication snapshots and wire archives, SEO, images and Copilot scope.
Save updates the draft. PostManager::publish($post, $revision) validates it and copies
its metadata and body into publication. The original publication date is retained;
publication_updated_at records the latest publish. Unpublish clears the snapshot and
publication timestamps. Each successful mutation advances the revision.
Public rendering
Use PostQueries::published($slug) to load a published post. Render $post->publication
with your article layout and the same catalogue used for editing. Render the public header
from snapshot metadata and the body with SectionRenderer; the stored body excludes the
synthetic editor header.
Never render the current draft columns just because published_at is set. They may contain
private edits made after publication.
Archive and management queries
PostQueries::archive($filters) returns posts (a paginator), filters, categories,
tags, and months. All archive content and taxonomy come from publication snapshots.
Only posts with a publication and a publication date at or before now are included.
| Query | Options |
|---|---|
| Public archive | category, tag, month (YYYY-MM), page |
| Admin list | search (title), status (all, draft, published), category, sort (title, published_at, updated_at), direction (asc, desc), per_page (10, 20, 50), page |
Admin results expose draft metadata, so authorize the listing and scope its repository. They include featured-image URLs and dates for a host-owned table. The adapter supplies queries and pagination; it does not ship the management table or public archive UI.
SEO and social sharing
PostPublication::metadata($post, $postUrl, $imageCallback, $publisher) returns:
title, canonical, description, image, imageAlt, and a BlogPosting schema array.
Pass those values to your application's head manager.
SEO overrides live in seo.title, seo.description, seo.canonicalUrl, and seo.image.
Without an override, the title uses the post title; description uses the excerpt or a short
plain-text summary of body content fields. The image falls back to the cover or a body
section's src. Your callback supplies its final URL. The host supplies the publisher's
identity; the package does not assume an author or organization.
$metadata = $publication->metadata(
$post,
route('blog.show', $post->publication['slug']),
fn ($src, $width) => url($images->url($src, width: $width)),
['@type' => 'Organization', 'name' => config('app.name'), 'url' => url('/')],
);
This example assumes your own $images service. The adapter does not depend on a particular
image processor or automatically emit <head> tags.
Images and sitemaps
PostPublication::render($snapshot, $rewriteDefinition, $imageUrl, $width = 1600) calls the
host's definition-rewriter and image service for body/featured images. It returns rendering
data while leaving the stored original URLs and native image settings unchanged. The image
URL callback receives (source, width); the definition callback handles image sizing inside
body sections.
PostQueries::sitemap($urlForSlug) yields public URL → last-publication timestamp entries.
Posts canonicalized to a different URL are excluded. Merge those entries into your site's
sitemap and advertise it through your own robots endpoint. Draft saves do not change these
timestamps. No sitemap or robots routes are automatically added by the module.
Copilot and existing editor tools
The post canvas uses the same rich fields, catalog context, AI Fill and proposal/apply flow
as a page. Choose your agent, conversation store and streaming endpoint in the host.
Derive conversation scope with PostSession::id($authorizedPost), never with a post ID
provided only as an untrusted client session string. Reserve the post- namespace on
public/unrelated chat endpoints with PostSession::isPost().
PostPageStore implements the shared PageStore contract for post-{id}. A host
PageStoreResolver can route authorized post IDs to it while retaining existing stores for
pages and presentations. This enables the same page transport, MCP and Laravel AI operations
without a second tool vocabulary. The bridge does not add authorization: bind an appropriately
scoped repository and enforce read/write/publish permissions in the calling integration.