# CLAUDE.md This repository uses @creo-team/wisdom. Before making changes: 1. Read AGENTS.md 2. Read relevant docs under docs/ai/ 3. Read relevant rules under .claude/rules/ 4. Use relevant skills under .claude/skills/ 5. Use specialist agents under .claude/agents/ when useful 6. Follow the smallest safe diff strategy Do not read .env files unless explicitly required by the user. Do not place secrets in memory, transcripts, comments, docs, tests, or generated examples. Do not make broad rewrites without a plan. # What Is DevOps — Claude Code Instructions ## Project Overview Educational single-page site explaining DevOps principles, practices, culture, and recommended tools. Built by **Creo Design**. Opinionated, sourced, honest — dark aesthetic inspired by cursor.com. **Tech Stack:** Next.js 16, React 19, Tailwind CSS 4, TypeScript 5.9. ## Before Making Changes 1. Generic engineering standards live in the Wisdom docs (`docs/ai/`, `.claude/rules`, `.cursor/rules/`) — this file covers only what is specific to this repo 2. Run the Verification commands below before finishing any change ## Repo-Specific Conventions - **Turbopack** — `next dev --turbopack` for local dev - **Latest stable versions** — dependencies are exact-pinned; Dependabot proposes bumps weekly - **Version bumps are automated** — a husky `post-commit` hook reads the Conventional Commit type and bumps `package.json` + `package-lock.json` via [`scripts/bump-version.mjs`](scripts/bump-version.mjs) (`feat:` → minor, `!` or a `BREAKING CHANGE:` footer → major, every other type → patch; merges skipped), folding the bump into the same commit. This satisfies the wisdom-managed "bump the version with the change" rule — never bump manually, and never put a version number in a commit subject (dependency versions go in the body). Commits made without hooks (server-side merges, Dependabot) ride along until the next hook-enabled commit bumps. The release workflow tags from `package.json` on push to main. This is the single statement of the rule — AGENTS.md defers here - **All user-facing copy lives in [`app/lib/content.ts`](app/lib/content.ts)** — components render from it; nothing user-visible is hardcoded in JSX - **URL state for modals** — `nuqs` with UPPERCASE keys (`OVERLAY`, `TAKE`), `parseAsStringEnum` for enum values, wrapped in `Suspense` with a skeleton fallback ## Design System The dark aesthetic is locked in. Colors are design tokens: CSS variables in [`app/globals.css`](app/globals.css) exposed to Tailwind via `@theme` — components use the utility classes, **never raw hex or rgba values**. `app/globals.css` is the single source of truth for values; the table below maps roles to classes. ### Color Tokens | Utility class | Backing token | Usage | |---------------|---------------|-------| | `bg-canvas` | `--bg-primary` | Page background | | `bg-surface` | `--bg-surface` | Card/surface backgrounds | | `bg-elevated` | `--bg-elevated` | Hover states on surfaces | | `bg-warm` / `text-ink-dark` | `--bg-warm` / `--text-dark` | Primary buttons and their text | | `text-ink` | `--text-primary` | Headings, primary text | | `text-ink-secondary` | `--text-secondary` | Body text, descriptions | | `text-ink-muted` | `--text-muted` | Labels, metadata, section numbers — WCAG AA on all surfaces | | `text-ink-faint` | `--text-faint` | Decorative-only marks (logo accents). Below AA — never for content | | `border-line-subtle` / `bg-line-subtle` | `--border-subtle` | Section dividers, grid gaps | | `border-line-medium` | `--border-medium` | Resting borders on pills/outlines | | `border-line-strong` | `--border-strong` | Hover borders | | `text-opinion` / `bg-opinion-strong` / `bg-opinion-surface` | `--accent-opinion*` | Opinion content (Hot Takes) only — never evidence sections | ### Typography | Utility class | Font | Usage | |---------------|------|-------| | `font-display` | Fraunces | Display headings, hero, logo "DevOps" | | `font-mono` | JetBrains Mono | Section numbers, code, monospace labels | | `font-label` | Inter | Logo "What is" label | | (default) | Geist Sans | Body text | ### Layout Patterns - **Sections**: `py-24 sm:py-32 px-6 border-t border-line-subtle` - **Content width**: `max-w-6xl mx-auto` (full sections), `max-w-3xl` (prose) - **Grid cards**: `gap-px bg-line-subtle rounded-2xl overflow-hidden` with `bg-canvas` children - **Card hover**: `hover:bg-surface transition-colors duration-300` - **Section scaffold**: use [`SectionHeader`](app/components/ui/section-header.tsx); stacked rows use [`StackedRow`](app/components/ui/stacked-row.tsx); CTAs use [`CtaLink`](app/components/ui/cta-link.tsx) (`primary` / `ghost`) - **Copy affordances**: [`CopyOverlay`](app/components/ui/copy-overlay.tsx) on cards; payloads always derive from `content.ts` ### Toast Notifications `react-hot-toast` for all user feedback, hosted in `ToastProvider.tsx` and styled with the tokens. Clipboard and share actions go through [`app/lib/clipboard.ts`](app/lib/clipboard.ts) and [`app/lib/share.ts`](app/lib/share.ts), which guard for unavailable APIs and blocked popups. ### Logo Prompt-style design: `›_` block + "What is" / "DevOps" wordmark. JetBrains Mono prompt, Fraunces italic "DevOps", Inter uppercase "What is". Cursor blinks with `animate-[blink_1.1s_step-end_infinite]` (disabled under reduced motion). Favicons: [`app/icon0.svg`](app/icon0.svg) is the primary SVG favicon (the `›` mark; it necessarily duplicates the `--bg-primary`/`--bg-warm` hex values — update it with any palette change), with `app/icon1.tsx` as the raster fallback for browsers that ignore SVG favicons and `app/apple-icon.tsx` for iOS. ## Trust & Honesty Conventions The site's promise is earned credibility. These rules keep it honest: - **No fake affordances** — never ship a control that implies data capture or state that doesn't exist (no dead vote buttons, no fake counters) - **Copy payloads derive from `content.ts`** — CopyButton text is always composed from the same fields rendered on screen, never hardcoded literals that can drift - **Claims trace to sources** — factual claims link their reference and carry a `` superscript to the anchored References list. Reference lookups go through `getReference(ReferenceKey.X)` — never array indices - **Dates are derived, not hardcoded** — "Content last updated" comes from `NEXT_PUBLIC_CONTENT_UPDATED` (git commit date injected in `next.config.ts`; empty on failure so the committed publication date is the fallback), consumed via `app/lib/content-meta.ts` by the trust section, sitemap, and JSON-LD - **Opinion is labeled** — Hot Takes carries the red opinion marker and "not evidence" framing; volatile claims get an `asOf` date - **Metadata matches the page** — no "comprehensive"/"world-class" claims; titles and descriptions say "opinionated guide" - **Privacy claim must stay true** — the editorial section states there are no analytics/cookies/third-party scripts; adding any requires updating that copy - **Structured data is real** — JSON-LD is `TechArticle` with actual dates and Organization authorship only; never add Review/AggregateRating/FAQ schema ## Page Sections Each section is a server component in [`app/components/sections/`](app/components/sections/), composed in [`app/page.tsx`](app/page.tsx): 1. **Hero** — tagline, byline (author · last updated · reference count), two CTAs 2. **About this guide** — who wrote it and why, up front 3. **Definition** — what DevOps is 4. **History** — origins, key publications 5. **Core Principles** (01) — 6 tenets in a 3-column grid 6. **Misconceptions** — common myths vs reality 7. **Practices** (02) — stacked rows with monospace labels 8. **Feedback Loops** (03) — bug discovery ladder ordered by cost (highest → lowest) 9. **Observability** (04) — audience value cards + patterns rows 10. **Measuring Success** (05) — DORA four keys + Reliability as a visually distinct fifth row (no published DORA threshold) 11. **Driving Change** (06) — playbook steps, starting campaigns, patterns that stick 12. **Recommendations** (07) — clickable cards with accessible modal; no-sponsorship disclosure 13. **For Your AI Agents** (08) — CLAUDE.md, AGENTS.md, DEVOPS.md with raw + GitHub links and copy buttons 14. **DevOps & SRE** (09) — relationship explanation 15. **Hot Takes** — opinionated stances with expand/copy/share; labeled "Opinions — not evidence" 16. **CTA** — three exits: playbook, sources, corrections 17. **Sources** — further reading + anchored references list (`#ref-N`) 18. **About this site** (`#editorial`) — publisher, editorial policy, zero-tracking statement, last-updated date, corrections channel 19. **Footer** — Creo Design copyright, source + version links ## Key File Map | File | Purpose | |------|---------| | `app/page.tsx` | Composes the section components | | `app/components/sections/` | One server component per page section | | `app/lib/content.ts` | All user-facing copy — single source for rendered text and copy payloads | | `app/layout.tsx` | Root layout, fonts, metadata, skip link | | `app/globals.css` | Design tokens, `@theme` mapping, animations, focus/reduced-motion rules | | `app/components/Navigation.tsx` | Nav with active-section state + full-screen mobile contents menu | | `app/components/ui/` | Primitives: `CtaLink`, `SectionHeader`, `StackedRow`, `CopyOverlay`, `Cite`, `InlineLink`, `ExternalLink`, `CopyButton`, `AnchorLink` | | `app/lib/sources-data.ts` | Sources, keyed references (`ReferenceKey`, `getReference`) | | `app/lib/content-meta.ts` | Publication + build-derived last-updated dates | | `app/lib/logger.ts` | Leveled module logger — no bare `console` in app code | | `app/api/raw/[name]/route.ts` | Serves CLAUDE.md/AGENTS.md/DEVOPS.md as plaintext (allow-listed; problem+json errors) | | `app/lib/navigation-data.ts` | `NAV_LINKS` (desktop) + `SECTION_LINKS` (full contents; drift-guarded by test) | | `scripts/` | Commit-msg validation + auto version bump (node --test via `npm run test:version`) | | `DEVOPS.md` | DevOps & security principles for AI agents | | `AGENTS.md` | Quick reference for all AI agents — defers to this file for conventions | ## Footer Every page: © {year} [Creo Design](https://creo.design). Montana Made. {version} `next.config.ts` exposes the `package.json` version as `NEXT_PUBLIC_APP_VERSION`; the footer links it to the GitHub release tag. Standard across Creo TypeScript projects. ## SEO (Vercel) Production: indexed with canonical URLs. Non-production (preview, beta, dev): hidden from crawlers. - **`app/robots.ts`** — Production: allow `/` and `/api/raw/`, disallow `/api/`, sitemap. Non-prod: disallow `/`. - **`app/sitemap.ts`** — Production: URLs with the git-derived last-modified date. Non-prod: `[]`. - **`app/lib/seo.ts`** — `isProductionEnv()`, `getBaseUrl()` (committed `CANONICAL_SITE_URL` in production; `NEXT_PUBLIC_SITE_URL` only as an override), `getArticleJsonLd()`. - **Security headers** — set at one chokepoint in `next.config.ts` (`headers()`). ## Verification ```bash npm run build npm run lint npm run typecheck npm test npm run test:version npx wisdom check ```