AI Website Construction & cockpitOS: Integration Concept
This document describes the target vision and implementation phases so that an AI session (e.g., Claude) can build websites and create or update content in cockpitOS — without users having to manually maintain everything in the dashboard. It applies to both Greenfield and Brownfield scenarios.
Guidelines: No data loss, no destructive schema steps; new interfaces only additively and with clear authentication. Existing APIs remain stable.
1. Problem & Target Vision
| Today | Goal |
|---|---|
| AI generates UI quickly (v0, Claude, …), data is separated | One session: Build + "for whom" + which content |
| Data is manually pulled into Cockpit | AI checks Cockpit (Is the center present? Is data there?) and writes missing data via secure APIs |
| Website shows demo data | Public site reads the same data as Cockpit (Single Source of Truth) |
| Editorial needs IT for every change | Editorial creates drafts via voice — approval in Cockpit workflow |
Identity: centerId consistently refers to the UUID ShoppingCenter.id in Cockpit (not Google Place ID). Slug → UUID can be resolved via public API (see Public API — Process for centerId).
2. Existing System Components
Do not reinvent these building blocks — build upon them:
| Component | Purpose | Documentation / Artifact |
|---|---|---|
| AgencyOS Magic Link + API-Key | Trust establishment, organization or user scope | AgencyOS Integration |
| Read/create/assign Center | GET/POST/PATCH under /api/agencyos/v1/centers/… | See AgencyOS documentation |
| Context for AI | Existing: Shops, Services, News, Events, Offers, Categories/Chains (slim), optional include=floors_summary without mapSvg body | GET …/centers/{id}/context |
| Write content (Upsert) | Shops, Events, News, Offers, Services; idempotency via metadata | POST …/content/push |
| Preview without DB write | Dry-run before live push | POST …/content/push/preview |
| Public read API | Website/SSR: Data from Cockpit without session | Public Center-Website API |
| MCP Server (Stdio + Remote) | Claude Desktop / Remote: all public reads + AgencyOS Context/Preview/Push; including Center Plan (cockpit_public_wayfinding_floors → GET /api/wayfinding/floors, including Hybrid-SVG with mapSvg + optionally mapImage/shopViewBoxes) | packages/mcp-cockpit-os, packages/mcp-cockpit-remote |
| Workflow & Approvals (UI) | Review drafts, approve, reject | Workflow & Approvals |
| Machine-readable | OpenAPI AgencyOS (including context with floors_summary) and public wayfinding read | /openapi/agencyos-integration.yaml, /openapi/public-wayfinding-read.yaml |
3. Two Usage Paths
3.1 Greenfield (new center / new site)
- User specifies organization, center name, desired slug, needed content types.
- AI checks: Does the center exist? (
GETCenters / possibly slug resolution via public API) - If necessary: Create or assign the center (only with appropriate rights — AgencyOS/Cockpit flows).
- Content validated stepwise via Push-Preview, then Push — or directly Push with monitoring.
- Website template / v0:
centerIdor Slug hardwired; data reference only via public endpoints +getDashboardApiUrl()/ contract.
3.2 Brownfield (existing center)
- User specifies the center (slug or UUID).
- AI loads context (
context?include=…), sees existing entities and Push-IDs. - Changes: again Preview → Push; no duplicates thanks to idempotency rules in the push documentation.
- Website remains linked to the same
centerId— only the content version changes.
4. Architecture Sketch (Target)
- Writing / sensitive context: via AgencyOS (or later user-scoped tokens — roadmap).
- Drafts for approval: via
submitToWorkflowpath → land in Workflow & Approvals, not directly live. - Delivery to visitors: via Public API (no secret in the browser).
5. Specific Use Case: “Offer for all Deichmann Centers"
This use case has been analyzed as an end-to-end test of the entire AI editorial workflow. It is representative of all multi-center campaigns.
Desired Process:
Editor → Claude: "Create an offer for Deichmann in all centers where Deichmann exists"
↓
Claude finds all centers with a Deichmann branch
↓
Claude generates offer text
Editor provides image URL (or uploads image to Cockpit beforehand)
↓
Claude creates draft in Cockpit — separately for each center
↓
Drafts appear in Workflow & Approvals (all visible at once)
↓
Approver approves (individually or in bulk) → goes live immediately on all websites
What Works Today — and What Doesn't
| Step | Current Status | Note |
|---|---|---|
| Retrieve all centers | ✅ | cockpit_list_centers |
| Filter Deichmann centers | ⚠️ Possible, but N+1 calls | Per center: cockpit_center_context?include=chains — for 50 centers 51 API calls |
| Generate offer text | ✅ | Native to Claude |
| Provide image | ❌ Only as URL | File upload not possible; image must be hosted beforehand |
| Create offer as draft | ⚠️ Directly in DB | content/push writes immediately, no workflow item |
| Draft in Workflow & Approvals | ❌ Not linked | AgencyOS push does not appear in the workflow queue |
| Approval in Dashboard | ⚠️ UI exists, backend partially mocked | Workflow system not yet fully implemented |
| Bulk approval of multiple centers | ❌ Planned, not implemented | Bulk actions in Workflow & Approvals are still missing |
Consequence: The workflow currently works with manual workarounds (upload image in advance, search for drafts manually in content list), but not as a seamless, secure editorial workflow for non-technical users.
6. Missing Components (Development Backlog)
The following features block or impair the idiot-proof AI editorial workflow. Prioritized by impact.
B1 — submitToWorkflow Mode in Content Push (Priority: High / Blocking)
Problem: POST /api/agencyos/v1/content/push writes directly to the database. Content goes live immediately (or as a draft without a queue entry). The Workflow & Approvals section does not see these items — editors and approvers cannot find them there.
Desired Behavior: A flag "submitToWorkflow": true in the push body (or a separate endpoint POST …/content/push/workflow-draft) should create a WorkflowItem record instead of a DB upsert:
source: "agencyos"status: "pending"- All content fields (title, description, image, dates, …) as JSON in the WorkflowItem payload
centerIdassigned- Optional:
campaignIdorcampaignLabel(e.g.,"Deichmann May Campaign") for bundled view - Upon approval: automatic conversion into a real content data record
Implementation (Proposal):
- New optional body parameter
submitToWorkflow: booleaninPOST …/content/push - If
true: no upsert logic, instead, createWorkflowItemwithsource: "agencyos",status: "pending" - Preview (
/preview) remains as before (no DB write, no WorkflowItem) - MCP tool
cockpit_content_pushto include flag; alternatively, a new toolcockpit_submit_for_approval
Dependency: Requires B3 (Workflow system fully implemented).
Affected Files (Reference):
apps/dashboard/src/app/api/agencyos/v1/content/push/route.tsapps/dashboard/src/lib/integration/process-center-entity-push.tspackages/mcp-cockpit-os/src/register-cockpit-tools.ts
B2 — Filter Centers by Chain (Priority: Medium / Performance)
Problem: There is no endpoint to find all centers where a specific brand/chain is present. Today, Claude has to:
- Load all centers (
GET /api/agencyos/v1/centers) - Load context for each center with
include=chains - Manually filter
This amounts to N+1 API calls. For 50 centers: 51 requests, increased latency, more token usage, and greater error risk.
Desired Behavior:
GET /api/agencyos/v1/centers?chainSlug=deichmann
GET /api/agencyos/v1/centers?chainName=Deichmann
Or as a dedicated chain endpoint:
GET /api/agencyos/v1/chains?name=Deichmann
→ { id, name, slug, centers: [{ centerId, centerName, centerSlug }] }
Implementation (Proposal):
- Optional
chainSlugorchainNamefilter inGET /api/agencyos/v1/centers - Internally: Join
ShoppingCenter↔Shop/ShopLocation↔ShopChainby name/slug - Same access check as existing center list (Org-Key vs. User-Key)
- MCP tool
cockpit_list_centersto extend with optionalchainSlug/chainNameparameters
Affected Files (Reference):
apps/dashboard/src/app/api/agencyos/v1/centers/route.tspackages/mcp-cockpit-os/src/register-cockpit-tools.ts
B3 — Workflow & Approvals: Fully Implement Backend (Priority: High / Blocking)
Problem: According to the current documentation, several core functions of the workflow system are not yet production-ready:
| Function | Status |
|---|---|
| Change Requests & Approval Requests | Mock implementation, no real DB integration |
| User Session (who approved) | Placeholder |
| Notifications / Audit Trail | Only logged, not persistent |
| Photo Upload in Workflow | In progress |
| Bulk Actions (approve multiple items) | Planned |
What is needed:
WorkflowItemtable with real database write operations- Fields:
id,centerId,source(agencyos/ai-assistant/cms/manager-app),type(offer/news/event/job),status(pending/in_review/approved/rejected),payload(JSON, all content fields),campaignLabel(optional),submittedBy,approvedBy,approvedAt,rejectedReason,createdAt,updatedAt - Status transitions:
pending→in_review→approved/rejected - Upon
approved: automatic creation of the real content data record (Offer, News, Event, …) including image URL from payload approvedBywith real user ID from NextAuth session- Bulk Approve: approve multiple items with one click — central for multi-center campaigns
- Filter by
campaignLabel— to allow approvers to see all items of a campaign at once - Email notification to the approver (or at least Dashboard notification for new items)
Especially important for multi-center campaigns: When Claude creates 8 offers for 8 Deichmann centers, these must be visible and approvable in bulk in the workflow.
Affected Files (Reference):
apps/dashboard/src/app/api/...(Workflow Route)apps/dashboard/src/app/dashboard/workflow/...(UI)- Prisma Schema: new
WorkflowItemtable (additive, no DROP)
B4 — Image Upload via API / MCP (Priority: Medium)
Problem: The image field in offers, news, events expects a URL as string. Non-technical editors cannot provide Claude with an image — they would have to manually upload the image somewhere and copy the URL.
Short-term Workaround (Option A):
- Editor uploads image to Cockpit media library or a linked CDN
- Copies the public URL
- Provides the URL to Claude as text: “Image: https://cdn.cockpit-os.de/…”
- Claude sets the URL in the push body
This option should be documented as a Step-0 Process and incorporated into the editorial workflow as a mandatory step until Option B is fully implemented.
Long-term Solution (Option B):
New endpoint:
POST /api/agencyos/v1/media/upload
Content-Type: multipart/form-data
Authorization: Bearer <apiKey>
→ { "success": true, "data": { "url": "https://cdn.cockpit-os.de/media/…" } }
- Register MCP tool
cockpit_upload_mediain the package - Claude can call this endpoint when the editor uploads an image in the chat (Base64 or file reference via Filesystem-MCP)
Affected Files (Reference):
- New endpoint:
apps/dashboard/src/app/api/agencyos/v1/media/upload/route.ts packages/mcp-cockpit-os/src/register-cockpit-tools.ts
B5 — Batch Context for Multiple Centers (Priority: Low / Convenience)
Problem: For multi-center campaigns (e.g., "check all Deichmann offers"), Claude has to make a separate cockpit_center_context call for each center today. This burdens the context window and increases latency.
Desired Behavior:
POST /api/agencyos/v1/centers/batch-context
Body: { "centerIds": ["uuid-1", "uuid-2"], "include": "offers,chains" }
→ { "success": true, "data": { "uuid-1": { ... }, "uuid-2": { ... } } }
Or as MCP tool:
cockpit_multi_center_context({ centerIds: [...], include: "offers,chains" })
Affected Files (Reference):
- New endpoint:
apps/dashboard/src/app/api/agencyos/v1/centers/batch-context/route.ts packages/mcp-cockpit-os/src/register-cockpit-tools.ts
7. Phased Roadmap (Updated)
| Phase | Content | Blocked by | Risk |
|---|---|---|---|
| 0 — completed | Concept + Capabilities JSON + MCP Phase 1 (public reads + AgencyOS Context/Preview/Push) | — | Documentation only |
| 1 — next step | Complete the Workflow backend (B3): WorkflowItem table, status transitions, user session, bulk approve, campaignLabel filter | — | DB migration additive; no schema drop |
| 2 | submitToWorkflow flag in content push (B1) + MCP tool extension | B3 (Phase 1) | No breaking changes; new optional parameter |
| 3 | Chain filter endpoint (B2) + MCP update | — | Only READ; no write risk |
| 4 | Image upload Option A: document Cockpit media library URL workflow (B4) | — | Only documentation + UI check |
| 5 | Image upload Option B: POST …/media/upload + MCP tool (B4) | — | New endpoint; additive |
| 6 | Batch context endpoint + MCP (B5) | — | Only READ; convenience |
| 7 | Personal access tokens (User-Scope) parallel to Org-Keys | Design + migration soft |
Prohibited in all phases: DROP statements, destructive migrations, changes to existing push semantics without versioning.
8. Target Workflow After Completing Backlog Items
When phases 1–4 are complete, the secure editorial workflow will look like this:
1. [Editor — optional, Step 0]
Upload image to Cockpit media library → copy URL
2. [Claude Chat]
"Create an offer for Deichmann, 20% off shoes,
valid May 1–14, image: https://cdn.cockpit-os.de/…
Please for all centers where Deichmann exists."
3. [Claude — automatically]
cockpit_list_centers → load all centers
Filter: Centers with chainSlug=deichmann (Phase 3 / B2)
Generate offer text
cockpit_content_push with submitToWorkflow: true
+ campaignLabel: "Deichmann May Campaign"
separately for each center — idempotency via agencyosPushId
4. [Cockpit Dashboard — Approver]
Workflow & Approvals → Filter "Deichmann May Campaign"
See all 8 drafts at once, image preview
Bulk approve with one click
→ Immediately live on all center websites
Security Properties of this Workflow:
- No content goes live without human approval
- Audit trail: who submitted what, when, who approved
- Idempotency: duplicate push overwrites, does not create a duplicate
- Rollback: rejected items remain as
rejected, no data loss - No
forcemode; no direct DB access for editors COCKPIT_ALLOW_CONTENT_PUSHremains as a safety switch for direct push (without workflow)
9. Checklist for Implementers
-
centerId= UUID from Cockpit; resolve slug viaGET /api/centers/by-slug/{slug}. - Writing: always Preview (
/push/preview) before direct push; in the editorial workflowsubmitToWorkflow: true. - Idempotency:
agencyosPushId/externalId/ Cockpit UUID according to AgencyOS documentation. - Website: only public URLs from Public API; no dashboard session in the client.
- WorkflowItem upon approval: create a real content data record with
source: "agencyos"and set WorkflowItem toapproved. - Bulk Approve: all items of a campaign (same
campaignLabel) should be approvable together. - After API extension: include
cockpit-api-capabilities.jsonand possibly OpenAPI.
Related Documentation
Nutzungsstatistik: Seitenaufrufe werden anonymisiert erfasst. Im Umami-Dashboard nach diesem Pfad filtern: /en/developer-guide/ki-website-builder-cockpit-sync-konzept