- name
- new-doc-page
- description
- Create a new documentation page for the Harness 3.0 docs site. Use when adding a new doc page, creating documentation, or when asked to add a page to the docs. Handles all three required file registrations and generates the page component.
- argument-hint
- <page-slug> <section-slug> [page-title]
- allowed-tools
- Read, Edit, Write, Grep, Glob, Bash(npx tsc --noEmit)
# Create a New Documentation Page
Create a new documentation page with slug `$0` in section `$1`, with optional title `$2`.
You MUST complete all three registration steps plus create the component file. Missing any step will break navigation.
## Step 1: Gather context
1. Read `lib/docs-data.ts` to understand the existing sections and find where to add the new item.
2. Read `components/docs/page-content.tsx` to see the import and registration patterns.
3. If `$2` (title) is not provided, derive a readable title from the slug by converting kebab-case to Title Case.
## Step 2: Register in `lib/docs-data.ts`
Add the new item to the correct section in the `docSections` array:
```typescript
{
title: "<Page Title>",
slug: "<page-slug>",
description: "<Short description of what this page covers>",
badge: "new",
}
```
Then add TOC entries in the `tocByPage` record. Always include an "Overview" entry first, then add section entries based on the content plan:
```typescript
"<page-slug>": [
{ title: "Overview", id: "overview" },
{ title: "Section Name", id: "section-id" },
],
```
## Step 3: Register in `components/docs/page-content.tsx`
Add the import at the top with the other page imports:
```typescript
import { PageNamePage } from "@/components/docs/pages/<page-slug>"
```
Add the entry in the `pageComponents` record (maintain alphabetical order by slug):
```typescript
"<page-slug>": PageNamePage,
```
**Naming conventions:**
- File name: `<page-slug>.tsx` (exception: if the slug conflicts with a reserved name like "settings", use `<slug>-page.tsx`)
- Export name: PascalCase of slug + "Page" (e.g., `ci-steps` → `CiStepsPage`)
## Step 4: Create the page component
Create the file at `components/docs/pages/<page-slug>.tsx` following this exact structure:
```tsx
import { Separator } from "@/components/ui/separator"
import { CodeBlock } from "@/components/docs/code-block"
import { Callout } from "@/components/docs/callout"
import { Badge } from "@/components/ui/badge"
import { Clock } from "lucide-react"
interface PageNamePageProps {
onNavigate?: (section: string, item: string) => void
}
export function PageNamePage({ onNavigate }: PageNamePageProps) {
return (
<div className="space-y-0">
{/* Header */}
<header id="overview" className="mt-6 scroll-mt-20">
<div className="flex items-center gap-3">
<Badge variant="secondary" className="text-xs">
Section Category
</Badge>
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
<Clock className="h-3 w-3" />
<span>Last updated Mar 2026</span>
</div>
</div>
<h1 className="mt-3 text-balance text-3xl font-bold tracking-tight text-foreground lg:text-4xl">
Page Title
</h1>
<p className="mt-3 max-w-2xl text-pretty text-base leading-relaxed text-muted-foreground lg:text-lg">
Description paragraph explaining what this page covers.
</p>
</header>
<Separator className="my-8" />
{/* Each section MUST have id + scroll-mt-20 for TOC linking */}
<section id="section-id" className="scroll-mt-20">
<h2 className="text-xl font-semibold text-foreground">Section Title</h2>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
Section content.
</p>
</section>
<Separator className="my-8" />
</div>
)
}
```
### Component usage rules
**CodeBlock** — for YAML/code examples:
```tsx
<CodeBlock code={`code here`} language="yaml" filename="pipeline.yaml" showLineNumbers={true} highlightLines={[2, 5]} />
```
**Callout** — for info/warning/tip/success boxes:
```tsx
<Callout type="info" title="Title" className="mt-4">Content here.</Callout>
```
**Tables** — wrap in overflow container:
```tsx
<div className="mt-4 overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-border">
<th className="px-3 py-2 text-left font-semibold text-foreground">Header</th>
</tr>
</thead>
<tbody className="text-muted-foreground">
<tr className="border-b border-border">
<td className="px-3 py-2 font-medium text-foreground">Label</td>
<td className="px-3 py-2">Value</td>
</tr>
</tbody>
</table>
</div>
```
**Bullet lists:**
```tsx
<ul className="mt-2 space-y-1.5 text-sm text-muted-foreground">
<li className="flex items-start gap-2">
<span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-primary" />
Item text
</li>
</ul>
```
**Inline code:**
```tsx
<code className="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">code</code>
```
**Cross-page links** — use the `onNavigate` prop:
```tsx
<span className="cursor-pointer text-primary hover:underline" onClick={() => onNavigate?.("section-slug", "page-slug")}>
Link text
</span>
```
**External links:**
```tsx
<a href="https://..." target="_blank" rel="noopener noreferrer" className="inline-flex items-center gap-1 text-primary hover:underline">
Link text <ExternalLink className="h-3 w-3" />
</a>
```
### YAML convention
All Harness pipeline YAML examples MUST use the v1 schema:
- No `projectIdentifier`, `orgIdentifier`, or `identifier` fields
- Flat stage types: `type: deploy` or `type: ci`
- Steps use `with:` (not `spec:`)
- Expression syntax: `${{ expression }}` with snake_case
## Step 5: Create markdown backup
Create a markdown backup file at `docs/<section-slug>/<page-slug>.md`.
The section-slug to directory mapping:
- `getting-started` → `docs/getting-started/`
- `pipeline-spec` → `docs/pipeline-spec/`
- `connectors` → `docs/connectors/`
- `secrets` → `docs/secrets/`
- `platform` → `docs/platform/`
- `harness-code` → `docs/harness-code/`
- `step-library` → `docs/step-library/`
- `agents` → `docs/agents/`
- `dashboards` → `docs/dashboards/`
- `roadmap` → `docs/roadmap/`
The markdown file must contain:
```markdown
---
title: "Page Title"
description: "Short description"
section: "Section Name"
slug: "page-slug"
---
# Page Title
*Section Category | Last updated Mar 2026*
All page content converted to standard markdown...
```
Conversion from TSX to markdown:
- h1/h2/h3 → `#`/`##`/`###`
- `<CodeBlock>` → fenced code block with language (add filename as comment above if present)
- `<Callout type="info" title="Title">` → `> **Info: Title**\n> content`
- `<Callout type="warning">` → `> **Warning: Title**`
- `<Callout type="tip">` → `> **Tip: Title**`
- `<Callout type="success">` → `> **Success: Title**`
- Tables → standard markdown tables
- Bullet lists → `- item`
- Inline `<code>` → backtick code
- Cross-page `onNavigate` links → `[text](../section-slug/page-slug.md)`
- External links → `[text](url)`
## Step 6: Validate
1. Run `npx tsc --noEmit` to verify no type errors.
2. Verify the TOC entry `id` values exactly match the `id` attributes on sections in the page component.
3. Verify the page is registered in all four locations (docs-data, page-content, component, markdown backup).
## Critical rules
- Every `<section>` must have both `id` and `className="scroll-mt-20"` for anchor linking
- The header section always uses `id="overview"`
- Use `<Separator className="my-8" />` between sections
- Badge text in the header should match the parent section name
- The `"Last updated"` date should be the current month and year
- Import only the Lucide icons you actually use
- Do NOT add unused imports
Auf GitHub ansehen