Add teach-impeccable and review commands, dynamic placeholders

New commands:
- /teach-impeccable: One-time setup that gathers UX-focused design
  context (explores codebase first, then asks targeted questions)
- /review: UX design review evaluating hierarchy, clarity, emotional
  resonance (complements technical /audit)

Build system improvements:
- Dynamic {{model}}, {{ask_instruction}}, {{config_file}} placeholders
  per provider (Claude/Gemini/GPT/the model)
- context: fork support for Claude Code sub-agents (audit, extract)
- Skill reference auto-added to design commands

Skill refinements:
- Merged Design Thinking and Context Awareness sections
- Removed redundant patterns and technical questions
- More direct feedback guidance (radical candor)

Website updates:
- 17 commands (was 16)
- Review demo showing UX issues (HIERARCHY, NO PRIMARY, DEAD END)
- teach-impeccable in System group of periodic table

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-01-07 16:56:08 -08:00
co-authored by Claude Opus 4.5
parent 8186f2a226
commit 0b9c1846a6
96 changed files with 1315 additions and 646 deletions
+3 -59
View File
@@ -1,6 +1,6 @@
import { readFileSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
import { readPatterns } from "../scripts/lib/utils.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@@ -8,64 +8,8 @@ const PROJECT_ROOT = join(__dirname, "..");
export default function handler(req, res) {
try {
const sourceDir = join(PROJECT_ROOT, "source");
const filePath = join(sourceDir, "patterns.md");
const content = readFileSync(filePath, "utf-8");
const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---/);
if (!frontmatterMatch) {
return res.status(200).json({ patterns: [], antipatterns: [] });
}
const frontmatterText = frontmatterMatch[1];
const patterns = [];
const antipatterns = [];
const lines = frontmatterText.split('\n');
let currentSection = null;
let currentCategory = null;
let inItems = false;
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed) continue;
const indent = line.length - line.trimStart().length;
if (indent === 0 && trimmed === 'patterns:') {
currentSection = 'patterns';
currentCategory = null;
inItems = false;
continue;
}
if (indent === 0 && trimmed === 'antipatterns:') {
currentSection = 'antipatterns';
currentCategory = null;
inItems = false;
continue;
}
if (trimmed.startsWith('- name:') && currentSection) {
currentCategory = { name: trimmed.slice(7).trim(), items: [] };
if (currentSection === 'patterns') {
patterns.push(currentCategory);
} else {
antipatterns.push(currentCategory);
}
inItems = false;
continue;
}
if (trimmed === 'items:' && currentCategory) {
inItems = true;
continue;
}
if (trimmed.startsWith('- ') && inItems && currentCategory && indent >= 6) {
currentCategory.items.push(trimmed.slice(2).trim());
}
}
// Extract patterns from SKILL.md using the shared utility
const { patterns, antipatterns } = readPatterns(PROJECT_ROOT);
res.status(200).json({ patterns, antipatterns });
} catch (error) {
console.error("Error in /api/patterns:", error);