Administration
Einblick SDK In-Page Editing
Register external sites, understand framework support, and integrate Einblick in-page editing without breaking SSR or host-site caching.
Einblick SDK In-Page Editing
Open System Settings → API to register external sites, manage allowed origins, and copy the publishable site key used by the in-page editing runtime.
Framework support
@einblick/sdkis framework-agnostic. Use it for typed reads, schema generation, public command calls, and server-side CMS fetching in any JavaScript or TypeScript stack.@einblick/sdk/reactcontains the current in-page editing runtime. It is designed for React-based sites such as Next.js, Remix, plain React, or Astro pages that render React components.- Non-React sites can still use
@einblick/sdktoday for typed reads and public commands, but they do not get the ready-made editing provider and wrappers yet.
Typed reads and response shapes
- Collection reads support
limit,cursor,sort, andinclude. Use comma-separated field keys forsortand prefix a field with-for descending order. Without an explicitsort, CMS collections follow Einblick's manual record order, and each record exposes that order assortin record meta. - Relation includes only work for readable relation fields and when the same API key also grants the related collection. Included records are returned in
included. - CMS
richtextvalues are returned as structured document JSON, not flattened HTML. - Asset payloads expose stable URLs plus optional
width,height,title,copyright,description,tags, andsort. When a CMS video has a generated web playback variant, the public asset URL resolves to that browser-compatible MP4 or WebM file. Browser-origin requests for non-transformed files are proxied with CORS headers and range support; server-side requests without anOriginheader can follow short-lived storage redirects.
Resource writes
- Use
client.createResource(...),client.updateResource(...), andclient.deleteResource(...)for the standard resource API. CMS resources use/api/v1/cms/{slug}; native resources use/api/v1/{slug}. - Resource writes require a matching resource write grant on the API key plus writable-field grants for create and update payloads. CMS resources support create, update, and delete. Native resource writes currently support buildings, events, and festivals; native deletes archive the record.
- Pass an
idempotencyKeyfor retryable resource writes. Reusing the same key for the same route and payload returns the stored result; reusing it with a different payload returns a conflict.
Public commands
- Public commands are separate from resource reads and require explicit write-action grants on the API key.
- Use
client.getCommandSchema()to inspect the commands available to the current token. - Use
client.command(name, input)or typed helpers such asclient.jobs.submitApplication(...)for granted actions. Pass anidempotencyKeyfor retryable submit-style calls. - Newsletter signup is available through
client.newsletter.signup(...)when the key grantsnewsletters.signup. It creates or updates a contact, can apply published contact-group slugs, and returns eithersubscribedorpending_confirmationdepending on workspace newsletter settings.
What the runtime does
- Anonymous visitors keep the normal SSR, caching, and performance profile of the external site.
- Signed-in editors get hover indicators, inline editing for simple fields, and a hosted drawer for more complex fields.
- By default, authenticated edit mode renders a fixed bottom Einblick control bar with the connected site, one general Collections button, and a More menu for opening Einblick or logging out. Use
chrome="badge"for the previous launcher style orchrome="none"when the host site provides its own entry point. - The collections panel lets editors search all available resources for the external site session. CMS collections are grouped under an expandable CMS item, while supported native resources appear on the same level as that group. Editors can expand or collapse nested CMS collections, open the matching resource in Einblick, edit or delete existing records in the hosted drawer, and create records from the host site. Native drawer editing currently uses the normal Einblick forms for buildings, events, and festivals. Search expands matching branches so matching children stay reachable. Record labels use the configured display field when available, then fall back to
title,name,headline, another displayable field, the slug, or a generic record label. Singleton resources only show the create action until their first record exists. - Editors can reorder CMS records in the collections panel with the drag handle unless sorting is disabled for that collection.
- Wrap rendered list surfaces with
EditableCollectionand acreateEditableCollectionBinding({ resourceSlug })binding to show an Add record action that opens the hosted drawer in create mode without leaving the host site. Keep item-levelEditableRegionbindings inside that wrapper so each record still has its own hover edit state. - In the hosted drawer, editors can reorder multi-value
filesandtagsfields. Savedfilesarrays keep that order in SDK and public API responses. - Relation and multi-relation fields in the hosted drawer load selectable records through the current edit session, scoped to the field's configured target collection. The picker uses the target collection's display field for labels, currently returns up to 100 records from the same workspace, and lets editors create or edit related records without opening the CMS separately. When a related record is created and the target collection has a relation field back to the current collection, Einblick pre-fills that back-reference.
- Field-level saves patch currently visible text-like bindings immediately.
- Image, gallery, and file bindings can upload and replace media from the external editor. Single-value fields store the uploaded file; multi-value image and file fields are replaced with the uploaded file as the new list.
- The host site's
onSaverefresh/refetch path is still needed when the rendered page depends on resolved asset URLs, SSR output, or cached data.
Login and edit sessions
- The login flow tries a popup first and falls back to a full-page redirect if the browser blocks popups.
- After sign-in, the editor returns to the current page with edit mode enabled.
- The provider stores the edit session per site key on the current device, so editors can keep working on the same registered origin until the session expires or they leave edit mode.
- Edit sessions are origin-bound. If you use multiple allowed origins for one site, editors sign in separately on each origin.
What the host site still owns
- The host site still owns server-side reads, page rendering, and any long-lived cache layers.
- The SDK can patch some currently visible DOM immediately, but it cannot automatically purge framework-specific SSR caches, CDN caches, or static generation outputs on every host.
- For the best experience, wire the provider
onSavecallback to the host site's cache invalidation plus the smallest refresh/refetch mechanism that re-renders fresh data. The callback also fires after hosted-drawer creates and deletes, with deleted records reported asvalue: null. - The default control bar reserves bottom body space and sets
--einblick-editor-bottom-offsetplusdata-einblick-editor-bar-activeon<html>. Move fixed bottom host UI with that variable, or setreserveBottomSpace={false}if the host site manages spacing itself.
Cache invalidation best practices
- If your site has no persistent SSR or CDN caching, text-like field edits and inline media replacements may already look correct immediately. Still refresh or refetch after save when the page renders resolved asset URLs or cached data.
- If your site uses tagged data caches, revalidate the smallest tag scope that covers the edited resource.
- If your site statically renders routes, also revalidate the affected route output. Tags refresh the data cache; paths refresh the prerendered page or layout cache.
- If your site uses a CDN or reverse proxy cache, purge the relevant cache key or path after a successful save.
Next.js
- Keep CMS fetching on the server.
- Tag resource fetches with
next.tags, preferably throughcreateEinblickCmsTags()from@einblick/sdk/next. - Expose
POST /api/einblick/revalidatewithcreateEinblickRevalidateHandler({ tags }). For route handlers and Einblick webhooks, use immediate expiration (revalidateTag(tag, { expire: 0 }));profile: "max"can serve stale content once before refreshing. - For statically rendered App Router pages, make sure the same route also invalidates affected paths. The SDK helper defaults to
revalidatePath('/', 'layout'), which is a solid small-site default. Larger apps can pass a narrowerpathsmap. - Mount
EinblickNextEditBootin the root layout. It pings the revalidation route after inline saves and hosted drawer saves, then callsrouter.refresh()to re-render the current route without a full page reload. - In the external site settings, keep the revalidation endpoint set to
/api/einblick/revalidateso direct edits made inside Einblick invalidate the same tags. Einblick posts{ resourceSlug }to that path on each allowed origin after CMS creates, updates, deletes, reorders, and external-editor file changes. A shared revalidation token is optional; if you require one, pass it to both the Einblick external site config andEinblickNextEditBoot.
// lib/einblick-cache.ts
import { createEinblickCmsTags } from '@einblick/sdk/next'
export const einblickTags = createEinblickCmsTags({
fanOut: { 'gedanken-sections': ['gedanken'] },
})
// app/api/einblick/revalidate/route.ts
import { createEinblickRevalidateHandler } from '@einblick/sdk/next'
import { einblickTags } from '@/lib/einblick-cache'
export const POST = createEinblickRevalidateHandler({
tags: einblickTags,
// Default: paths: [{ path: '/', type: 'layout' }]
})
// app/layout.tsx
import { EinblickNextEditBoot } from '@einblick/sdk/next'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>
<EinblickNextEditBoot>{children}</EinblickNextEditBoot>
</body>
</html>
)
}
Remix and custom SSR
- Keep CMS fetching on the server or in loaders.
- After save, invalidate your loader data, route cache, or CDN cache in the smallest possible scope, then trigger the smallest refresh/refetch path that re-renders fresh server data.
- If you use client-side query caches, trigger a refetch after save when needed.
Recommended integration shape
- Fetch CMS or native resource data on the server with
@einblick/sdk. - Map raw records into view models and keep editable bindings alongside them.
- Wrap CMS-backed output with
EditableText,EditableImage, orEditableRegion. For repeated lists, wrap the full list inEditableCollectionand keep item-level regions inside it. For native records, setsourceType: 'native'on the binding and pass the native resource slug plus record ID. - Mount
EinblickEditProviderwith the publishable site key and choose the default control bar,chrome="badge", or custom host chrome. - Use
EinblickLoginButtonor?einblick-login/?loginas the editor entry point. - Use
onSaveto revalidate caches and trigger the host site's refresh/refetch path when the page reads resource data through SSR or other caches.