Your project uses React 18, Vite, Vitest, and Tailwind. But your rules mention Jest patterns, CSS modules conventions, and generic "component" guidance that doesn't account for React's concurrent features. The rules were written for a TypeScript project. Not your TypeScript project.

So you edit. You prune. You customize. Then you add Playwright. Or upgrade to TypeScript 5.4. Or switch from React Query to TanStack Query. Your rules become stale again. You're now maintaining two things: your codebase and the rules that describe it.

What if rules could figure out what stack you're using and generate themselves?


The Problem Today

radar-beta
    title Rule Coverage vs Stack Needs
    axis Testing["Testing"], CSS["CSS/Styling"], Framework["Framework"], Legacy["Legacy Patterns"], Types["TypeScript"], A11y["Accessibility"]
    curve rules["Your Rules"]{2, 4, 2, 5, 3, 1}
    curve needs["Stack Needs"]{5, 2, 5, 1, 4, 3}
    max 5
    min 0

The radar shows the mismatch at a glance. The orange curve is what your stack actually needs; the blue curve is what your rules currently cover.

  • Gaps (orange exceeds blue): Testing, Framework, A11y — your rules don't cover what you actually need
  • Excess (blue exceeds orange): CSS, Legacy — rules you maintain but don't use (CSS Modules when you use Tailwind, class components when you use hooks)
  • Partial coverage: TypeScript rules exist but incomplete

This isn't just missing coverage—it's misaligned coverage. You're spending effort maintaining rules for things you don't use while missing rules for things you do.

Where do these rules come from, and where do they end up?

sankey-beta

Your Effort,Community Templates,30
Your Effort,Existing Rules,40
Your Effort,Custom Rules,30

Community Templates,Mismatched,22
Community Templates,Aligned,8

Existing Rules,Mismatched,30
Existing Rules,Aligned,10

Custom Rules,Not Portable,12
Custom Rules,Aligned,18

Your maintenance effort splits across sources, then flows to outcomes. Of 100 units of effort:

  • 36 → Aligned (actually useful)
  • 52 → Mismatched (rules that don't match your current stack—whether generic templates or outdated patterns)
  • 12 → Not Portable (works for you, breaks for teammates)

64% of your effort is wasted. And the gaps? They're not in the diagram because no effort flows there. While you maintain all this problematic output, the areas you actually need (testing, accessibility, framework patterns) have nothing flowing to them at all.

An adaptive rules engine inverts this. Instead of writing rules and hoping they fit, you analyze the project and generate rules that match what's actually there.

Static Rules Adaptive Rules
Written once, edited forever Generated from project state
Generic patterns Stack-specific guidance
Conflicts with existing config Reads existing config to avoid conflicts
Stale after every dependency change Regenerates on demand

The Three Phases

Adaptive rule generation has three stages: detect what you're working with, generate rules that fit, and validate that nothing conflicts.

flowchart LR
    subgraph DETECT["1. DETECT"]
        D1[Scan Configs]
        D2[Extract Patterns]
        D3[Build Profile]
        D1 --> D2 --> D3
    end
    
    subgraph GENERATE["2. GENERATE"]
        G1[Select Templates]
        G2[Augment Context]
        G3[Compose Rules]
        G1 --> G2 --> G3
    end
    
    subgraph VALIDATE["3. VALIDATE"]
        V1[Check Conflicts]
        V2[Flag Issues]
        V3[Preview Output]
        V1 --> V2 --> V3
    end
    
    DETECT --> GENERATE --> VALIDATE

Phase 1: Detect

Before generating anything, you need to know what's in the repo. This isn't magic—it's reading configuration files systematically.

Source What It Tells You
package.json Framework, test tools, build tools
tsconfig.json Strictness level, target, paths
.eslintrc Existing lint rules and style preferences
vite.config.* Build setup, plugins
tailwind.config.* CSS approach
playwright.config.* E2E setup
.cursor/rules/ Existing rules (to avoid duplicating or conflicting)
src/**/*.{ts,tsx} Actual code patterns and conventions

The output is a stack profile:

stack_profile:
  framework: react@18.2
  build: vite@5.0
  language: typescript@5.3
  strictness: strict
  css: tailwind@3.4
  testing:
    unit: vitest
    e2e: playwright
  patterns_detected:
    - "Functional components with hooks"
    - "Barrel exports"
    - "Feature-based folder structure"
  existing_rules:
    - base/code-quality
    - languages/typescript
  gaps:
    - No CSS/styling rules
    - No testing rules

This is the foundation. Everything else builds on it.

Phase 2: Generate

With the stack profile in hand, generation becomes conditional selection plus augmentation.

flowchart TD
    SP[Stack Profile]:::primary --> SEL{Rule Selector}:::primary
    
    SEL --> R1[react-patterns.md]
    SEL --> R2[vitest-patterns.md]
    SEL --> R3[tailwind-conventions.md]
    SEL -.-> R4[css-modules.md]:::secondary
    
    R1 --> AUG[Augmentation Layer]:::highlight
    R2 --> AUG
    R3 --> AUG
    
    AUG --> OUT[Project-Specific Rules]:::highlight

Selection logic is straightforward:

  • If framework = react, include react-patterns, hooks-rules, jsx-accessibility
  • If testing.unit = vitest, include vitest-patterns
  • If css.approach = tailwind, include tailwind-conventions; skip css-modules rules

Augmentation adds the project-specific layer:

A base rule template might say "Prefer functional components." For React 18 specifically, you augment: "Use React 18 concurrent features when appropriate." For this project specifically, you augment: "Follow existing barrel export convention in /src."

This layering matters. Generic templates become project-specific rules without requiring manual customization.

Phase 3: Validate

Generated rules can conflict with what already exists. Before applying anything, check:

  1. Against existing .cursor/rules/ — Don't duplicate or contradict what's already there
  2. Against .eslintrc rules — Don't tell the AI to do something ESLint will reject
  3. Against tsconfig settings — Don't recommend patterns incompatible with your strictness level
  4. Against detected code patterns — Don't prescribe conventions that contradict what the codebase already does

Conflicts get flagged before they cause problems:

⚠️ Generated rule conflicts with existing lint configuration
   Rule: "Prefer interface over type"
   ESLint: @typescript-eslint/consistent-type-definitions set to "type"
   
   Recommendation: Skip this rule or update ESLint config

What This Looks Like in Practice

Imagine running /generate-rules in a new project:

🔍 Detecting stack...

Stack Profile:
  ├─ Framework: React 18.2 (Vite 5.0)
  ├─ Language: TypeScript 5.3 (strict)
  ├─ CSS: Tailwind 3.4
  ├─ Testing: Vitest + React Testing Library + Playwright
  └─ Patterns: Feature folders, barrel exports, React Query

📋 Rule Selection:
  ├─ ✅ react-patterns (framework detected)
  ├─ ✅ typescript-strict (tsconfig strict: true)
  ├─ ✅ tailwind-conventions (tailwind.config found)
  ├─ ✅ vitest-testing (vitest in devDeps)
  ├─ ✅ playwright-e2e (playwright.config found)
  ├─ ⏭️ css-modules (skipped - using Tailwind)
  └─ ⏭️ jest-testing (skipped - using Vitest)

⚠️ Potential Conflicts:
  └─ Generated TS rule overlaps with existing languages/typescript
     Recommendation: Merge or skip duplicate sections

📝 Will Generate:
  ├─ .cursor/rules/frontend-react/RULE.md (47 rules)
  ├─ .cursor/rules/testing-vitest/RULE.md (31 rules)
  └─ .cursor/rules/css-tailwind/RULE.md (22 rules)

Preview rules before applying? (y/n/diff)

You see exactly what will be generated, why, and what conflicts exist. You can preview, diff against existing rules, or apply directly.


The Counterargument: Why Not Just Write Rules Once?

Fair question. Manual rules work fine for small, stable projects. The investment in adaptive generation pays off when:

  1. Your stack is non-trivial. React + Vite + Tailwind + Vitest + Playwright is five different rule domains. Manual maintenance doesn't scale.

  2. You're working across multiple projects. If you maintain 10 repos with different stacks, manually customizing rules for each is slow. Detection + generation becomes worthwhile.

  3. Dependencies change frequently. Swapping from Jest to Vitest or adding a new framework means your rules need updating. Adaptive systems handle this automatically.

  4. Teams share base rules. Shared rule templates plus project-specific augmentation lets you maintain consistency without forcing identical conventions on different projects.

If you're building a single, stable project that rarely changes dependencies, manual rules are probably fine. For everything else, adaptive generation removes friction.


What's Required to Build This

This isn't a small undertaking. The components include:

Rule templates per stack:

templates/
├── frameworks/
│   ├── react.md
│   ├── vue.md
│   └── svelte.md
├── css/
│   ├── tailwind.md
│   └── css-modules.md
├── testing/
│   ├── vitest.md
│   ├── jest.md
│   └── playwright.md
└── concerns/
    ├── accessibility.md
    ├── performance.md
    └── security.md

Detection logic for each config file format. This is parsing package.json, tsconfig.json, various config files, and making sense of them.

Augmentation system. Taking base templates and enriching them with stack-specific and project-specific context.

Conflict detection. Comparing generated rules against existing rules and tooling configuration.

Output structure:

.cursor/rules/
├── stack-profile/RULE.md       # Generated stack reference
├── frontend-react/RULE.md      # React + Vite specific
├── testing-vitest/RULE.md      # Vitest + Playwright specific
├── css-tailwind/RULE.md        # Tailwind specific
├── code-quality/RULE.md        # Universal (manually maintained)
└── typescript/RULE.md          # Language rules (manually maintained)

Rules are flat—each rule folder sits directly under .cursor/rules/. Use naming prefixes (like frontend-, testing-) to organize related rules rather than nesting them.


Evolution Path

This vision has stages:

flowchart LR
    subgraph P1["Phase 1: Manual"]
        M1[Write Rules]
        M2[Edit Forever]
        M1 --> M2
    end
    
    subgraph P2["Phase 2: Semi-Auto"]
        S1[Detect Stack]
        S2[Generate Rules]
        S3[Review & Apply]
        S1 --> S2 --> S3
    end
    
    subgraph P3["Phase 3: Continuous"]
        C1[Git Hook]
        C2[Auto-Detect Changes]
        C3[Suggest Updates]
        C1 --> C2 --> C3
    end
    
    P1 -->|"You are here"| P2 -->|Future| P3

Phase 1 (Current): Manual rules. You write them, you maintain them. This is where most teams are.

Phase 2 (Near-term): Semi-automated generation. A command analyzes your stack, generates contextual rules, you review before applying. This is achievable now with current tooling.

Phase 3 (Future): Continuous adaptation. Git hooks detect stack changes and suggest rule updates. Dependency upgrades trigger rule regeneration. The rules evolve with the codebase without manual intervention.

Phase 3 requires infrastructure—pre-commit hooks, CI integration, potentially a service that monitors for changes. But Phase 2 is achievable today and delivers most of the value.


What to Do Next

If you're maintaining static rules that don't match your actual stack:

  1. Audit your existing rules. How many mention tools or patterns you don't use? How many miss tools you do use?

  2. Document your stack profile manually. List your framework, build tool, test tools, CSS approach, and any detected patterns. This is the input for any rule generation system.

  3. Identify the gaps. Compare your documented stack to your existing rules. Where's the mismatch?

  4. Start with one domain. Don't try to generate everything at once. Pick frontend rules, or testing rules, and build the detection + generation pipeline for that domain.

  5. Build the conflict checker. Before generating any new rules, check them against existing configuration. Conflicts caught early are conflicts avoided.

Adaptive rules aren't a silver bullet. They're a system for reducing maintenance burden when your stack is complex and evolving. The investment scales with project complexity—small projects might not need it, but for anything non-trivial, rules that know your stack beat rules that guess at it.


Keep Going


The best rules are the ones you don't have to write twice. Adaptive generation isn't about removing humans from the loop—it's about removing the tedious parts so humans can focus on the decisions that matter.