Knowledge vs custom pages
What this is
ComStack has two editable page types behind the MCP tools, and picking the wrong editor is the most common first-run mistake. This page explains how the server classifies a page as knowledge or custom, which tool edits each, and the guardrails that refuse a cross-type edit. (There is a third surface — the live voice agent — but it is not edited as a page.)
How it works
Every document exposes a page_type of knowledge or custom, returned on each get-project-state live/draft entry and on get-page-content. The server derives it — you never set page_type directly:
customwhenmetadata.typeis"custom"or the document uses thecustom-pagetemplate.knowledgeotherwise (the default).
The type maps one-to-one to an editor:
| page_type | What it is | Edit with | Body shape |
|---|---|---|---|
knowledge | Markdown on a structured template (docs, blog, product, FAQ…) | create-page / update-page | Markdown in content |
custom | Vibe-coded Astro/HTML with full layout freedom | upload-custom-page | Opaque body_source + <T> / data-t-key markers |
The guard is fail-closed in both directions:
update-pageon acustompage is rejected: ”… is a CUSTOM page (metadata.type=“custom”). Edit it with upload-custom-page (body_source +<T key=…>markers), not update-page. update-page edits knowledge (markdown) pages only.”upload-custom-pageon aknowledgepage is rejected with error codewrong_tool_knowledge_page: ”… is a KNOWLEDGE (markdown) page, not a custom page. upload-custom-page would overwrite its body with opaque body_source. Edit it with update-page, or pick a different slug for the custom page.”
So read page_type before you choose a tool.
When to use it
- Deciding which tool edits an existing page you were handed by URL
- Choosing a template for a new page (markdown structure vs total layout freedom)
- Diagnosing a
wrong_tool_*rejection
Page type vs template
page_type is coarse — it picks the editor. The doc template is fine-grained — it picks the fields and structure. A knowledge page still chooses a template (technical-doc-page, blog-post, solution-page, …), each with its own required metadata; a custom page always uses the custom-page template. List templates via get-project-state.available_doc_templates; inspect one with get-doc-template.
Example
get-page-content(project_id, slug: 'pricing', language: 'en') -> { page_type: 'knowledge', path: '...', metadata: { ... }, content: '## ...' }
(knowledge -> markdown editor)update-page(project_id, slug: 'pricing', content: '## ...') (accepted)
(the same call on a custom page is refused:)update-page(project_id, slug: 'home-hero') -> InvalidRequest: 'home-hero' is a CUSTOM page (metadata.type="custom"). Edit it with upload-custom-page ...Common errors
update-pageon a custom page — rejected with a redirect toupload-custom-page. Re-issue the edit as a custom-page upload, or confirm you meant a different page.upload-custom-pageon a knowledge page (wrong_tool_knowledge_page) — would overwrite markdown with opaque source. Useupdate-page, or pick a new slug for the custom page.- Assuming
page_typeis writable — it is derived frommetadata.type/ the template. To make a pagecustom, author it throughupload-custom-page; you cannot flip an existing knowledge page by setting a field.
Related
- First-run guide — where page-type selection sits in the flow
- Custom pages — authoring vibe-coded pages end to end
- Publishing — how either page type drafts and promotes
- Tool catalogue —
update-pagevsupload-custom-page - Errors — the wrong-tool guards in the full error list