ماذا يمكنك أن تفعل مع AI-SLOT Management؟
- Drop-in for the site you already have — wrap existing markup in
<ai-slot>; plain HTML, React and Vue all work, no rewrite required. - Ship AI content like a static asset —
prewarm.mjsbakes developer prompts intoai-cache.jsonat build time, so production serves with no runtime LLM calls on cache hits. - Content updates without a redeploy —
livesubscribes to invalidation pushes and reconnects after interruption; a data-source change re-renders connected slots. On connection, integrators can useonConnectto check current content; simultaneous deliv... - Skeleton-first streaming —
streamfetches over SSE: a skeleton frame renders immediately, the final tree replaces it. - Protocol-neutral — native JSON today, A2UI tomorrow via
@ai-slot/a2ui; the endpoint changes, the page does not. - Visitor personalization is opt-in, per slot —
editableadds a one-line prompt box scoped to that slot: sanitized, rate-limited, short TTL. - Runs offline out of the box — deterministic mock LLM by default; unit tests replay fixtures and never hit a real API.
التثبيت
أضف هذا إلى إعدادات MCP في عميلك (Claude Desktop: claude_desktop_config.json، وCursor: .cursor/mcp.json، ويستخدم VS Code وغيره الصيغة نفسها «mcpServers»).
@ai-slot/mcpclaude mcp add ai-slot-management -e 'AI_SLOT_AGENT_TOKEN=<your ai_slot_agent_token>' -- npx -y @ai-slot/mcp@0.1.3
{
"mcpServers": {
"ai-slot-management": {
"command": "npx",
"args": [
"-y",
"@ai-slot/mcp@0.1.3"
],
"env": {
"AI_SLOT_AGENT_TOKEN": "<your ai_slot_agent_token>"
}
}
}
}
متغيرات البيئة
AI_SLOT_AGENT_TOKENإلزامي سري 本地管理服务配置的 Agent 令牌;不得使用 Owner 令牌。
التوثيق
مأخوذ من ملف README للمشروع على GitHub ويُحدَّث أسبوعيًا. تفتح الروابط على GitHub.
المحتويات
ai-slot-component
The AI content delivery layer for the pages you already have.
English | 简体中文
AI-SLOT adds local AI content and component composition to existing sites, CMSs and site builders. AI produces validated component-tree JSON using developer-registered components. Endpoints can also supply the same protocol without calling AI for every update. After initial integration, supported content updates do not require a host redeploy. A local reference implementation now supports versioned publishing and management MCP; it has protocol tests, while external Agent use and customer deployment remain unverified. The website MCP still reads documentation only. See the delivery status.
Wrap a region of your page and provide the initial HTML as fallback. The runtime keeps a copy for recovery when it replaces the visible content:
<ai-slot name="hero" src="/ai-render/hero">
<section class="hero">
<h1>Our product</h1>
<p>A normal product intro.</p>
</section>
</ai-slot>
Behind that element sits a delivery pipeline: a stateless server proxy turns model output into a validated component tree — never HTML — rendered as your real components, served from a two-tier cache, streamed skeleton-first, and re-pushed when the underlying data changes. If the model times out, invents a component name, or violates a prop schema, the original markup above silently stays. The initial HTML supplies fallback content independently of the model; indexing, accessibility and uptime still depend on the host application.
Content reaches a slot in three ways — visitor personalization is only one of them:
| Delivery mode | Trigger | Path |
|---|---|---|
| Pregenerated | your build (prewarm.mjs) | baked into ai-cache.json, long-TTL cache, no runtime LLM calls on cache hits |
| Live | a data-source change | invalidation push re-renders the slot on every open tab — no redeploy |
| Personalized | a visitor prompt (editable) | sanitized, rate-limited, short TTL — scoped to that one slot |
Quick Start
Prerequisites: Node ≥ 18, pnpm (corepack enable). No API key needed — the demo ships with a deterministic mock LLM.
git clone https://github.com/iannil/ai-slot-component
cd ai-slot-component
pnpm install && pnpm build
node examples/plain-html/server.mjs
# → open http://localhost:4173
The demo app opens with an industry picker — e-commerce, hotel, news and banking pages, each a realistic legacy page. The hero slot carries stream + live, and a recommendation slot whose AI always fails shows the silent fallback. There is no input box on the page — the operator is the one who adjusts: the admin.html ops console (or POST /admin/prompt?slot=<slotId>&prompt=<new prompt>) changes the selling-point angle, POST /admin/publish?slot=<slotId> simulates a data-source change, and both push invalidation so open pages update in place. node examples/plain-html/prewarm.mjs bakes ai-cache.json for the pregenerated path. The project website embeds the same pages as an interactive, step-guided demo running the real runtime in your browser, and the demo app itself is also deployed live on Cloudflare Workers.
To use a real model instead of the mock:
OPENAI_API_KEY=sk-... node examples/plain-html/server.mjs
# optional: AI_BASE_URL (any OpenAI-compatible endpoint)
# optional: AI_MODEL_DEVELOPER (default gpt-4o) / AI_MODEL_USER (default gpt-4o-mini)
Got it running? A GitHub star helps others find the project.
Features
- Drop-in for the site you already have — wrap existing markup in
<ai-slot>; plain HTML, React and Vue all work, no rewrite required. - Ship AI content like a static asset —
prewarm.mjsbakes developer prompts intoai-cache.jsonat build time, so production serves with no runtime LLM calls on cache hits. - Content updates without a redeploy —
livesubscribes to invalidation pushes and reconnects after interruption; a data-source change re-renders connected slots. On connection, integrators can useonConnectto check current content; simultaneous delivery to every visitor is not guaranteed. - Skeleton-first streaming —
streamfetches over SSE: a skeleton frame renders immediately, the final tree replaces it. - Protocol-neutral — native JSON today, A2UI tomorrow via
@ai-slot/a2ui; the endpoint changes, the page does not. - Visitor personalization is opt-in, per slot —
editableadds a one-line prompt box scoped to that slot: sanitized, rate-limited, short TTL. - Runs offline out of the box — deterministic mock LLM by default; unit tests replay fixtures and never hit a real API.
Why it is safe
- The model never writes markup. It returns component-tree JSON whose component names must exist in the registry you declared, validated against prop schemas, slot rules, depth and node-count limits before anything renders. This constrains model output; application components must still handle untrusted props safely.
- Fallback for handled delivery failures. A network failure, timeout, rate limit or invalid output falls back silently to the content inside
<ai-slot>. No blank screen, no error shown to visitors. - Secrets stay on the server. LLM keys live only in the proxy. Visitor prompts are sanitized, length-capped and injected as bounded context, with token budgets, an 8s timeout, per-minute rate limiting and usage logs.
- Initial HTML contains the fallback you provide. After a successful render, the runtime replaces the slot’s visible children and retains the fallback for recovery. Crawlers that render JavaScript may see the enhanced content; indexing is not guaranteed.
Protocol-neutral by design
ai-slot separates three layers:
- Slot protocol — the wire format between the AI endpoint and the page. Native JSON today; A2UI (Google's open protocol for agent-driven UI) works too via
@ai-slot/a2ui. - Delivery runtime —
<ai-slot>, client-side re-validation, and fallback recovery for handled failures. - Lifecycle infrastructure — two-tier caching, build-time pregeneration, invalidation push, rate limiting.
An agent endpoint using the A2UI versions and message subset supported by @ai-slot/a2ui can feed an existing page:
import { defineRegistry } from "@ai-slot/registry";
import { createDomRenderer } from "@ai-slot/adapter-dom";
import { configureAiSlot, registerRenderer, registerWireFormat } from "@ai-slot/runtime";
import { a2uiWireFormat, basicCatalogComponentDefs, basicCatalogDomDefs } from "@ai-slot/a2ui";
const registry = defineRegistry({
components: { ...basicCatalogComponentDefs /* , your brand components */ },
});
registerWireFormat("a2ui", a2uiWireFormat);
registerRenderer("dom", createDomRenderer(basicCatalogDomDefs));
configureAiSlot({ registry, onFailure: (f) => console.debug(f) });
| A2UI / AG-UI | ai-slot | |
|---|---|---|
| Layer | Wire format for agent ↔ in-app UI (Google / CopilotKit) | Delivery layer for public web content slots — speaks A2UI via @ai-slot/a2ui |
| Existing pages | Integration depends on the host application | Wraps existing HTML with an explicit fallback |
| SEO & crawlers | Depends on the host rendering strategy, access and crawler capabilities | Author-provided fallback in initial HTML; generated enhancements render on the client |
| Lifecycle | A protocol does not determine the host application’s cache or delivery lifecycle | Two-tier TTL, build-time prewarm, invalidation push, rate limiting |
Rendering and indexing boundaries
prewarm.mjs generates ai-cache.json, not HTML. It avoids runtime model calls for cache hits; a cache miss or expiry can still invoke the model. Generated component trees are fetched and rendered by the browser. To put generated content in the initial HTML, the host must add its own static or server rendering integration; this example does not provide one.
Google can render JavaScript, while other crawlers may have different capabilities. Keep useful fallback content in the initial response and verify the deployed page. See Google’s JavaScript SEO guide and the Chinese delivery-boundary guide.
Usage
All packages are on npm as
@ai-slot/*: client —npm install @ai-slot/runtime @ai-slot/adapter-dom(+@ai-slot/a2uifor A2UI endpoints); server —npm install @ai-slot/proxy @ai-slot/registry. To hack on the monorepo instead, clone andpnpm install && pnpm build.
1. Declare what the AI may build with (shared by proxy, runtime and build tooling):
import { defineRegistry } from "@ai-slot/registry";
export const registry = defineRegistry({
components: {
"hero-banner": {
description: "Page hero section",
props: {
title: { type: "string", maxLength: 60 },
subtitle: { type: "string", maxLength: 120 },
},
required: ["title"],
},
},
});
2. Wire the proxy — a Web-standard (Request) => Promise<Response>, deployable to Node, Edge or any serverless runtime:
import { createAiRenderHandler, createOpenAIClient } from "@ai-slot/proxy";
import { registry } from "./registry.js";
export const handler = createAiRenderHandler({
registry,
llm: createOpenAIClient({ apiKey: process.env.OPENAI_API_KEY! }), // baseUrl: any OpenAI-compatible endpoint
resolveSlot: (slotId) => slots[slotId] ?? null,
});
// Exposes GET/POST /ai-render/:slotId — GET for CI pregeneration, POST for real-time delivery (visitor prompts included).
3. Render it — pick your stack:
<script type="module">
import { configureAiSlot, registerRenderer } from "@ai-slot/runtime";
import { createDomRenderer } from "@ai-slot/adapter-dom";
import { registry } from "./registry.js";
import { domComponents } from "./components.js";
registerRenderer("dom", createDomRenderer(domComponents));
configureAiSlot({ registry });
</script>
// React ≥ 18 — any failure keeps `fallback`, same semantics as the Web Component
<AiSlot src="/ai-render/hero" components={{ "hero-banner": HeroBanner }} fallback={<HeroStatic />} editable />
<AiSlot src="/ai-render/hero" :components="vueComponents">
<HeroStatic />
</AiSlot>
<ai-slot> attributes
| Attribute | Effect |
|---|---|
src | Proxy endpoint for this slot (/ai-render/:slotId) |
name | Slot id sent to the proxy |
renderer | Registered renderer to use (default dom) |
stream | Fetch over SSE: skeleton frame first, final tree second |
live | Subscribe to invalidation pushes and re-render on change (live-src overrides the endpoint) |
refresh-interval | Re-fetch every N seconds |
editable | Adds a one-line prompt box that re-renders this slot |
fresh-only | For managed content, requires a valid future meta.expiresAt (Unix milliseconds) on each final tree; failures and expiry restore the original fallback |
The delivery pipeline
graph TD
A["ai-slot element in your HTML"] -->|"GET / POST /ai-render/:slotId"| B["Stateless proxy (Edge / Serverless)"]
B --> C["PromptCompiler"]
C --> D["LLM (OpenAI-compatible)"]
D --> E["OutputValidator"]
E -->|"valid component tree"| F["Cache: L1 developer / L2 visitor"]
F -->|"JSON, or SSE skeleton + tree"| G["Adapter renders your real components"]
E -->|"invalid / timeout / rate-limited"| H["Silent fallback: original content stays"]
Packages
| Package | What it does |
|---|---|
@ai-slot/registry | The contract: defineRegistry, component-tree types, and the OutputValidator shared by proxy, runtime and tooling |
@ai-slot/proxy | Stateless render proxy: prompt compilation, LLM calls, validation, two-tier cache, rate limiting, SSE, invalidation push, pregeneration |
@ai-slot/runtime | Zero-dependency <ai-slot> Web Component + registerRenderer registry |
@ai-slot/adapter-dom | Maps component trees to plain DOM (tag / class / applyProps) — no framework needed |
@ai-slot/adapter-react | treeToReact + <AiSlot> component |
@ai-slot/adapter-vue | treeToVue + AiSlot component |
@ai-slot/a2ui | A2UI wire-format compatibility |
@ai-slot/operations | Experimental local version store and approval/publish governance; Node >=22 |
@ai-slot/mcp | Experimental local stdio management client; Node >=22, separate HTTP service required |
Development
pnpm build # build all packages (ESM → dist/)
pnpm test # all unit tests (Vitest)
pnpm typecheck # needs dist type artifacts: run pnpm build first on a fresh checkout
pnpm --filter @ai-slot/runtime test # single package
cd packages/proxy && npx vitest run src/cache.test.ts # single test file
# End-to-end (Playwright, 7 specs)
pnpm --filter example-plain-html exec playwright install chromium
pnpm --filter example-plain-html test:e2e
# CI pregeneration (bakes ai-cache.json, hydrated on server start)
node examples/plain-html/prewarm.mjs
The workspace uses type checking; the website also has an ESLint gate.
For AI coding agents
- Repo guides: CLAUDE.md and AGENTS.md. The design spec in
docs/superpowers/specs/is the source of truth for implementation work. - The example runs on a deterministic mock LLM with no network and no key, so
pnpm build && node examples/plain-html/server.mjsis a safe smoke test for an agent to verify the repo. OutputValidatoris a pure function with adversarial test cases inpackages/registry— the security boundary lives there, not in prompts.
Project status
All nine packages are published on npm, including runtime 0.2.0, proxy 0.3.0 and the first public operations/mcp 0.1.0 releases. The management packages are experimental, require Node >=22, and support the local reference workflow. Clean npm installation, package integrity, rendering, storage restart and MCP CLI discovery are verified. External AI-client acceptance and customer pilots remain pending. See the release record and acceptance status.
Deliberately deferred: token-level LLM streaming and multi-instance rate-limit/cache stores. Explicitly out of scope: arbitrary HTML/CSS generation, client-side DOM patch protocols, in-browser inference, multi-tenant billing.
Contributing
Issues and PRs are welcome — see AGENTS.md for architecture, commands and conventions (Conventional Commits, Chinese commit messages).
Bugs and feature requests: GitHub Issues.
Links
License
Released under the MIT License.
الأسئلة الشائعة
ما هو AI-SLOT Management؟
实验性本地 stdio 管理服务;需先启动 127.0.0.1:4194 管理端,内容发布仍需人工审批。
كيف أثبّت AI-SLOT Management؟
يعمل على جهازك. في Claude Code: claude mcp add ai-slot-management -e 'AI_SLOT_AGENT_TOKEN=<your ai_slot_agent_token>' -- npx -y @ai-slot/mcp@0.1.3. وفي العملاء الآخرين، الصق إعداد JSON من هذه الصفحة في إعدادات MCP الخاصة بهم.
هل يحتاج AI-SLOT Management إلى مفتاح API؟
نعم. يتطلب AI_SLOT_AGENT_TOKEN، وتضبطها في إعداداته.
هل AI-SLOT Management مفتوح المصدر؟
نعم. شيفرته متاحة على GitHub بترخيص MIT.
من يصون AI-SLOT Management؟
ينشره iannil. يدرجه AI.tn لكنه لا يصونه ولا يوصي به.
من سجل MCP الرسمي. الإدراج ليس توصية: راجع شيفرة الخادم وصلاحياته قبل منحه الوصول إلى بياناتك.