- name
- doc-conventions
- description
- Reference guide for Harness 3.0 documentation site conventions, component patterns, and styling rules. Auto-invoked when working on documentation pages, editing components in docs/pages/, or modifying docs-data.ts. Use explicitly to look up the correct pattern for a specific UI element.
- argument-hint
- ["component-name"]
# Harness 3.0 Documentation Conventions
Quick reference for all component patterns and conventions used in the documentation site. If `$ARGUMENTS` is provided, focus on that specific component or pattern.
## Typography scale
| Element | Classes |
|---------|---------|
| Page h1 | `text-3xl font-bold tracking-tight text-foreground lg:text-4xl` |
| Section h2 | `text-xl font-semibold text-foreground` |
| Subsection h3 | `text-base font-semibold text-foreground` (with `mt-6`) |
| Body text | `text-sm leading-relaxed text-muted-foreground` |
| Page description | `text-base leading-relaxed text-muted-foreground lg:text-lg` |
## Page structure
Every page follows this skeleton:
```
<div className="space-y-0">
<header id="overview" className="mt-6 scroll-mt-20">
Badge + Clock + date
h1 title
p description
</header>
<Separator className="my-8" />
<section id="..." className="scroll-mt-20">
h2 + content
</section>
<Separator className="my-8" />
...more sections...
</div>
```
Rules:
- Root div: `className="space-y-0"`
- Header: `id="overview"` with `mt-6 scroll-mt-20`
- Every section: must have `id` + `scroll-mt-20`
- Separators: `<Separator className="my-8" />` between every section
- Props interface: `{ onNavigate?: (section: string, item: string) => void }`
## Component patterns
### CodeBlock
```tsx
<CodeBlock
code={`yaml or code content`}
language="yaml" // "yaml" | "typescript" | "text" | "bash" | etc.
filename="pipeline.yaml" // optional — shows header bar with filename
showLineNumbers={true} // default true
highlightLines={[2, 5]} // optional — 1-indexed lines to highlight
className="mt-4" // optional extra classes
/>
```
Side-by-side comparison:
```tsx
<div className="mt-5 grid gap-4 lg:grid-cols-2">
<CodeBlock code={`...`} language="yaml" filename="before.yaml" />
<CodeBlock code={`...`} language="yaml" filename="after.yaml" />
</div>
```
### Callout
```tsx
<Callout type="info" title="Title" className="mt-4">
Content with <code className="rounded bg-muted px-1 py-0.5 text-xs">inline code</code>.
</Callout>
```
Types and their colors:
- `info` — blue, `Info` icon — general information
- `warning` — orange, `AlertTriangle` icon — caution/important
- `tip` — yellow, `Lightbulb` icon — helpful tip
- `success` — green, `CheckCircle` icon — positive outcome
### Tables
```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>
```
For repetitive tables, define a local sub-component in the same file:
```tsx
function MyTable({ rows }: { rows: Array<{ label: string; value: string }> }) {
return (
<div className="mt-4 overflow-x-auto">
<table className="w-full text-sm">...</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>
```
### Numbered step cards
```tsx
<div className="rounded-lg border border-border bg-card p-4">
<div className="flex items-center gap-3">
<span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary text-xs font-bold text-primary-foreground">1</span>
<h3 className="text-sm font-semibold text-foreground">Step Title</h3>
</div>
<p className="mt-2 pl-10 text-sm text-muted-foreground">Step description.</p>
</div>
```
### Inline code
```tsx
<code className="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">text</code>
```
### Cross-page navigation
```tsx
<span
className="cursor-pointer text-primary hover:underline"
onClick={() => onNavigate?.("section-slug", "page-slug")}
>
Link text
</span>
```
For cards:
```tsx
<div className="cursor-pointer" onClick={() => onNavigate?.("section-slug", "page-slug")}>
<QuickLinkCard title="..." description="..." />
</div>
```
### 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>
```
### Stat cards (grid)
```tsx
<div className="mt-6 grid grid-cols-2 gap-4 sm:grid-cols-4">
<div className="rounded-lg border border-border bg-card p-4 text-center">
<div className="text-2xl font-bold text-primary">100+</div>
<div className="mt-1 text-xs text-muted-foreground">Description</div>
</div>
</div>
```
## Badge conventions
In doc item registrations:
- `"new"` — `bg-accent text-accent-foreground`
- `"beta"` — `bg-primary/15 text-primary`
- `"updated"` — `bg-chart-4/15 text-chart-4`
- `"coming-soon"` — `bg-muted text-muted-foreground`
In page headers, use `<Badge variant="secondary">` for the section category.
## YAML v1 pipeline schema
All Harness pipeline YAML examples MUST use v1 format:
```yaml
# CORRECT v1 format
pipeline:
name: Deploy App
stages:
- name: Deploy to Dev
type: deploy
service: my_service
environment:
name: dev
deploy-to: k8s_dev
steps:
- name: Rolling Deploy
with:
skip_dry_run: false
```
Rules:
- No `projectIdentifier`, `orgIdentifier`, `identifier` — inferred from context
- Flat stage types: `type: deploy` or `type: ci` (NOT `type: Deployment`)
- Steps use `with:` (NOT `spec:`)
- `service` and `environment` are top-level stage fields (NOT `serviceRef`/`environmentRef`)
- Expression syntax: `${{ expression }}` with snake_case (NOT `<+expression>` with camelCase)
## File naming
- Page files: `components/docs/pages/<slug>.tsx`
- Export name: PascalCase of slug + "Page" (e.g., `ci-steps` → `CiStepsPage`)
- Exception: if slug conflicts with reserved names, append `-page` to filename (e.g., `settings` → `settings-page.tsx`)
## Import conventions
Only import what you use. Common imports:
```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"
// Add other lucide icons as needed
```
عرض على GitHub