--- name: cm-project-bootstrap description: Use when starting any new project from scratch. Asks for project identity (name, GitHub org, Cloudflare account), detects project type, sets up design system, staging+production, i18n from day 1, SEO foundation, AGENTS.md manifest, test infrastructure, 8-gate deploy pipeline, and disciplined development workflows. Prevents wrong deploys, redundant repos, and technical debt from day 0. --- # ๐๏ธ Cody Master Project Bootstrap v2.0 > **Every project starts here. No exceptions.** > Inspired by best practices from Amp, Claude Code, Cursor, Lovable, and Manus agents. ## Core Principles ``` ASK FIRST. BUILD SECOND. NEVER ASSUME IDENTITY. STAGING IS MANDATORY. PRODUCTION IS EARNED. I18N FROM DAY 1. NOT "LATER." DESIGN SYSTEM BEFORE COMPONENTS. TOKENS BEFORE PIXELS. SEO IS NOT AN AFTERTHOUGHT. IT'S INFRASTRUCTURE. EVERY PROJECT GETS AN AGENTS.MD. NO EXCEPTIONS. ``` --- ## 11-Phase Bootstrap Process ``` Phase 0: Identity Lock โ WHO are you deploying as? Phase 0.5: Security Foundation โ HOW do we prevent secret leaks? Phase 1: Project Type Detection โ WHAT kind of project? Phase 2: Repository & Environments โ WHERE does code live? Phase 3: Design System Foundation โ HOW does it look? Phase 4: i18n From Day 1 โ WHICH languages? Phase 5: SEO Foundation โ HOW will people find it? Phase 6: AGENTS.md + Git Safety โ HOW do agents collaborate? Phase 7: Test Infrastructure โ HOW do we catch bugs? Phase 8: Deploy Pipeline (8 Gates) โ HOW does code ship? Phase 9: Development Workflow โ HOW do we work daily? ``` --- ## Phase 0: Identity Lock ๐ > **MANDATORY. Cannot proceed without this.** > **Values are NOT hardcoded โ check history, suggest, let user confirm.** ### Step 1: Check Identity History Before asking anything, check if `~/.cm-identity-history.json` exists. If it does, load previous identities and **suggest** the most recently used values. ```json // ~/.cm-identity-history.json โ Auto-maintained across projects { "lastUsed": "2026-03-17", "identities": [ { "github": { "org": "my-work-org" }, "cloudflare": { "accountId": "abc123def456ghi789jkl012mno345pqr" }, "i18n": { "primary": "en", "targets": ["es", "fr", "de"] }, "usedCount": 5, "lastProject": "my-awesome-project", "lastUsed": "2026-03-17" } ] } ``` ### Step 2: Ask with Suggestions Present the 6 questions, pre-filling from history where available. User only needs to **confirm or change**: ``` ๐ NEW PROJECT โ Identity Setup (Values from your last project shown as suggestions) 1. Project name (kebab-case): ___________ 2. GitHub org [my-work-org]: โ Enter to keep, or type new 3. Cloudflare ID [abc12...5pqr]: โ Enter to keep, or type new 4. Domain: ___________ 5. Primary language [en]: โ Enter to keep, or type new 6. Target languages [es, fr, de]: โ Enter to keep, or type new ``` > **RULE:** Never assume. Always show. Let user confirm. > If no history exists, ask all 6 from scratch. ### Step 3: Verify Identity ``` โ ๏ธ BEFORE PROCEEDING โ CONFIRM: ๐ GitHub Org: {org} โ๏ธ Cloudflare: {accountId} ๐ Domain: {domain} ๐ฃ๏ธ Languages: {primary} (primary), {targets} โ Correct? โ proceed โ Wrong? โ fix before continuing ``` ### Step 4: Create `.project-identity.json` ```json { "projectName": "{name}", "github": { "org": "{org}", "repo": "{name}" }, "cloudflare": { "accountId": "{accountId}", "projectName": "{name}", "productionBranch": "production" }, "domain": { "production": "{domain}", "staging": "staging.{domain}" }, "i18n": { "primary": "{primary}", "targets": ["{targets}"] }, "createdAt": "{date}", "bootstrapVersion": "2.0" } ``` ### Step 5: Save to History After creating `.project-identity.json`, update `~/.cm-identity-history.json`: - Add or update the identity entry - Increment `usedCount` - Update `lastProject` and `lastUsed` - This ensures **next project** gets pre-filled suggestions automatically > Call `cm-identity-guard` to verify git config matches the GitHub org BEFORE any git push. --- ## Phase 0.5: Security Foundation ๐ก๏ธ > **NEW โ Defense-in-depth from day 0. Secrets leak at project start when security is "later."** > **Calls `cm-secret-shield` for setup.** ### Step 1: Create `.gitleaks.toml` Create project-level Gitleaks configuration: ```toml # .gitleaks.toml โ Secret Shield Config title = "CM Secret Shield" [extend] useDefault = true [[rules]] id = "supabase-service-key" description = "Supabase Service Role Key" regex = '''eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+''' tags = ["supabase", "jwt"] [[rules]] id = "generic-high-entropy" description = "High entropy string that may be a secret" regex = '''(?i)(api[_-]?key|secret[_-]?key|access[_-]?token|private[_-]?key|auth[_-]?token)\s*[=:]\s*['"][a-zA-Z0-9/+=]{20,}['"]''' tags = ["generic"] [allowlist] paths = ['''\.gitleaks\.toml$''', '''\.dev\.vars\.example$''', '''node_modules/''', '''dist/'''] ``` ### Step 2: Setup Pre-Commit Hook ```bash # Install git pre-commit hook for secret scanning mkdir -p .git/hooks cat > .git/hooks/pre-commit << 'EOF' #!/bin/sh echo "๐ก๏ธ Secret Shield: scanning staged files..." if command -v gitleaks &> /dev/null; then gitleaks git --pre-commit --staged --verbose if [ $? -ne 0 ]; then echo "โ SECRET DETECTED! Commit blocked." exit 1 fi echo "โ No secrets detected" else echo "โ ๏ธ Gitleaks not installed. Running basic checks..." STAGED=$(git diff --cached --name-only --diff-filter=ACM) PATTERNS="SERVICE_KEY|ANON_KEY|PRIVATE_KEY|DB_PASSWORD|SECRET_KEY|sk-[a-zA-Z0-9]{20,}" for file in $STAGED; do if echo "$file" | grep -qE '\.(js|ts|json|toml|yaml|env)$'; then if git diff --cached "$file" | grep -qE "$PATTERNS"; then echo "โ Potential secret in: $file" exit 1 fi fi done echo "โ Basic check passed" fi EOF chmod +x .git/hooks/pre-commit ``` ### Step 3: Add Security Script Add to `package.json`: ```json { "scripts": { "security:scan": "node scripts/security-scan.js || echo 'Create scripts/security-scan.js from cm-secret-shield'" } } ``` ### Step 4: Create `.dev.vars.example` ```bash # .dev.vars.example โ Template for local secrets (committed to repo) # Copy to .dev.vars and fill in real values SUPABASE_URL=https://YOUR_PROJECT.supabase.co SUPABASE_SERVICE_KEY=your_service_key_here SUPABASE_ANON_KEY=your_anon_key_here ``` > **RULE:** `.dev.vars` = real secrets (gitignored). `.dev.vars.example` = template (committed). --- ## Phase 1: Project Type Detection ๐ > **Detect project type โ auto-select the right stack.** > **Default UI: shadcn/ui + Tailwind. Default layout: Mobile-first.** > **Unless user explicitly requests otherwise.** ### Step 1: Ask Project Type Present these options to the user: | Type | When to use | Stack | |------|------------|-------| | **A. Static Website** | Docs, landing pages, portfolios | HTML + vanilla JS + CSS | | **B. SPA (Vite)** | Dashboards, apps with client routing | Vite + React + TypeScript + **shadcn/ui** | | **C. Cloudflare Workers** | APIs, backends, serverless functions | Hono + wrangler + TypeScript | | **D. Fullstack (Workers + SPA)** | Complete apps with API + frontend | Hono + Vite + React + **shadcn/ui** | | **E. Content Site (Astro)** | Blogs, docs, content-heavy sites | Astro + MDX | ### UI Library Default Rules ``` ๐จ DEFAULT UI LIBRARY: shadcn/ui + Tailwind CSS ๐ฑ DEFAULT LAYOUT: Mobile-first responsive These defaults apply UNLESS user explicitly says otherwise. Examples of overrides: - "Use Ant Design" โ switch to Ant Design - "No mobile needed" โ skip mobile optimization - "Desktop only" โ desktop-first layout If user says nothing about UI โ use shadcn/ui + mobile-first. ``` ### Step 2: Scaffold Based on Type #### Type A: Static Website ```bash mkdir -p public/static/{css,js,img} src tests/unit docs touch public/index.html public/static/css/design-tokens.css public/static/css/style.css public/static/js/app.js ``` #### Type B: SPA (Vite) โ with shadcn/ui ```bash # Check available options first npx -y create-vite@latest --help # Scaffold React + TypeScript npx -y create-vite@latest ./ --template react-ts # Install Tailwind CSS npm install -D tailwindcss @tailwindcss/vite # Install and init shadcn/ui npx -y shadcn@latest init ``` #### Type C: Cloudflare Workers ```bash npm init -y npm install hono wrangler --save-dev mkdir -p src tests/unit touch src/index.ts wrangler.jsonc ``` #### Type D: Fullstack โ with shadcn/ui ```bash # Workers backend + Vite frontend in one repo mkdir -p api/src frontend/src tests/{unit,integration} npm init -y npm install hono wrangler --save-dev cd frontend && npx -y create-vite@latest ./ --template react-ts npm install -D tailwindcss @tailwindcss/vite npx -y shadcn@latest init ``` #### Type E: Astro ```bash npx -y create-astro@latest --help npx -y create-astro@latest ./ --template blog --typescript strict ``` ### Step 3: Install Common Dependencies For ALL project types: ```bash npm install --save-dev vitest ``` ### Step 4: Mobile-First Setup For ALL projects with UI, enforce mobile-first from scaffold: ```css /* Mobile-first media queries โ ALWAYS start from mobile */ /* Default styles = mobile (< 640px) */ /* sm: 640px+ */ @media (min-width: 640px) { } /* md: 768px+ */ @media (min-width: 768px) { } /* lg: 1024px+ */ @media (min-width: 1024px) { } /* xl: 1280px+ */ @media (min-width: 1280px) { } ``` ``` ๐ฑ MOBILE-FIRST RULES: 1. Default CSS = mobile layout (no media query needed) 2. Add complexity with min-width media queries 3. Touch targets minimum 44x44px 4. Test on 375px width (iPhone SE) as baseline 5. Navigation: bottom nav or hamburger on mobile 6. Tables: horizontal scroll or card layout on mobile 7. Forms: single column, full width inputs on mobile ``` --- ## Phase 2: Repository & Environments ๐ ### Step 1: Initialize Git ```bash git init git checkout -b main ``` ### Step 2: Create Staging + Production Branches ```bash # main = staging (default) # production = production only git checkout -b production git checkout main ``` ### Step 3: Configure Cloudflare Pages ```bash npx wrangler pages project create PROJECT_NAME --production-branch production ``` ### Step 4: Add Deploy Scripts to package.json ```json { "scripts": { "deploy:staging": "npx wrangler pages deploy ./public --project-name=PROJECT_NAME --branch=main", "deploy:production": "npx wrangler pages deploy ./public --project-name=PROJECT_NAME --branch=production", "test": "vitest run", "test:gate": "npm run test" } } ``` > Adjust `./public` to match your build output directory based on project type. ### Step 5: Create `.gitignore` (Hardened) ```gitignore # === Secret Shield: Mandatory Ignores === # Environment & secret files .env .env.* !.env.example !.env.test .dev.vars !.dev.vars.example .secret-lifecycle.json # Platform-specific secrets *.pem *.key *.p12 # Build & dependencies node_modules/ dist/ .wrangler/ .next/ # OS & IDE .DS_Store *.log ``` --- ## Phase 3: Design System Foundation ๐จ > **Design tokens BEFORE components. Semantic naming ALWAYS.** > **Saved per brand โ consistent across ALL projects of the same user/company.** > **shadcn/ui components as default. Mobile-first always.** ### Step 0: Check for Existing Brand Profile Before creating a new design system, check if `~/.cm-design-profiles/` exists. If the user has a previous design profile, **reuse it** for brand consistency. ```json // ~/.cm-design-profiles/{org-name}.json // Auto-saved after first project. Reused for all future projects. { "orgName": "my-work-org", "brand": { "name": "Acme Corp", "industry": "technology", "style": "professional-modern" }, "colors": { "primary": { "50": "#eff6ff", "500": "#3b82f6", "600": "#2563eb", "700": "#1d4ed8" }, "accent": { "500": "#f59e0b" }, "success": "#22c55e", "warning": "#f59e0b", "error": "#ef4444" }, "typography": { "fontFamily": "Inter", "monoFamily": "JetBrains Mono" }, "ui": { "library": "shadcn/ui", "borderRadius": "0.5rem", "darkMode": true }, "lastUpdated": "2026-03-17", "usedInProjects": ["my-awesome-project", "my-frontend-app"] } ``` **Rules:** - If profile exists โ load and apply. Ask user: "Found design profile for {orgName}. Reuse it?" - If no profile โ ask user about brand/industry โ create new profile - After bootstrap, **always save** the design profile to `~/.cm-design-profiles/` - Profile is updated with each new project that uses it ### Step 1: Ask Brand Context (if no profile exists) ``` ๐จ DESIGN SYSTEM SETUP No existing design profile found. Tell me about your brand: 1. Company/Brand name: ___________ 2. Industry: ___________ 3. Style preference: (professional / playful / minimal / bold) 4. Primary brand color (hex): ___________ (or "auto" to suggest) 5. Dark mode needed? (yes / no) [default: yes] 6. UI Library: [shadcn/ui] (Enter to keep, or type alternative) ``` ### Step 2: Create Design Tokens **For shadcn/ui projects (default):** Design tokens are managed through `tailwind.config.ts` and shadcn's CSS variables. Customize `app/globals.css` (or `src/index.css`) with brand colors: ```css @tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { /* === Brand Colors (from profile or user input) === */ --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; --primary: 221.2 83.2% 53.3%; /* โ Brand primary */ --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; --accent: 210 40% 96.1%; --accent-foreground: 222.2 47.4% 11.2%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; --ring: 221.2 83.2% 53.3%; /* โ Brand primary */ --radius: 0.5rem; /* === Additional Semantic Tokens === */ --success: 142.1 76.2% 36.3%; --warning: 37.7 92.1% 50.2%; --info: 221.2 83.2% 53.3%; } .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; --card: 222.2 84% 4.9%; --card-foreground: 210 40% 98%; --popover: 222.2 84% 4.9%; --popover-foreground: 210 40% 98%; --primary: 217.2 91.2% 59.8%; --primary-foreground: 222.2 47.4% 11.2%; --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; --accent: 217.2 32.6% 17.5%; --accent-foreground: 210 40% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; --ring: 224.3 76.3% 48%; } } ``` **For vanilla/static projects:** Create `design-tokens.css` with CSS custom properties (see example in project scaffold). Use the same brand colors from the profile. ### Step 3: Install shadcn/ui Components (SPA/Fullstack projects) Install essential base components: ```bash # Core layout components npx shadcn@latest add button npx shadcn@latest add input npx shadcn@latest add label npx shadcn@latest add card npx shadcn@latest add dialog npx shadcn@latest add dropdown-menu npx shadcn@latest add toast npx shadcn@latest add skeleton ``` > Only install what's needed. Add more components as features require them. ### Step 4: Mobile-First Base Styles ```css /* Always include these mobile-first foundations */ /* Touch-friendly interactive elements */ button, a, [role="button"] { min-height: 44px; min-width: 44px; } /* Responsive container */ .container { width: 100%; padding-inline: 1rem; } @media (min-width: 640px) { .container { padding-inline: 1.5rem; } } @media (min-width: 1024px) { .container { max-width: 1024px; margin-inline: auto; } } @media (min-width: 1280px) { .container { max-width: 1280px; } } /* Safe area for mobile devices */ body { padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); } ``` ### Step 5: Save Design Profile After setting up the design system, **auto-save** to `~/.cm-design-profiles/{org}.json`: - Brand colors, fonts, border radius, UI library preference - Add current project to `usedInProjects` array - Next project with same org โ instant design system reuse ### Design System Rules ``` โ DO: - Use shadcn/ui components as building blocks (SPA/Fullstack) - Use semantic color tokens: bg-primary, text-muted-foreground - Design mobile layout FIRST, then enhance for larger screens - Reuse brand profile from ~/.cm-design-profiles/ - Touch targets: minimum 44x44px - Test at 375px (iPhone SE) as baseline โ DON'T: - Use raw hex colors: color: #333 โ use token - Design desktop-first then "fix" mobile - Create new color palette when brand profile exists - Skip dark mode (enabled by default) - Use fixed widths on mobile: width: 500px - Ignore safe-area-inset on mobile ``` --- ## Phase 4: i18n From Day 1 ๐ > **Keep from v1 โ enhanced to be framework-agnostic.** ### Step 1: Create i18n Engine For **static/vanilla** projects, create `i18n.js`: ```javascript const i18n = { currentLang: 'vi', translations: {}, async init(lang) { this.currentLang = lang || localStorage.getItem('lang') || 'vi'; try { const res = await fetch(`/static/i18n/${this.currentLang}.json`); this.translations = await res.json(); } catch { const fallback = await fetch('/static/i18n/vi.json'); this.translations = await fallback.json(); } this.apply(); }, t(key) { return key.split('.').reduce((obj, k) => obj?.[k], this.translations) || `[${key}]`; }, apply() { document.querySelectorAll('[data-i18n]').forEach(el => { el.textContent = this.t(el.dataset.i18n); }); document.querySelectorAll('[data-i18n-placeholder]').forEach(el => { el.placeholder = this.t(el.dataset.i18nPlaceholder); }); document.documentElement.lang = this.currentLang; }, async switchTo(lang) { localStorage.setItem('lang', lang); await this.init(lang); } }; ``` For **React/Vite** projects, use `react-i18next`: ```bash npm install i18next react-i18next i18next-browser-languagedetector ``` For **Astro** projects, use `astro-i18n` or manual routing. ### Step 2: Create Language Files ``` i18n/ โโโ vi.json โ Source of truth (primary language) โโโ en.json โโโ th.json โโโ ph.json ``` ### Step 3: i18n Rules ``` โ DO: - Write ALL user-facing strings with t() or data-i18n - Primary language file is source of truth - MAX 30 strings per batch when extracting - Run i18n-sync test after every batch โ DON'T: - Hardcode strings: "Save" โ use t('common.save') - Add 600 strings in one shot โ app crashes - Translate before primary language is complete - Skip audit gates between batches ``` --- ## Phase 5: SEO Foundation ๐ > **NEW โ Learn from Lovable & Cursor: SEO is infrastructure, not afterthought.** ### Step 1: HTML Head Template Every page must include: ```html