feat(web): real 3-step wizard, settings, audit, docs, marketing pages
Sprint 3.5: close every dead link and replace the single-step wizard with the
spec-mandated 3-step flow.
Wizard:
- Step 1 collects prompt + name + slug, calls /v1/servers/preview.
- Step 2 renders parsed tools (name, description, input schema as copyable JSON)
+ a credential field per requiredSecret Claude actually identified. Self-contained
servers see 'No credentials needed' instead of generic Notion placeholders.
- Step 3 streams the live build over WebSocket and shows install snippets.
New dashboard pages:
- /settings — org, plan/usage, members table, API keys + billing stubs (Sprint 4),
encryption status. Reads /v1/me/org.
- /audit — filterable table over /v1/audit with action pills, resource refs, IP,
metadata JSON.
Docs site (/docs + 6 sub-pages):
- Sticky 240px sidebar, max-w-prose article column, shared DocsTitle/H2/Code primitives.
- Quickstart, MCP concepts, OAuth 2.1 flow (full walkthrough with curl), Authoring
tools, Self-hosting, API reference, FAQ.
Marketing pages:
- /changelog with tagged release timeline.
- /security with 8 pillars + disclosure.
- /privacy with GDPR-aware sections.
- /terms (10 clauses).
- /pricing full page (nav now points here instead of /#pricing anchor).
- /status with live 10s probes against /api/health and /login.
Footer 'system status' badge now links to /status.
All 20 routes 200 OK in smoke crawl. Typecheck clean across packages.
2026-05-19 18:20:31 +02:00
import {
DocsTitle ,
DocsLead ,
DocsH2 ,
DocsP ,
DocsList ,
DocsLi ,
DocsCode ,
Mono ,
} from '@/components/docs-page' ;
2026-07-08 23:00:02 +02:00
import { JsonLd } from '@/components/json-ld' ;
import { breadcrumbJsonLd , pageMetadata } from '@/lib/seo' ;
feat(web): real 3-step wizard, settings, audit, docs, marketing pages
Sprint 3.5: close every dead link and replace the single-step wizard with the
spec-mandated 3-step flow.
Wizard:
- Step 1 collects prompt + name + slug, calls /v1/servers/preview.
- Step 2 renders parsed tools (name, description, input schema as copyable JSON)
+ a credential field per requiredSecret Claude actually identified. Self-contained
servers see 'No credentials needed' instead of generic Notion placeholders.
- Step 3 streams the live build over WebSocket and shows install snippets.
New dashboard pages:
- /settings — org, plan/usage, members table, API keys + billing stubs (Sprint 4),
encryption status. Reads /v1/me/org.
- /audit — filterable table over /v1/audit with action pills, resource refs, IP,
metadata JSON.
Docs site (/docs + 6 sub-pages):
- Sticky 240px sidebar, max-w-prose article column, shared DocsTitle/H2/Code primitives.
- Quickstart, MCP concepts, OAuth 2.1 flow (full walkthrough with curl), Authoring
tools, Self-hosting, API reference, FAQ.
Marketing pages:
- /changelog with tagged release timeline.
- /security with 8 pillars + disclosure.
- /privacy with GDPR-aware sections.
- /terms (10 clauses).
- /pricing full page (nav now points here instead of /#pricing anchor).
- /status with live 10s probes against /api/health and /login.
Footer 'system status' badge now links to /status.
All 20 routes 200 OK in smoke crawl. Typecheck clean across packages.
2026-05-19 18:20:31 +02:00
2026-07-08 23:00:02 +02:00
export const metadata = pageMetadata ( {
title : 'Authoring tools' ,
description :
'How to write prompts that generate good MCP tools — naming, input schemas, credentials, and how the generated TypeScript is checked before it ships.' ,
path : '/docs/authoring' ,
} ) ;
feat(web): real 3-step wizard, settings, audit, docs, marketing pages
Sprint 3.5: close every dead link and replace the single-step wizard with the
spec-mandated 3-step flow.
Wizard:
- Step 1 collects prompt + name + slug, calls /v1/servers/preview.
- Step 2 renders parsed tools (name, description, input schema as copyable JSON)
+ a credential field per requiredSecret Claude actually identified. Self-contained
servers see 'No credentials needed' instead of generic Notion placeholders.
- Step 3 streams the live build over WebSocket and shows install snippets.
New dashboard pages:
- /settings — org, plan/usage, members table, API keys + billing stubs (Sprint 4),
encryption status. Reads /v1/me/org.
- /audit — filterable table over /v1/audit with action pills, resource refs, IP,
metadata JSON.
Docs site (/docs + 6 sub-pages):
- Sticky 240px sidebar, max-w-prose article column, shared DocsTitle/H2/Code primitives.
- Quickstart, MCP concepts, OAuth 2.1 flow (full walkthrough with curl), Authoring
tools, Self-hosting, API reference, FAQ.
Marketing pages:
- /changelog with tagged release timeline.
- /security with 8 pillars + disclosure.
- /privacy with GDPR-aware sections.
- /terms (10 clauses).
- /pricing full page (nav now points here instead of /#pricing anchor).
- /status with live 10s probes against /api/health and /login.
Footer 'system status' badge now links to /status.
All 20 routes 200 OK in smoke crawl. Typecheck clean across packages.
2026-05-19 18:20:31 +02:00
export default function Authoring() {
return (
< >
2026-07-08 23:00:02 +02:00
< JsonLd
data = { breadcrumbJsonLd ( [
{ name : 'Home' , path : '/' } ,
{ name : 'Docs' , path : '/docs' } ,
{ name : 'Authoring tools' , path : '/docs/authoring' } ,
] ) }
/ >
feat(web): real 3-step wizard, settings, audit, docs, marketing pages
Sprint 3.5: close every dead link and replace the single-step wizard with the
spec-mandated 3-step flow.
Wizard:
- Step 1 collects prompt + name + slug, calls /v1/servers/preview.
- Step 2 renders parsed tools (name, description, input schema as copyable JSON)
+ a credential field per requiredSecret Claude actually identified. Self-contained
servers see 'No credentials needed' instead of generic Notion placeholders.
- Step 3 streams the live build over WebSocket and shows install snippets.
New dashboard pages:
- /settings — org, plan/usage, members table, API keys + billing stubs (Sprint 4),
encryption status. Reads /v1/me/org.
- /audit — filterable table over /v1/audit with action pills, resource refs, IP,
metadata JSON.
Docs site (/docs + 6 sub-pages):
- Sticky 240px sidebar, max-w-prose article column, shared DocsTitle/H2/Code primitives.
- Quickstart, MCP concepts, OAuth 2.1 flow (full walkthrough with curl), Authoring
tools, Self-hosting, API reference, FAQ.
Marketing pages:
- /changelog with tagged release timeline.
- /security with 8 pillars + disclosure.
- /privacy with GDPR-aware sections.
- /terms (10 clauses).
- /pricing full page (nav now points here instead of /#pricing anchor).
- /status with live 10s probes against /api/health and /login.
Footer 'system status' badge now links to /status.
All 20 routes 200 OK in smoke crawl. Typecheck clean across packages.
2026-05-19 18:20:31 +02:00
< DocsTitle kicker = "Build" > Authoring tools < / DocsTitle >
< DocsLead >
What you write in the prompt is what Claude turns into TypeScript . Better prompts mean
better tools . These patterns cover 80 % of the common asks .
< / DocsLead >
< DocsH2 id = "anatomy" > Anatomy of a tool < / DocsH2 >
< DocsP > Each generated tool ends up looking like this : < / DocsP >
< DocsCode
label = "generated TypeScript"
code = { ` server.registerTool(
'search_pages' ,
{
title : 'search_pages' ,
description : 'Search Notion pages matching a query.' ,
inputSchema : {
query : z.string ( ) . describe ( 'search terms' ) ,
} ,
} ,
async ( args ) = > {
try {
const res = await fetch ( 'https://api.notion.com/v1/search' , {
method : 'POST' ,
signal : AbortSignal.timeout ( 10000 ) ,
headers : {
'Authorization' : \ ` Bearer \ ${ process . env . NOTION_API_KEY } \` ,
'Notion-Version' : '2022-06-28' ,
'Content-Type' : 'application/json' ,
} ,
body : JSON.stringify ( { query : args.query } ) ,
} ) ;
const data = await res . json ( ) ;
return { content : [ { type : 'text' , text : JSON.stringify ( data . results ) } ] } ;
} catch ( err ) {
const msg = err instanceof Error ? err.message : String ( err ) ;
return { content : [ { type : 'text' , text : 'Error: ' + msg } ] , isError : true } ;
}
} ,
) ; ` }
/ >
< DocsH2 id = "rules" > Rules the generator enforces < / DocsH2 >
< DocsList >
< DocsLi > No < Mono > eval < / Mono > , no < Mono > new Function < / Mono > , no < Mono > child_process < / Mono > . The static check rejects the build . < / DocsLi >
< DocsLi > No < Mono > import < / Mono > statements in tool bodies — the runtime injects < Mono > fetch < / Mono > , < Mono > pg < / Mono > , < Mono > z < / Mono > . < / DocsLi >
< DocsLi > Secrets live in < Mono > process . env < / Mono > . Never embedded literally . < / DocsLi >
< DocsLi > External HTTP calls must use < Mono > AbortSignal . timeout < / Mono > . Default 10 s . < / DocsLi >
< DocsLi > Database access via < Mono > pg < / Mono > with parameterized queries only . < / DocsLi >
< DocsLi > Errors return as MCP error - content , not thrown exceptions . < / DocsLi >
< / DocsList >
< DocsH2 id = "patterns" > Prompt patterns that work < / DocsH2 >
< DocsP >
< strong > Be explicit about tool names . < / strong > "Tool: <Mono>search_pages(query)</Mono>"
beats "give me a search tool" .
< / DocsP >
< DocsP >
< strong > Name the credentials . < / strong > "Auth: <Mono>NOTION_API_KEY</Mono>" tells the
generator what to put in < Mono > requiredSecrets < / Mono > . Saves an iteration .
< / DocsP >
< DocsP >
< strong > Say if a tool is destructive . < / strong > " Tool : < Mono > delete_page ( page_id ) < / Mono > —
destructive , permanently removes the page " surfaces the warning to the AI client .
< / DocsP >
< DocsP >
< strong > One server per integration , not per tool . < / strong > A Notion server with five
tools is cleaner than five Notion servers each with one tool .
< / DocsP >
< DocsH2 id = "iteration" > Iterate on a live server < / DocsH2 >
< DocsP >
Open the server detail page , click the < Mono > Iterate < / Mono > tab , describe what you want
to add . A new build version is queued , rolling - deployed , the old version stays live until
the new one is healthy .
< / DocsP >
< / >
) ;
}