Docs
Systhema Design (opens in new tab)
Unreleased

AI assistant

The AI surfaces in the Admin, what the model knows, and enabling it.

On this page

The Admin assistant can open beside an individual field.

The Lexical toolbar also opens the assistant.

@systhemaui/payload ships a native AI assistant for the admin panel — no extra plugin to install. It covers seven surfaces:

  1. Field-level generation — a four-pointed AI star riding inside eligible text and textarea fields on the right, positioned like a select's caret and always visible (the star becomes a hexagon when hovered, and holds it while its panel is open). It opens one combined panel: a highlighted free-text prompt first (Enter generates), then the pre-made actions underneath — Check grammar / Rephrase as prominent paired buttons, then Expand, Summarize, Simplify, Translate and a Personalize link (which opens its own sub-page). While generating, the mark morphs between hexagon and a smaller rotating, pulsing circle (click it to stop), the field locks read-only, and a skeleton shimmer sweeps over it while the text streams in — back to the star when done. The whole UI is built from Payload's own admin primitives, so it matches the panel's look in both themes.

  2. Rich text editing — a single AI button (the same star mark, always last) in the lexical editor toolbars opens the same combined panel as a floating popover anchored at the button (works in fixed and inline toolbars): prompt first, then the transform actions — Check grammar, Rephrase, Expand, Summarize, Simplify, Translate. Each acts on the current selection, or — with nothing selected — on the whole editor: grammar, rephrase and translate map every text 1:1 so blocks, formatting and structure are preserved, while Expand/Summarize/Simplify regenerate the content and replace it. Results splice into a selection so native undo/redo keeps working. There is no separate "generate layout" control — the prompt itself drives everything (see Layout generation). While generating, the toolbar hexagon runs the same morph animation, the editor locks read-only under a skeleton shimmer, and the panel shows the result streaming in live; the final content is applied in a single update so undo stays one step.

  3. Layout generation — generation is driven entirely by the prompt's intent — there's no explicit layout button to toggle. The model is aware of the editor's design blocks but strongly prefers plain rich text and reaches for blocks only when the brief genuinely asks for a designed page. "Write a 500-word blog post about …" produces flowing editorial text — a scannable heading outline, paragraphs, lists, links and an occasional inline call-to-action button (the real Systhema button block, with the project's own token-driven variants), with no unnecessary block wrappers. "A beautifully designed landing page about …" — or a brief that names structures ("add an FAQ accordion", "a 3-column feature grid", "a contact form") — gets the full designer treatment with token-driven defaults. With text selected, the selected content becomes the source material and is replaced; without a selection the result is inserted at the cursor (and a pure write reveals progressively in its final formatted shape). Layout blocks are only available in editors that register them; elsewhere the prompt composes plain rich text. See What the model knows for the vocabulary.

  4. Page-level assistant — on content collections only (those with a top-level rich text editor — pages, components, posts; never uploads/taxonomy), an AI button next to the document controls (styled like the live-preview toggler) generates the whole page from one brief: a value for every fillable text field plus a layout for every top-level rich text editor, all telling one coherent story. It also offers full-page translation: every text/textarea value plus every rich text editor (including content nested inside blocks) translated at once, schema-driven so slugs, URLs, selects, uploads and relationships are structurally untouchable. Results land in the form as draft edits — review and save yourself. Because a whole-page run rewrites every field and editor at once, a full-document loading veil (the AI mark + a shimmer sweep, like an "Uploading…" state) covers and shields the form until the changes land.

  5. Image generation and refinement — upload fields get the same AI mark, opening the same combined panel: an auto-growing prompt first; with an image already selected, a pre-checked "Refine the selected image" toggle plus quick actions (Boost resolution, Remove background); and a Settings sub-page for aspect ratio and target resolution (1K/2K/4K — providers price by resolution; mapped best-effort per provider/model, e.g. Gemini's imageSize, OpenAI's quality tiers). Generation defaults to 1K — cheap and fast to iterate; Boost resolution is the upscale path once a result is worth keeping. Style direction belongs in the prompt itself. Both flows always create a new uploads document — and after a result lands, a Revert affordance restores the previous image with a choice to delete the generated upload and revert, keep it and revert, or cancel. Refining pulls the source image bytes from the upload's URL, forwarding the admin session cookie only when the URL is same-origin as serverURL (guarding against SSRF/cookie leakage); a missing or unreachable source returns HTTP 400. The status message cycles through friendlier updates while the longer image runs work.

  6. SEO auto-generation — with AI enabled, the SEO tab's native auto-generate buttons (meta title and meta description) are powered by the AI module: the page's whole content is digested into the prompt, so the description actually describes the page (≤155 characters, content language). Quota-gated and usage-logged like every other generation; without AI they fall back to naive field copies. The /seo and /alt endpoints return a bare { error } on failure (quota → 429 with quotaExceeded, other generation errors → 500), distinct from the { success: false, error, quotaExceeded } envelope used by /generate and /generate-image.

  7. Image alt text — an upload collection's alt field gets a one-click Auto-generate alt text button (below the field description — never the full compose panel). The model sees the image (vision) and writes a concise descriptive alt tag (≤125 characters, no "image of…" preamble); for local/non-public files the image is sent as bytes, and on a text-only provider it falls back to context-only. Counts as one text generation and bills its tokens (vision input included) like any other. The uploads list view also gets a Generate missing alt text bulk action: it finds image uploads with no alt, confirms the count (one generation each), then generates + saves them one by one, stopping cleanly if the plan limit is hit.

Each quick-generate trigger (SEO title/description, single + bulk alt text) has a caret opening a small popup to customize the result: a target language (overrides the content's language) and free-text custom instructions. The choices persist per-surface in localStorage and are sent with the request (instructions are length-clamped server-side).

Every generation is page-aware: the request carries the current form data, and the server digests the whole document (every text and rich text value, path-labelled, schema-driven) into prompt context — so a generated label, paragraph or layout fits the page it lands on instead of just the field it was asked from.

What the model knowsLink to this section

The layout vocabulary is built per request from two inputs: what the requesting editor registers (its tier decides the blocks, its inline blocks decide button / chip), and the project's own facts, read server-side with the requesting user's access:

ItemWhere it may appearWhat the model choosesWhat it needs
texteverywhereheadings, paragraphs, lists, links, an occasional button, a chip tag row—
sectionrootbackground and theme from the project's colour system, region content—
featurerootan image beside copy, float left/right, background / themean image in the uploads catalogue
columns, card, quote, accordionroot, region (columns/card where registered)the same shapes an editor inserts by hand—
imageroot, region, fragmenta content-width picturean image in the uploads catalogue
formroot, region, fragmentan existing forma form in the forms catalogue
componentroota reusable band authored once in the Components collectiona component in the catalogue
postsrootlimit, view, background / themethe Posts module

The catalogues are short lists of existing documents: published pages (title and path — the only paths an internal link or button may use; they hydrate as real document references, and an invented internal path is dropped while its words stay), forms, components, and the most recent image uploads by alt text. A kind whose catalogue is empty is withheld from the schema entirely, so the model can never invent an id. Every generated block is hydrated from the real block definition, so untouched fields carry the same defaults an editor gets.

Three design rules from Systhema's own layout model are part of every layout prompt, because they are what a fresh author most often gets wrong: adjacent sections with the same theme and background merge into one band (so a designed page alternates backgrounds, and gives at most one band an accent theme); a feature is one image beside copy and is never faked with columns plus an image; and prose needs no wrappers or spacing of its own — the rich-text rules already space it. The page's own title (its hero or title field) is the only h1: composed content starts at h2, and a generated h1 is demoted on hydration. Whole-page generation additionally treats the hero group as the masthead, so the editors continue the page after it instead of opening with a second title.

The feature is disabled by default and activates through the ai plugin option.

InstallationLink to this section

There is nothing to install. The Vercel AI SDK is bundled inside @systhemaui/payload — enabling ai requires no extra dependencies in your project, and the provider code loads lazily so projects with AI disabled never pay for it.

EnablingLink to this section

On an existing project, the recommended path is the global CLI: systhema setup ai walks the same questionnaire as create (None / single provider / custom model list), writes src/payload/ai.ts, and wires the .env variables for you — see systhema setup. The rest of this section covers what that config looks like and how to author it by hand.

Configuration is forwarded through the ai plugin option from your own environment — exactly like the captcha site/secret keys. The package never reads environment variables itself:

payload.config.ts
withSysthema({
  ai: {
    text: {
      provider: 'anthropic',
      apiKey: process.env.ANTHROPIC_API_KEY,
      model: 'claude-opus-4-8',
    },
    image: {
      provider: 'openai', // gpt-image-1 — supports refinement (so do Gemini/Nano Banana models)
      apiKey: process.env.OPENAI_API_KEY,
    },
  },
})

model is optional — each provider has a built-in default (openai → gpt-5-mini, anthropic → claude-opus-4-8, google → gemini-flash-latest, groq → openai/gpt-oss-120b).

To make the feature conditional on the environment (the same pattern the Payload template uses for captcha), gate it on the variable:

ai: process.env.ANTHROPIC_API_KEY
  ? { text: { provider: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY } }
  : false,

New projects: systhema createLink to this section

The Payload template ships pre-wired. systhema create asks about the AI assistant in its setup questionnaire, offering:

  • None — AI disabled.
  • Single provider (--ai <provider> / --ai-key / --ai-model / --ai-base-url) — one model, driven by SYSTHEMA_AI_* env vars.
  • Custom — an interactive loop to add your own text/image models (and locked upgrade teasers), plus an optional credit budget and plan label — all your own values.

The wizard configures the AI assistant technically and prescribes no plan or pricing structure — that's the licensee's own business logic. Author a plan (packageName + models[] + quota) directly in src/payload/ai.ts if you want one.

The AI config lives in its own module, src/payload/ai.ts (export const ai), which payload.config.ts imports — the same pattern as the database/email adapters. Single-provider scaffolds keep the env-gated module below; a custom model list emits an explicit models[] config whose keys are referenced from per-provider env vars (OPENAI_API_KEY, ANTHROPIC_API_KEY, …). The env-gated single-model module activates whenever SYSTHEMA_AI_PROVIDER is set:

Env varMeaning
SYSTHEMA_AI_PROVIDERopenai | anthropic | google | groq | openai-compatible
SYSTHEMA_AI_API_KEYThe provider API key (optional for self-hosted endpoints)
SYSTHEMA_AI_MODELModel id (blank = package default; required for openai-compatible)
SYSTHEMA_AI_BASE_URLEndpoint base URL — openai-compatible only

systhema doctor validates this convention (the ai-config check) and flags an unknown provider, a missing key, or a self-hosted endpoint without its base URL/model.