From 18c15a6437431abff8403a91617143c0c34c0580 Mon Sep 17 00:00:00 2001 From: Juan Date: Thu, 16 Apr 2026 13:04:38 -0500 Subject: [PATCH] design system token v0.7 --- README.md | 57 +++- mcp/server.ts | 150 ++++++++++ public/gh - logo - offblack.svg | 1 + public/gh - logo - positive - full black.svg | 1 + public/gh - logo - white.svg | 1 + public/gh - symbol - full black.svg | 1 + public/gh - symbol - full white.svg | 1 + public/greyproxy - positive.svg | 1 + public/greywall - positive.svg | 1 + scripts/generate-skill.ts | 73 ++++- skill/AGENTS.brand.md | 110 ++++++++ skill/BRAND.md | 273 +++++++++++++++++++ skill/install.sh | 123 ++++++++- 13 files changed, 768 insertions(+), 25 deletions(-) create mode 100644 public/gh - logo - offblack.svg create mode 100644 public/gh - logo - positive - full black.svg create mode 100644 public/gh - logo - white.svg create mode 100644 public/gh - symbol - full black.svg create mode 100644 public/gh - symbol - full white.svg create mode 100644 public/greyproxy - positive.svg create mode 100644 public/greywall - positive.svg create mode 100644 skill/AGENTS.brand.md create mode 100644 skill/BRAND.md diff --git a/README.md b/README.md index 8ef8249..2bb717f 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,11 @@ greyhaven-design-system/ │ ├── radii.json │ ├── shadows.json │ └── motion.json -├── skill/ # Claude Skill (auto-generated) -│ ├── SKILL.md -│ └── install.sh +├── skill/ # AI skills +│ ├── SKILL.md # Design system reference (auto-generated) +│ ├── AGENTS.md # Project instructions (auto-generated) +│ ├── BRAND.md # Voice/tone/messaging (hand-curated, opt-in) +│ └── install.sh # Installer (supports --brand-skill flag) ├── mcp/ # MCP server for AI agents │ └── server.ts ├── stories/ # Storybook stories (23 files, 8 categories) @@ -55,20 +57,25 @@ greyhaven-design-system/ ## Using the Design System with AI -The design system provides three things for AI agents: +The design system provides four things for AI agents: | File | What it is | Where it goes | |------|-----------|---------------| | **SKILL.md** | Full design system reference (tokens, all components, composition rules, extension protocol) | `.claude/skills/` — works in Claude Code, Cursor, OpenCode, Anigravity, etc. | | **AGENTS.md** | Short project instructions telling the AI *how* to use the design system (follows the [agents.md](https://agents.md) convention) | Project root — copy as `AGENTS.md`, `CLAUDE.md`, `.cursorrules`, or `.github/copilot-instructions.md` | -| **MCP Server** | Runtime tools for looking up components, validating colors, suggesting components | Configured in `.mcp.json` | +| **BRAND.md** *(opt-in)* | Voice/tone/messaging rules for generating marketing copy, CTAs, product explanations. Hand-curated from the brand guidelines. | `.claude/skills/greyhaven-brand.md` — opt in via `--brand-skill` flag | +| **MCP Server** | Runtime tools for looking up components, validating colors, suggesting components, fetching brand rules, validating copy | Configured in `.mcp.json` | -All are auto-generated from the same sources (`tokens/*.json` and `lib/catalog.ts`). +SKILL.md and AGENTS.md are auto-generated from `tokens/*.json` and `lib/catalog.ts`. BRAND.md is hand-curated from `vibedocs/greyhaven-brand-system.md`. ### Quick Install (all at once) ```bash +# Default: SKILL.md + AGENTS.md + fonts ./skill/install.sh /path/to/your/project + +# With brand skill: also install BRAND.md + logo SVGs +./skill/install.sh /path/to/your/project --brand-skill ``` This **copies** (not symlinks) the following into your project: @@ -76,6 +83,11 @@ This **copies** (not symlinks) the following into your project: 2. `AGENTS.md` → project root (project-level instructions) 3. Aspekta font files → `public/fonts/` +With `--brand-skill`, additionally: + +4. `BRAND.md` → `.claude/skills/greyhaven-brand.md` (voice/tone/messaging) +5. Logo SVGs → `public/logos/` (file names normalized: `gh-logo-positive-full-black.svg`, `gh-symbol-full-black.svg`, etc.) + The script also prints the CSS `@font-face` block and MCP server config to add next. **Re-run the script after design system updates** to refresh your copies. @@ -119,9 +131,34 @@ cp /path/to/greyhaven-design-system/skill/AGENTS.md /path/to/your/project/.githu Or use the install script, which copies `AGENTS.md` to the project root automatically. +### BRAND.md (voice, tone, messaging) + +BRAND.md is an **opt-in** skill for projects that generate user-facing content — marketing copy, landing pages, CTAs, product explanations, emails. It codifies the Greyhaven brand voice: direct, plain-spoken, engineering-flavored, no hype, no sales language. + +It's **not installed by default** because most projects only need the design system components, not brand voice rules. + +**Install via the `--brand-skill` flag:** + +```bash +./skill/install.sh /path/to/your/project --brand-skill +``` + +This adds: +- `skill/BRAND.md` → `.claude/skills/greyhaven-brand.md` (brand skill) +- Greyhaven logo SVGs → `public/logos/` (full logos + symbol-only + product lockups, in black and white variants, file names normalized) + +Once installed, AI agents in your project can reference the brand skill when generating copy. The skill covers: +- Core positioning and the three brand axes (containment, human-centered, engineered) +- Tone of voice rules +- Writing patterns (plain-language engineering, no hype) +- Reasoning patterns (cause→effect, constraint→outcome, observation→explanation, finite scope→concrete result) +- CTA guidance (good vs. bad patterns) +- Logo usage rules +- A self-check list to run before shipping any copy + ### Option C: MCP Server -The MCP server provides 5 tools for programmatic access: +The MCP server provides 7 tools for programmatic access: | Tool | Description | |------|-------------| @@ -130,8 +167,10 @@ The MCP server provides 5 tools for programmatic access: | `list_components(category?)` | Lists components (all, or by: primitives, layout, overlay, navigation, data, feedback, form, composition) | | `validate_colors(code)` | Checks code for raw hex values that should use design tokens | | `suggest_component(description)` | Suggests components for a described UI need | +| `get_brand_rules(section?)` | Returns brand voice/tone/messaging rules. Section can be: `positioning`, `axes`, `tone`, `writing-rules`, `reasoning-patterns`, `cta`, `logo`, `self-check`, or `all` | +| `validate_copy(text)` | Lints marketing copy for hype words, sales language, vague superlatives, urgency framing, and exclamation marks | -Plus resources: `tokens://all` and `component://{name}` for each component. +Plus resources: `tokens://all`, `component://{name}` for each component, and `brand://guidelines` for the full brand skill. **Run directly:** @@ -224,7 +263,7 @@ pnpm build-storybook # Static build | `pnpm storybook` | Storybook dev server on :6006 | | `pnpm build-storybook` | Static Storybook build | | `pnpm tokens:build` | Regenerate CSS/TS/MD from token JSON files | -| `pnpm skill:build` | Regenerate skill/SKILL.md from tokens + catalog | +| `pnpm skill:build` | Regenerate skill/SKILL.md and skill/AGENTS.md from tokens + catalog | | `pnpm mcp:start` | Start the MCP server (stdio transport) | | `pnpm mcp:build` | Type-check MCP server | | `pnpm lint` | Run ESLint | diff --git a/mcp/server.ts b/mcp/server.ts index f334ec1..fcd82ae 100644 --- a/mcp/server.ts +++ b/mcp/server.ts @@ -257,10 +257,160 @@ server.tool( }, ) +// --------------------------------------------------------------------------- +// Brand tools & resources +// --------------------------------------------------------------------------- + +const BRAND_SKILL_PATH = path.join(ROOT, 'skill', 'BRAND.md') + +function readBrandSkill(): string { + try { + return fs.readFileSync(BRAND_SKILL_PATH, 'utf-8') + } catch { + return '(skill/BRAND.md not found — hand-curated brand skill is missing)' + } +} + +server.tool( + 'get_brand_rules', + 'Returns the Greyhaven brand voice, tone, and messaging rules. Use this BEFORE generating any user-facing marketing copy, CTAs, landing page content, or product explanations. Covers positioning, brand axes, tone, writing rules, reasoning patterns, CTA guidance, logo usage, and a self-check list.', + { + section: z + .enum([ + 'all', + 'positioning', + 'axes', + 'tone', + 'writing-rules', + 'reasoning-patterns', + 'cta', + 'logo', + 'self-check', + ]) + .optional() + .describe('Optional section filter. Default returns the full brand skill.'), + }, + async ({ section }) => { + const full = readBrandSkill() + + if (!section || section === 'all') { + return { + content: [{ type: 'text' as const, text: full }], + } + } + + // Section anchors in BRAND.md (markdown H2 headings) + const anchors: Record = { + positioning: /## 2\. Core Positioning[\s\S]*?(?=\n## |\n---)/, + axes: /## 3\. The Three Brand Axes[\s\S]*?(?=\n## |\n---)/, + tone: /## 4\. Tone of Voice[\s\S]*?(?=\n## |\n---)/, + 'writing-rules': /## 5\. Writing Rules[\s\S]*?(?=\n## |\n---)/, + 'reasoning-patterns': /## 6\. Patterns for Reasoning[\s\S]*?(?=\n## |\n---)/, + cta: /## 7\. CTA Guidance[\s\S]*?(?=\n## |\n---)/, + logo: /## 10\. Logo Usage[\s\S]*?(?=\n## |\n---)/, + 'self-check': /## 11\. Self-check[\s\S]*?(?=\n## |\n---)/, + } + + const re = anchors[section] + const match = re ? full.match(re) : null + + if (!match) { + return { + content: [{ + type: 'text' as const, + text: `Section "${section}" not found. Returning full brand skill instead.\n\n${full}`, + }], + } + } + + return { + content: [{ type: 'text' as const, text: match[0] }], + } + }, +) + +server.tool( + 'validate_copy', + 'Checks a piece of user-facing copy against Greyhaven brand rules. Flags hype words, sales language, vague superlatives, and other brand violations. Use on marketing copy, CTAs, headlines, product descriptions before shipping.', + { text: z.string().describe('The copy to validate') }, + async ({ text }) => { + const lower = text.toLowerCase() + + const bannedWords = [ + 'unleash', 'transform', 'revolutionary', 'revolutionize', + 'seamless', 'seamlessly', 'game-changing', 'cutting-edge', + 'next-gen', 'next-generation', 'leverage', 'synergy', 'unlock', + 'supercharge', 'empower', 'empowered', 'unprecedented', + 'best-in-class', 'industry-leading', 'world-class', + 'lightning-fast', 'blazing fast', + ] + + const vagueSuperlatives = [ + 'amazing', 'incredible', 'awesome', 'stunning', 'beautiful', + 'powerful', 'robust', 'cutting edge', 'state-of-the-art', + ] + + const urgencyPhrases = [ + 'limited time', 'act now', "don't miss out", 'hurry', + 'last chance', 'today only', + ] + + const findings: string[] = [] + + for (const w of bannedWords) { + if (lower.includes(w)) { + findings.push(`⚠ Banned hype/sales word: "${w}"`) + } + } + for (const w of vagueSuperlatives) { + if (lower.includes(w)) { + findings.push(`⚠ Vague superlative: "${w}" — replace with specifics`) + } + } + for (const p of urgencyPhrases) { + if (lower.includes(p)) { + findings.push(`⚠ Urgency framing: "${p}" — Greyhaven does not use urgency`) + } + } + + // Exclamation marks + const exclamations = (text.match(/!/g) || []).length + if (exclamations > 0) { + findings.push(`⚠ Found ${exclamations} exclamation mark(s) — Greyhaven copy does not use them`) + } + + if (findings.length === 0) { + return { + content: [{ + type: 'text' as const, + text: 'No obvious brand violations found. Still run the self-check list from get_brand_rules({section: "self-check"}) before shipping.', + }], + } + } + + return { + content: [{ + type: 'text' as const, + text: `Found ${findings.length} potential brand violation(s):\n\n${findings.join('\n')}\n\nFor detailed guidance, call get_brand_rules() or get_brand_rules({section: "tone"}).`, + }], + } + }, +) + // --------------------------------------------------------------------------- // Resources // --------------------------------------------------------------------------- +server.resource('brand://guidelines', 'brand://guidelines', async (uri) => { + return { + contents: [{ + uri: uri.href, + mimeType: 'text/markdown', + text: readBrandSkill(), + }], + } +}) + server.resource('tokens://all', 'tokens://all', async (uri) => { const tokens = getTokens(ROOT) return { diff --git a/public/gh - logo - offblack.svg b/public/gh - logo - offblack.svg new file mode 100644 index 0000000..74c34c9 --- /dev/null +++ b/public/gh - logo - offblack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/gh - logo - positive - full black.svg b/public/gh - logo - positive - full black.svg new file mode 100644 index 0000000..cbf8323 --- /dev/null +++ b/public/gh - logo - positive - full black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/gh - logo - white.svg b/public/gh - logo - white.svg new file mode 100644 index 0000000..93a28e1 --- /dev/null +++ b/public/gh - logo - white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/gh - symbol - full black.svg b/public/gh - symbol - full black.svg new file mode 100644 index 0000000..9b346ff --- /dev/null +++ b/public/gh - symbol - full black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/gh - symbol - full white.svg b/public/gh - symbol - full white.svg new file mode 100644 index 0000000..671f72f --- /dev/null +++ b/public/gh - symbol - full white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/greyproxy - positive.svg b/public/greyproxy - positive.svg new file mode 100644 index 0000000..d643935 --- /dev/null +++ b/public/greyproxy - positive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/greywall - positive.svg b/public/greywall - positive.svg new file mode 100644 index 0000000..da973d7 --- /dev/null +++ b/public/greywall - positive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/scripts/generate-skill.ts b/scripts/generate-skill.ts index 16e8a78..56e4cf9 100644 --- a/scripts/generate-skill.ts +++ b/scripts/generate-skill.ts @@ -332,6 +332,70 @@ If fonts aren't loaded yet, add to your global CSS: ` } +// --------------------------------------------------------------------------- +// Brand addendum (appended to AGENTS.md only when --brand-skill is installed) +// --------------------------------------------------------------------------- + +function buildBrandAddendum(): string { + return `--- + +## Brand Voice and Messaging + +This project generates user-facing content (marketing copy, CTAs, landing pages, product explanations, emails) and MUST follow the Greyhaven brand voice. + +### Brand Rules + +- **Before writing any user-facing copy**, read the brand skill: + - Claude Code / compatible tools: \`.claude/skills/greyhaven-brand.md\` (full voice/tone/messaging reference) + - Or via MCP: call \`get_brand_rules()\` (or a specific section: \`positioning\`, \`axes\`, \`tone\`, \`writing-rules\`, \`reasoning-patterns\`, \`cta\`, \`logo\`, \`self-check\`) +- **Before shipping any user-facing copy**, validate it: + - Via MCP: call \`validate_copy(text)\` to lint for hype words, vague superlatives, urgency framing, and exclamation marks + - Or manually run the 8-item self-check list from the brand skill + +### Core Voice (memorize) + +- **Direct. Plain-spoken technical.** Write like an engineer who explains systems cleanly, without mystique or theatrics. +- **No** hype adjectives (\`revolutionary\`, \`cutting-edge\`, \`seamless\`, \`game-changing\`, \`powerful\`). +- **No** evangelism verbs (\`unleash\`, \`transform\`, \`empower\`, \`supercharge\`, \`unlock\`). +- **No** sales language, urgency framing, exclamation marks. +- **No** jargon for its own sake. Prefer plain words: "where the data goes" over "data paths"; "things the system relies on" over "dependencies". +- **Yes** specifics, causal reasoning, concrete outcomes. + +### The Three Brand Axes + +Copy must land on the correct side of each: +1. **Containment** — systems run inside the perimeter, nothing leaks (not cloud/SaaS narratives) +2. **Human-centered** — built around how people actually work (not around model capabilities) +3. **Engineered** — from real deployments and constraints (not vision-first, theatrical, speculative) + +### Reasoning Patterns to Use + +Structure explanations as: +- **Cause → Effect** +- **Constraint → Outcome** +- **Observation → Explanation** +- **Finite Scope → Concrete Result** + +### CTA Guidance + +- **Good**: "Map your first process", "See how it runs in your environment", "Review the architecture", "Get a working prototype in 48 hours" +- **Avoid**: "Unleash the power of AI", "Transform your business", "Don't miss out!", "Get started today!" + +### Logo Usage + +Logos live in \`public/logos/\` after install. See the brand skill for the full rules (clearspace, minimum sizes, what to avoid). + +- **Full logo** (symbol + wordmark): \`gh-logo-positive-full-black.svg\` (light bg), \`gh-logo-white.svg\` (dark bg), \`gh-logo-offblack.svg\` (warm-neutral) +- **Symbol only**: \`gh-symbol-full-black.svg\`, \`gh-symbol-full-white.svg\` — only when Greyhaven recognition is already established +- **Product lockups**: \`greyproxy-positive.svg\`, \`greywall-positive.svg\` +- **Never**: change opacity, apply new colors, stretch, rotate, apply gradients/shadows, alter the symbol-to-wordmark ratio + +### One-Line Test + +Before writing a sentence, ask: *Would an engineer who understands the system read this and feel it's accurate, direct, and free of hype?* If not, rewrite. +` +} + // --------------------------------------------------------------------------- // Main // --------------------------------------------------------------------------- @@ -347,12 +411,19 @@ function main() { const skillLines = skill.split('\n').length console.log(`skill/SKILL.md generated (${skillLines} lines, ${componentCount()} components)`) - // AGENTS.md + // AGENTS.md (design system only — default) const agent = generateAgent() const agentPath = path.join(outDir, 'AGENTS.md') fs.writeFileSync(agentPath, agent, 'utf-8') const agentLines = agent.split('\n').length console.log(`skill/AGENTS.md generated (${agentLines} lines, ${componentCount()} components)`) + + // AGENTS.brand.md (design system + brand voice addendum — installed via --brand-skill) + const agentBrand = agent + '\n' + buildBrandAddendum() + const agentBrandPath = path.join(outDir, 'AGENTS.brand.md') + fs.writeFileSync(agentBrandPath, agentBrand, 'utf-8') + const agentBrandLines = agentBrand.split('\n').length + console.log(`skill/AGENTS.brand.md generated (${agentBrandLines} lines, ${componentCount()} components)`) } main() diff --git a/skill/AGENTS.brand.md b/skill/AGENTS.brand.md new file mode 100644 index 0000000..812eb98 --- /dev/null +++ b/skill/AGENTS.brand.md @@ -0,0 +1,110 @@ +# Project Instructions + +> **Auto-generated** by the Greyhaven Design System. +> Re-generate: `pnpm skill:build` in the design system repo. +> +> Copy this file to your project root as `AGENTS.md` (standard), `CLAUDE.md`, +> `.cursorrules`, or `.github/copilot-instructions.md` depending on your AI tool. + +This project uses the **Greyhaven Design System**. + +## Rules + +- **ALWAYS use TypeScript** (`.tsx` / `.ts`). NEVER generate plain JavaScript (`.jsx` / `.js`). +- Use the `greyhaven` SKILL.md for full design system context (tokens, components, composition rules). It should be installed at `.claude/skills/greyhaven-design-system.md` or accessible to your AI tool. +- If the `greyhaven` MCP server is available, use its tools: + - `list_components()` to find the right component for a UI need + - `get_component(name)` to get exact props, variants, and usage examples + - `validate_colors(code)` to check code for off-brand colors + - `suggest_component(description)` to get recommendations +- Import components from `components/ui/` (or `@/components/ui/` with path alias) +- Never use raw hex colors -- use semantic Tailwind classes (`bg-primary`, `text-foreground`, `border-border`, etc.) +- Use `font-sans` (Aspekta) for UI elements: buttons, nav, labels, forms +- Use `font-serif` (Source Serif) for content: headings, body text +- Trust the design system's default component variants for accent -- they apply orange at the right scale. Don't apply `bg-primary` to large surfaces, containers, or section backgrounds +- All components are framework-agnostic React (no Next.js, no framework-specific imports) +- Dark mode is toggled via the `.dark` class -- use semantic tokens that adapt automatically + +## Component Summary + +38 components across 8 categories: primitives (11), layout (4), overlay (5), navigation (3), data (4), feedback (4), form (1), composition (6). + +For full component specs, props, and examples, refer to the SKILL.md file or use the MCP `get_component(name)` tool. + +## Key Patterns + +- **CVA variants**: Components use `class-variance-authority` for variant props +- **Slot composition**: Components use `data-slot="name"` attributes +- **Class merging**: Always use `cn()` from `@/lib/utils` (clsx + tailwind-merge) +- **Focus rings**: `focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]` +- **Disabled**: `disabled:pointer-events-none disabled:opacity-50` +- **Card spacing**: `gap-6` between cards, `p-6` internal padding +- **Section rhythm**: `py-16` between major sections +- **Form layout**: Vertical stack with `gap-4`, labels above inputs + +## Font Setup + +If fonts aren't loaded yet, add to your global CSS: +```css +@font-face { font-family: 'Aspekta'; font-weight: 400; font-display: swap; src: url('/fonts/Aspekta-400.woff2') format('woff2'); } +@font-face { font-family: 'Aspekta'; font-weight: 500; font-display: swap; src: url('/fonts/Aspekta-500.woff2') format('woff2'); } +@font-face { font-family: 'Aspekta'; font-weight: 600; font-display: swap; src: url('/fonts/Aspekta-600.woff2') format('woff2'); } +@font-face { font-family: 'Aspekta'; font-weight: 700; font-display: swap; src: url('/fonts/Aspekta-700.woff2') format('woff2'); } +``` + +--- + +## Brand Voice and Messaging + +This project generates user-facing content (marketing copy, CTAs, landing pages, product explanations, emails) and MUST follow the Greyhaven brand voice. + +### Brand Rules + +- **Before writing any user-facing copy**, read the brand skill: + - Claude Code / compatible tools: `.claude/skills/greyhaven-brand.md` (full voice/tone/messaging reference) + - Or via MCP: call `get_brand_rules()` (or a specific section: `positioning`, `axes`, `tone`, `writing-rules`, `reasoning-patterns`, `cta`, `logo`, `self-check`) +- **Before shipping any user-facing copy**, validate it: + - Via MCP: call `validate_copy(text)` to lint for hype words, vague superlatives, urgency framing, and exclamation marks + - Or manually run the 8-item self-check list from the brand skill + +### Core Voice (memorize) + +- **Direct. Plain-spoken technical.** Write like an engineer who explains systems cleanly, without mystique or theatrics. +- **No** hype adjectives (`revolutionary`, `cutting-edge`, `seamless`, `game-changing`, `powerful`). +- **No** evangelism verbs (`unleash`, `transform`, `empower`, `supercharge`, `unlock`). +- **No** sales language, urgency framing, exclamation marks. +- **No** jargon for its own sake. Prefer plain words: "where the data goes" over "data paths"; "things the system relies on" over "dependencies". +- **Yes** specifics, causal reasoning, concrete outcomes. + +### The Three Brand Axes + +Copy must land on the correct side of each: +1. **Containment** — systems run inside the perimeter, nothing leaks (not cloud/SaaS narratives) +2. **Human-centered** — built around how people actually work (not around model capabilities) +3. **Engineered** — from real deployments and constraints (not vision-first, theatrical, speculative) + +### Reasoning Patterns to Use + +Structure explanations as: +- **Cause → Effect** +- **Constraint → Outcome** +- **Observation → Explanation** +- **Finite Scope → Concrete Result** + +### CTA Guidance + +- **Good**: "Map your first process", "See how it runs in your environment", "Review the architecture", "Get a working prototype in 48 hours" +- **Avoid**: "Unleash the power of AI", "Transform your business", "Don't miss out!", "Get started today!" + +### Logo Usage + +Logos live in `public/logos/` after install. See the brand skill for the full rules (clearspace, minimum sizes, what to avoid). + +- **Full logo** (symbol + wordmark): `gh-logo-positive-full-black.svg` (light bg), `gh-logo-white.svg` (dark bg), `gh-logo-offblack.svg` (warm-neutral) +- **Symbol only**: `gh-symbol-full-black.svg`, `gh-symbol-full-white.svg` — only when Greyhaven recognition is already established +- **Product lockups**: `greyproxy-positive.svg`, `greywall-positive.svg` +- **Never**: change opacity, apply new colors, stretch, rotate, apply gradients/shadows, alter the symbol-to-wordmark ratio + +### One-Line Test + +Before writing a sentence, ask: *Would an engineer who understands the system read this and feel it's accurate, direct, and free of hype?* If not, rewrite. diff --git a/skill/BRAND.md b/skill/BRAND.md new file mode 100644 index 0000000..ca551df --- /dev/null +++ b/skill/BRAND.md @@ -0,0 +1,273 @@ +# Greyhaven Brand Voice & Messaging -- Claude Skill + +> **Source of truth**: `vibedocs/greyhaven-brand-system.md` (Brand Guidelines v1.1) +> +> This skill applies when generating ANY user-facing content for Greyhaven: +> marketing copy, landing pages, CTAs, product descriptions, documentation, +> email, README intros, explanations of how the product works, or any prose +> that will be read by a human. It does NOT apply to internal code comments, +> commit messages, or technical logs. + +--- + +## 1. The One-Line Test + +Before writing any sentence, ask: + +> Would an engineer who understands the system read this and feel it's accurate, direct, and free of hype? + +If no, rewrite. That single test catches 90% of brand drift. + +--- + +## 2. Core Positioning (memorize) + +**Greyhaven builds custom, contained AI systems that run entirely inside the client's environment, shaped by real operational constraints and deployed under the client's control.** + +**Short form**: *Local-first AI systems shaped by real work. Built where work happens. Contained end to end.* + +Powered by Monadical's internal, open-source stack, hardened over eight years. + +--- + +## 3. The Three Brand Axes + +Every sentence, heading, or visual choice should land on the correct side of these three axes. When in doubt, use them to explain *why* something is wrong without relying on taste. + +| Axis | Greyhaven is on this side | NOT this side | +|------|---------------------------|---------------| +| **Containment** | Systems run inside the perimeter. Nothing leaks. | Cloud/SaaS narratives. "Connected everywhere." | +| **Human-centered** | Built around how people actually work. | Built around model capabilities or vendor features. | +| **Engineered** | From real deployments, constraints, operator reality. | Vision-first, theatrical, speculative, futuristic. | + +If copy drifts toward **exposure, performance, or model-led thinking → it doesn't fit**. + +--- + +## 4. Tone of Voice + +**Direct. Plain-spoken technical. Explains difficult things in simple terms.** + +Greyhaven speaks like an engineer who understands how systems work and can describe them cleanly -- without mystique or theatrics. + +- **No** jargon for its own sake +- **No** oversimplification +- **No** sales language +- **No** hype adjectives ("revolutionary", "cutting-edge", "seamless", "powerful", "game-changing") +- **No** evangelism ("unleash", "empower", "transform") +- **No** emotional leverage or fear-mongering +- **Yes** calm, precise, explanatory +- **Yes** mechanical facts +- **Yes** specifics over superlatives +- **Yes** authority through clarity, not volume + +--- + +## 5. Writing Rules + +### 5.1 Explain clearly. Don't perform. + +The goal is clarity, not persuasion. Readers have different levels of technical know-how. Describe what happens inside the environment, how data flows, which dependencies matter, what boundaries exist. If something is complex, break it down without dumbing it down. + +### 5.2 Plain-language engineering + +Use everyday words for technical realities. If a simpler word communicates the same thing, use it. + +| Instead of | Prefer | +|-----------|--------| +| "data paths" | "where the data goes" | +| "surfaces" | "places where exposure/risk can happen" | +| "dependencies" | "things the system relies on" | +| "isolation" | "kept separate from the outside" | +| "logs" | "records of what happened" | +| "handoffs" | "when one person/system passes something to another" | +| "leverage" | "use" | +| "leverage AI to..." | "the system uses AI to..." | +| "synergy" | (don't use) | +| "cutting-edge solution" | (don't use) | +| "transform your workflow" | describe what the system does instead | + +Don't assume the reader knows technical shorthand. The reader should leave with a clearer mental model, not an impressed feeling. + +### 5.3 Human-first in how we describe work + +Start from what operators actually do -- steps, judgment calls, knowledge. Explain operator behaviors the same way you explain systems: concretely and without dramatization. + +### 5.4 Security, stated without drama + +Mechanical facts, not alarmism. + +- **Good**: "Running inside the perimeter restores finite boundaries." +- **Bad**: "Protect your data from devastating breaches!" + +State causal reasoning. No emotional leverage. + +### 5.5 Quiet confidence + +State specifics. No hype adjectives. No evangelism. Authority comes from clarity, not volume. + +- **Good**: "A working, testable prototype delivered in 24-48 hours." +- **Bad**: "Lightning-fast, industry-leading AI delivery!" + +--- + +## 6. Patterns for Reasoning + +Use these four patterns to structure explanations. They express engineering logic: minimal wording, direct causality, observable/verifiable outcomes. + +### Cause → Effect +> "When work relies on external AI services, every step -- inputs, outputs, logs, metadata -- becomes part of someone else's infrastructure." + +### Constraint → Outcome +> "No external APIs and no data leaving the environment. The system remains contained, and the client keeps full operational and security control." + +### Observation → Explanation +> "We sit with the operators, map the steps, and build a system that mirrors what actually happens." + +### Finite Scope → Concrete Result +> "One process at a time. A working, testable prototype delivered in 24-48 hours." + +--- + +## 7. CTA Guidance + +Greyhaven CTAs should be concrete and engineering-flavored, not aspirational or urgent. + +**Good CTA patterns**: +- "See how it runs in your environment" +- "Map your first process" +- "Review the architecture" +- "Read how it's deployed" +- "Get a working prototype in 48 hours" + +**Avoid**: +- "Unlock the power of AI" +- "Transform your business today" +- "Don't miss out!" +- "Revolutionary AI solutions await" +- Urgency/scarcity framing ("limited time", "hurry", "act now") +- Hype verbs ("unleash", "supercharge", "revolutionize") + +--- + +## 8. Driving Ideas (use these to self-check) + +A sentence, heading, or design choice should feel like one of these: + +> **(System-)aware · Applied · Adaptable · Unblocking · Safe-to-experiment · Contained · Durable · Iterative** + +If it doesn't land on any of them, or lands somewhere else (flashy, theatrical, aspirational), rewrite. + +--- + +## 9. Typography Approach (for written-content UI) + +Hierarchy is built through **tonal shifts**, not decorative treatments. + +- Primary points stay **dark and controlled** (foreground text) +- Supporting detail **moves lighter** (muted-foreground) +- The orange accent is **reserved** for parts that require immediate attention -- never decorative + +Do NOT establish hierarchy through: +- Multiple contrasting typefaces +- Decorative styles (italics for emphasis, ALL CAPS for drama, oversized type for style) +- Color variety + +DO establish hierarchy through: +- Weight differences within the same family (serif for content, sans for UI) +- Shade shifts between foreground, muted-foreground, and the orange accent +- Spatial rhythm (section padding, line-height) + +This keeps the system quiet, structured, and readable. + +--- + +## 10. Logo Usage + +### Available files (in `public/logos/` after install) + +| File | Use when | +|------|----------| +| `gh-logo-positive-full-black.svg` | Full logo (symbol + wordmark) on light backgrounds | +| `gh-logo-white.svg` | Full logo on dark backgrounds | +| `gh-logo-offblack.svg` | Full logo in off-black (#161614) for warm-neutral contexts | +| `gh-symbol-full-black.svg` | Symbol only, light bg (use when name recognition is already established) | +| `gh-symbol-full-white.svg` | Symbol only, dark bg | +| `greyproxy-positive.svg` | Greyproxy product logo (Greyhaven symbol + product wordmark) | +| `greywall-positive.svg` | Greywall product logo (Greyhaven symbol + product wordmark) | + +### Rules + +- **Structure**: The logo is **Symbol + Wordmark**. Keep them locked together in most contexts. Use the Symbol alone only when Greyhaven name recognition is already assured. +- **Clearspace**: Minimum 1× (one grid module of the symbol) on all sides. Nothing -- text, images, other graphics -- enters this zone. +- **Minimum sizes**: + - Wordmark lockup: 20mm print / 120px digital + - Standalone symbol: 8mm print / 14px digital (22px preferred) + +### What to avoid (all of these are brand violations) + +- Do NOT change opacity +- Do NOT apply new colors (black, white, off-black only -- per file) +- Do NOT stretch or alter proportions +- Do NOT apply gradients, shadows, glows, or other embellishments +- Do NOT rotate +- Do NOT change the lockup or alter symbol/wordmark relative scale + +### Product logos + +New Greyhaven products/demos reuse the Greyhaven symbol with the product wordmark in the same lockup pattern (see `greyproxy-positive.svg`, `greywall-positive.svg`). Typography for new wordmarks: Circular Medium. Do NOT invent a new symbol unless the product genuinely needs its own sub-identity. + +--- + +## 11. Self-check Before Shipping Any Copy + +Run the output through these checks: + +1. ☐ Does it pass **The One-Line Test** (accurate, direct, no hype)? +2. ☐ Does it land on the correct side of all **three brand axes** (containment, human-centered, engineered)? +3. ☐ Did I use any **banned words** (unleash, transform, revolutionary, seamless, game-changing, cutting-edge, leverage, synergy, unlock)? +4. ☐ Is every claim **specific and verifiable**, or am I using vague superlatives? +5. ☐ Does the copy **explain how the thing works**, or just tell the reader how to feel about it? +6. ☐ Does it match a **reasoning pattern** (cause→effect, constraint→outcome, observation→explanation, finite scope→concrete result)? +7. ☐ Does it fit one of the **driving ideas** (system-aware, applied, adaptable, unblocking, safe-to-experiment, contained, durable, iterative)? +8. ☐ Is the orange accent used only where immediate attention is warranted, not as decoration? + +If any box is unchecked, rewrite. + +--- + +## 12. Quick Examples + +### Bad vs. Good: Hero headline + +| Bad | Good | +|-----|------| +| "Unleash the power of AI in your organization" | "AI systems that run inside your environment" | +| "Revolutionary cloud-native AI platform" | "Custom AI, contained end to end" | +| "Transform your workflows with next-gen AI" | "Map one process. Deploy a working prototype in 48 hours." | + +### Bad vs. Good: Feature description + +**Bad**: +> Our cutting-edge AI seamlessly integrates with your existing infrastructure to unlock unprecedented productivity gains. + +**Good**: +> The system runs on the machines you already have. Data, models, and execution stay inside your perimeter. Nothing is sent to external APIs. + +### Bad vs. Good: CTA + +| Bad | Good | +|-----|------| +| "Get started today!" | "Map your first process" | +| "Try it free -- limited time!" | "Review the architecture" | +| "Unlock AI superpowers" | "See a 48-hour prototype" | + +--- + +## 13. When You're Unsure + +Default to: +1. **Fewer words**. Greyhaven copy is shorter than you expect. +2. **More specifics**. Numbers, concrete nouns, named constraints. +3. **Less enthusiasm**. No exclamation marks. No superlatives. No urgency. +4. **Describe the system, not the feeling**. diff --git a/skill/install.sh b/skill/install.sh index 75fc1d4..5fa5b55 100755 --- a/skill/install.sh +++ b/skill/install.sh @@ -4,14 +4,19 @@ # Copies (does NOT symlink) files so the consuming project owns its copies. # Re-run this script to pull updated versions after design system changes. # -# What it does: +# What it does (by default): # 1. Copies SKILL.md into .claude/skills/ (for Claude Code) # 2. Copies AGENTS.md into the project root (standard convention) # 3. Copies Aspekta font files + font-face.css into public/fonts/ # 4. Prints CSS import + MCP setup instructions # +# With --brand-skill: +# 5. Copies BRAND.md into .claude/skills/ (voice, tone, messaging rules) +# 6. Copies Greyhaven logo SVGs into public/logos/ +# # Usage: # ./skill/install.sh /path/to/your/project +# ./skill/install.sh /path/to/your/project --brand-skill set -euo pipefail @@ -19,16 +24,49 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" SKILL_FILE="${SCRIPT_DIR}/SKILL.md" AGENTS_FILE="${SCRIPT_DIR}/AGENTS.md" +AGENTS_BRAND_FILE="${SCRIPT_DIR}/AGENTS.brand.md" +BRAND_FILE="${SCRIPT_DIR}/BRAND.md" FONTS_DIR="${REPO_ROOT}/public/fonts" +PUBLIC_DIR="${REPO_ROOT}/public" -if [ $# -ge 1 ]; then - TARGET_PROJECT="$(cd "$1" && pwd)" -else - echo "Usage: $0 " - echo "" - echo "Example:" - echo " $0 /path/to/my-app" - echo " $0 ." +# Parse arguments +TARGET_PROJECT="" +INSTALL_BRAND=false + +while [ $# -gt 0 ]; do + case "$1" in + --brand-skill) + INSTALL_BRAND=true + shift + ;; + -h|--help) + echo "Usage: $0 [--brand-skill]" + echo "" + echo "Options:" + echo " --brand-skill Also install BRAND.md (voice/tone/messaging) and logo SVGs" + echo "" + echo "Examples:" + echo " $0 /path/to/my-app" + echo " $0 /path/to/my-app --brand-skill" + echo " $0 . --brand-skill" + exit 0 + ;; + *) + if [ -z "$TARGET_PROJECT" ]; then + TARGET_PROJECT="$1" + else + echo "Error: Unexpected argument: $1" + echo "Run '$0 --help' for usage." + exit 1 + fi + shift + ;; + esac +done + +if [ -z "$TARGET_PROJECT" ]; then + echo "Usage: $0 [--brand-skill]" + echo "Run '$0 --help' for details." exit 1 fi @@ -37,13 +75,14 @@ if [ ! -d "$TARGET_PROJECT" ]; then exit 1 fi +TARGET_PROJECT="$(cd "$TARGET_PROJECT" && pwd)" + # Helper: backup existing file/symlink and copy new one copy_with_backup() { local src="$1" local dst="$2" if [ -L "$dst" ]; then - # Remove any existing symlink (leftover from old installs) rm "$dst" elif [ -f "$dst" ]; then mv "$dst" "${dst}.bak" @@ -54,6 +93,9 @@ copy_with_backup() { } echo "Installing Greyhaven Design System into ${TARGET_PROJECT}" +if [ "$INSTALL_BRAND" = true ]; then + echo " (with --brand-skill: BRAND.md + logos)" +fi echo "" # ── 1. SKILL.md ──────────────────────────────────────────────────────────── @@ -68,12 +110,22 @@ else fi # ── 2. AGENTS.md ─────────────────────────────────────────────────────────── -if [ -f "$AGENTS_FILE" ]; then - DST="${TARGET_PROJECT}/AGENTS.md" - copy_with_backup "$AGENTS_FILE" "$DST" - echo "[ok] AGENTS.md: ${DST}" +# Pick the brand-augmented variant if --brand-skill is passed, so agents +# working in the consuming project know how to use the brand skill + MCP tools. +if [ "$INSTALL_BRAND" = true ] && [ -f "$AGENTS_BRAND_FILE" ]; then + AGENTS_SRC="$AGENTS_BRAND_FILE" + AGENTS_LABEL="AGENTS.md (with brand voice addendum)" else - echo "[skip] AGENTS.md not found — run 'pnpm skill:build' first" + AGENTS_SRC="$AGENTS_FILE" + AGENTS_LABEL="AGENTS.md" +fi + +if [ -f "$AGENTS_SRC" ]; then + DST="${TARGET_PROJECT}/AGENTS.md" + copy_with_backup "$AGENTS_SRC" "$DST" + echo "[ok] ${AGENTS_LABEL}: ${DST}" +else + echo "[skip] AGENTS source not found — run 'pnpm skill:build' first" fi # ── 3. Fonts ─────────────────────────────────────────────────────────────── @@ -97,6 +149,47 @@ else echo "[skip] Fonts dir not found at ${FONTS_DIR}" fi +# ── 4. Brand skill (opt-in via --brand-skill) ────────────────────────────── +if [ "$INSTALL_BRAND" = true ]; then + # 4a. BRAND.md into .claude/skills/ + if [ -f "$BRAND_FILE" ]; then + SKILLS_DIR="${TARGET_PROJECT}/.claude/skills" + mkdir -p "$SKILLS_DIR" + DST="${SKILLS_DIR}/greyhaven-brand.md" + copy_with_backup "$BRAND_FILE" "$DST" + echo "[ok] BRAND.md: ${DST}" + else + echo "[skip] BRAND.md not found at ${BRAND_FILE}" + fi + + # 4b. Logo SVGs into public/logos/ + TARGET_LOGOS="${TARGET_PROJECT}/public/logos" + mkdir -p "$TARGET_LOGOS" + + logo_files=( + "gh - logo - positive - full black.svg" + "gh - logo - white.svg" + "gh - logo - offblack.svg" + "gh - symbol - full black.svg" + "gh - symbol - full white.svg" + "greyproxy - positive.svg" + "greywall - positive.svg" + ) + + # Rename files on copy to remove spaces — better for web paths + copied=0 + for f in "${logo_files[@]}"; do + src="${PUBLIC_DIR}/${f}" + if [ -f "$src" ]; then + # "gh - logo - positive - full black.svg" → "gh-logo-positive-full-black.svg" + clean_name=$(echo "$f" | sed 's/ - /-/g; s/ /-/g') + cp "$src" "${TARGET_LOGOS}/${clean_name}" + copied=$((copied + 1)) + fi + done + echo "[ok] Logos: ${copied} SVGs copied to ${TARGET_LOGOS}/ (renamed: spaces → dashes)" +fi + # ── Next steps ───────────────────────────────────────────────────────────── cat <<'EOF'