Every rule is contextual. Read the brief first, then pull only what fits.
Good: "用 archviz 给这份产品全案 §2 画 V1 闭环图" · "Gantt + 任务表 + ASCII fallback" · "内嵌 Warm Paper SVG 到 Obsidian 笔记"
Bad: "帮我生成小红书 PNG 并截图上传" → use claude-design-card (Bun + Playwright). archviz supplies the language + HTML skeleton, not the screenshot CLI.
design-taste-frontend, frontend-design, or huashu-design.claude-design-card.mermaid-arc-skills (lighter, Mermaid-focused).imagegen / fal MCP.NeedUseDiagram in .md + fallbacksarchviz-skillsEditable professional diagramarchviz-skills draw.io mode ( references/drawio-output-mode.md)Publishable PNG card (14 formats)claude-design-cardSwiss/guizang Mermaid styling onlymermaid-arc-skillsDESIGN.md for a product brandanydesign + host DESIGN.md
GatePass criteriaOn failG0 BriefOne-line "Reading this as…" + dials setSTOP — infer from host docG1 TypeQR table match; ≤2 types per deliverableSTOP — split diagramG2 TokensPalette locked; contrast computed; max 1 accentSTOP — fix init/CSSG3 Editorial askIf card/cover ambiguous: 1 primary + 2 alt OR user said "your call"STOP — do not guess platformG4 GenerateTemplate read if path existsFallback: flowchart TD + subgraphG5 Validatereferences/validation-checklist.md pre+postSTOP — ASCII fallback + document ⚠️G6 EmbedCaption = finding firstRevise caption before ship
Iron rule: No ship without G2 contrast check. No Family A cover with >3 text layers.
text
Dials: COMPLEXITY=4 DENSITY=3 RESTRAINT=8
Palette: surface=#f5f0eb text=#1B365D border=#a8a29e accent=#002FA7 (max 1)
Init: %%{init: {'theme':'base','themeVariables':{'primaryColor':'#f5f0eb','primaryTextColor':'#1B365D','primaryBorderColor':'#a8a29e','lineColor':'#a8a29e','tertiaryColor':'#d6d3d1','fontSize':'13px'}}}%%
Contrast: luminance(0.299R+0.587G+0.114B) < 128 → light text, ≥ 128 → dark text
Labels: ≤6 words / ≤8 Chinese chars / no ALL CAPS
Gantt: codes only inside block + table beside / min 3w / termaid for terminal
Anti-slop: no purple default / no rainbow / no flowchart-for-everything / no pie
Editorial: Parchment=#f5f4ed ink=#141413 terracotta=#c96442 (max 1) serif 500 not 700
Type selection (fast):
DataTypeTemplateHierarchicalmindmap—Sequentialflowchart LR/TD—System/layeredflowchart TD + subgraph—Comparison/rankingxychart-beta (bar)—Proportionaltreemap or stacked bar—Timelineganttmermaid/gantt.mmdDistributionhistogram/boxmermaid/distribution.mmdCorrelationscatter/heatmappython/scatter-plot.pyFlow/networksankeymermaid/sankey.mmdFunnel/conversionfunnel charthtml/funnel.htmlDecision/evaluationdecision matrix (table)mermaid/decision-matrix.mmdState transitionsstateDiagram-v2mermaid/state-machine.mmdDependenciesdependency graphmermaid/dependency-network.mmdEditable architecture handoffdraw.io XML planreferences/drawio-output-mode.mdMulti-criteria scoringradar or diverging barhtml/radar.html / mermaid/diverging-bar.mmdSimple (≤5 items)TABLE, not chart—3D: Building structureThree.js structure shellhtml/threejs-archviz.html3D: Floor planThree.js extruded floorhtml/threejs-floorplan.html3D: Section cutThree.js ClippingPlanehtml/threejs-archviz.html**Cover / hero (click promise)**Editorial Family A HTMLhtml/editorial-card.html**Knowledge card (saveable)**Editorial Family B HTMLhtml/editorial-card.html**Social square (quote/data)**Editorial Family C HTMLhtml/editorial-card.htmlLong-form article layoutEditorial Family D HTMLhtml/editorial-card.html
Mixed types (when data spans categories):
Degradation strategy (when data is too complex):
50 nodes → split into 2-3 linked diagrams with shared legend
7 categories → aggregate into "Other" + detail diagram
Mixed data types → identify primary relationship, table the rest
Preview environment fails → ASCII fallback (always prepared)
Mermaid syntax error → flowchart TD + subgraph (most compatible)
Environment routing:
EnvOutputObsidian/previewlightweight Mermaid / self-contained HTMLTerminaltermaid-first ( termaid diagram.mmd --theme mono --width N) then ASCII fallbackDeliverablesPython (Plotly/Matplotlib)Editable handoffdraw.io .drawio source + optional PNG/SVG/PDF export3D / archviz****Three.js self-contained HTML (CDN import)
Specialized references:
references/termaid-routing.mdreferences/drawio-output-mode.mdreferences/scene-contract.md3D archviz mode (when brief = building/structure/spatial):
structure=#a8a29e, floor=#e8e4e0, accent-3d=#002FA7CDN importmap pattern (self-contained HTML, zero build):
html
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/",
"animejs": "https://cdn.jsdelivr.net/npm/animejs@4.4.1/dist/bundles/anime.esm.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { animate } from 'animejs'; // v4: named export, NOT default
</script>
Tech stack pitfalls (硬规则,已踩坑验证):
PitfallSymptomFixanimejs CDN 404Canvas blank, no errorsv4.4.1 路径是 dist/bundles/anime.esm.js,不是 lib/anime.es.jsanimejs default importimport anime from 'animejs' → undefinedv4 是 named export: import { animate } from 'animejs'animejs v3→v4 APIanime({targets: x, ...}) 报错v4 是 animate(target, params),无 targets keyanimate 命名冲突渲染循环函数也叫 animate → 覆盖 import渲染循环用 renderLoop 或 tick,不要用 animateThree.js CatmullRomCatmullRomCurvePath 不存在用 CatmullRomCurve3(3D 曲线)
Full rules → DESIGN.md. Templates → templates/.
Before generating, read these signals:
Output one line: "Reading this as: for , , ."
Palette routing: academic/diagram default → Warm Paper + IKB · editorial/card/cover → Editorial Parchment + Terracotta · host doc with existing tokens → match host (Aver cinnabar, etc.).
4-layer analysis (from anydesign): Identity → System → Components → Layout. Mark confidence: ✅/⚠️/❓.
DESIGN.md contract (from awesome-design-md): Atmosphere → Tokens → Components → Layout → Guardrails. If any layer is unknown, state the assumption before generating.
Anti-default: No purple gradients, no rainbow nodes, no centered symmetry, no flowchart-for-everything, no default theme.
DialDefaultRangeCOMPLEXITY41(minimal)–10(dense)DENSITY31(airy)–10(packed)RESTRAINT81(expressive)–10(austere)
Inference: "academic" → 3-5/2-3/9-10 · "playful" → 5-8/3-5/3-5 · "data report" → 6-8/6-8/5-7
Defined in DESIGN.md. Summary:
TokenWarm PaperSwissIKBsurface#f5f0eb#f5f5f4#e4e8f0text#1B365D#1B365D#0a0a0aborder#a8a29e#d6d3d1#94a3b8accent——#002FA7Editorial Parchment#f5f4ed``#141413``#e8e6dc
Rules: Max 1 accent. No AI-purple. Same doc = same palette. Contrast check mandatory. Light surface uses dark text. Editorial mode: serif display 500 max, no #ffffff canvas, no cool #64748b grays. Full rules → references/editorial-parchment-language.md.
越大越细,越小越粗:Large=200(ExtraLight) · Body=300(Light) · Small=500-600(SemiBold)
Labels: ≤6 words · ≤8 Chinese chars · no ALL CAPS · same language per diagram
DataFormat2-3 itemsTable4-8 itemsBar chartProportionalTreemap/stackedSequentialFlowchartHierarchicalMindmapTimelineGantt
Simple comparison (≤5 items) → TABLE, not chart.
Do: Cite hex/px · Infer semantic roles · Mark confidence (✅/⚠️/❓) · Match document style
Don't: Generic descriptions · Colors without hex · Invent tokens · Ignore context
yaml
---
diagram: [name]
type: [mindmap|flowchart|xychart-beta|gantt|...]
context: [paper|log|PPT|note]
dials: {complexity: N, density: N, restraint: N}
tokens: {surface: "#f5f0eb", text: "#1B365D", border: "#a8a29e", accent: "#002FA7"}
confidence: {palette: "✅", layout: "✅", nodes: "⚠️"}
---
Pre-gen checklist: Brief done? DESIGN.md contract complete? Dials set? Tokens locked? Labels short? Gantt: codes+table? Card/cover: compressed to judgment+promise+one evidence?
After generating a diagram, run a validation loop:
text
Generate → Render → Check → Fix → Re-render (max 2 rounds)
Step 1: Render
termaid diagram.mmd --theme mono (terminal) or paste into ObsidianStep 2: Check (read the rendered output)
Step 3: Fix (if issues found)
Step 4: Re-render and verify fix
Stop when: 0 issues found, or 2 rounds exhausted (report remaining issues to user).
Terminal validation (termaid):
bash
# Render and visually inspect
termaid diagram.mmd --theme mono
# If output looks wrong, edit .mmd and re-run
Trigger: 封面、卡片、信息卡、小红书、公众号、分享图、排版、knowledge card, or publishable HTML.
Load: references/editorial-parchment-language.md + templates/html/editorial-card.html.
Gate G3: platform/read-vs-share unclear → 1 primary + 2 alternatives + ≤3 questions. User says「按你判断」→ Family B default.
Families: A cover · B knowledge 1080×1440 · C square · D long-form width-led. Full sizes/safe-zones → reference file.
Primary: termaid ( pip install termaid)
bash
# 直接渲染 Mermaid 文件到终端
termaid diagram.mmd --theme mono
termaid diagram.mmd --theme terra
echo 'graph LR; A-->B-->C' | termaid --theme mono
6种主题: default, terra, neon, mono, amber, phosphor
支持18种图: flowchart, sequence, class, ER, state, block, git, gantt, architecture, pie, treemap, mindmap, timeline, kanban, quadrant, xychart, user journey, packet
Python API:
python
from termaid import render
print(render("graph LR\n A --> B --> C"))
Fallback: 纯文本ASCII(termaid不可用时)
Plain text only. Max 80 columns. No box-drawing characters.
元素符号节点[文本] 或 (文本)重要节点[[文本]] 或 ((文本))决策{文本}箭头--> ==>
Save and reuse visual styles across diagrams.
Preset format (YAML):
yaml
# .archviz-preset.yaml
name: warm-paper-restrained
tokens:
surface: "#f5f0eb"
text: "#1B365D"
border: "#a8a29e"
accent: "#002FA7"
mermaid_init: "%%{init: {'theme':'base','themeVariables':{'primaryColor':'#f5f0eb','primaryTextColor':'#1B365D','primaryBorderColor':'#a8a29e','lineColor':'#a8a29e','tertiaryColor':'#d6d3d1','fontSize':'13px'}}}%%"
dials: {complexity: 4, density: 3, restraint: 8}
Extract from existing diagram:
%%{init:...}%% block from a .mmd filethemeVariables into token names.archviz-preset.yamlApply preset:
.archviz-preset.yaml from project root (if exists)Built-in presets: warm-paper (default), swiss-neutral, ikb-accent, lemon-accent, stone-mono, editorial-parchment, warm-paper-dark, ikb-dark
Actual files live in templates/. Current inventory (do not hardcode counts in prompts):
text
templates/
├── mermaid/ 15 files (gantt, sankey, distribution, diverging-bar, network, scoring, intro, architecture, closed-loop variants, funnel, decision-matrix, state-machine, dependency-network)
│ flowchart + mindmap: inline Mermaid (no standalone .mmd)
├── ascii/ 4 files (flowchart, architecture, gantt, icon-system)
├── html/ 15 files (+ editorial-card; bubble, bullet-graph, funnel, gauge, heatmap, line, radar, sunburst, treemap, waffle, waterfall, threejs-archviz, threejs-floorplan)
└── python/ 5 files (scatter-plot, box-plot, candlestick, parallel-coordinates, viz template)
templates/<mode>/ at use time instead of relying on this list. Flowchart and mindmap have no template files — generate inline using tokens from DESIGN.md.#IssueFixEditorial wrong paletteHost doc wins; else Editorial Parchment #f5f4ed + Terracotta #c96442 — never mix with IKBCover too denseFamily A: drop to judgment + promise + one evidence; move rest to Family BCard needs PNG exportOut of scope — hand off HTML to claude-design-card screenshot.ts or browser exportMindmap failsUse flowchart/subgraphArchitecture-beta lexer errorUse flowchart TD + subgraph (preview-compatible)Gantt text overflowCodes only + table + ASCII fallbackTheme too flashyForce solarized-light/nord-lightText unreadableCheck contrast rule (QR)Too many nodesSplit into subgraphsCanvas blank (Three.js)Check console for CDN 404 / import errorsanimejs not animatingv4 API: animate(target, props) not anime({targets})Render loop stopsDon't name loop function animate (conflicts with animejs import)
Anti-patternSymptomFixPie for everythingPie chart with >5 slices or similar values≤3 slices → table; >3 → treemap or stacked barRainbow nodesEvery node a different colorSame hue, vary lightness. Max 1 accentFlowchart-for-everythingNon-sequential data forced into flowchartMatch data relationship to type table (§QR)Label soupLabels >10 words, full sentences≤6 words / ≤8 Chinese chars. Detail in caption3D decoration3D bar/pie for "visual interest"Flat only. Depth = data dimension, never decorationDual Y-axis lieTwo unrelated metrics on shared axisSplit into 2 charts or use indexed/baseline ratioTruncated axisBar chart Y-axis starts at non-zeroAlways start at 0. Use inset zoom if range mattersLegend overload>7 legend items, hard to matchAggregate "Other". Use direct labelingDefault themeMermaid/Chart.js default purple/blue gradientAlways apply custom init + tokens from DESIGN.mdMissing captionDiagram embedded without contextCaption = finding, not title. "Sales dropped 30% in Q3" not "Q3 Sales Chart"Color as only channelRed/green distinction for colorblind usersAdd pattern/shape/label. Never rely on color aloneSpaghetti network>20 edges in network/graphCluster nodes, hide weak edges, or split into subgraphsMixed metaphorFlowchart arrows + pie segments + bar heights in one viewOne visual language per diagram. Split if neededInfinite GanttGantt with 30+ tasks, unreadableGroup into phases. Detail in separate Gantt or tableEmoji overload🎯📊🔥 in every nodeMax 1 icon per group. No emoji in formal deliverablesCover as summary slide4–6 bullets on a platform coverFamily A: judgment + promise + one evidence onlyEditorial serif 700Headlines feel bombastic / off-brandGeorgia/Newsreader at 500; enlarge size insteadCool SaaS white#ffffff + #64748b on cardsParchment #f5f4ed + Near-Black #141413Equal card gridEvery module same weightOne hero + hierarchy via type scale
绝不WhyShip Mermaid default themeReads as AI slop; always custom initTwo accents in one set (IKB + Terracotta + cinnabar)Breaks restraint dialfont-weight: 700 on editorial serifOff-brand; enlarge type instead#ffffff canvas or #64748b UI grayViolates warm editorial contractBox-drawing in ASCIIGarbles in chat/non-mono viewersPie chart >3 slicesUse table or treemapSkip ASCII fallback when target env unknownText-first survivabilityEmbed diagram without finding-captionViolates G6Duplicate claude-design-card Playwright pipeline inside archvizToolkit bloat — boundary in §When NOT
references/editorial-parchment-language.md)Full design system → DESIGN.md · Editorial cards → references/editorial-parchment-language.md · Research → research/
This skill uses darwin-skill for self-scoring and optimization, and skills-curation for audit.
Darwin Evaluation of 0.1.6 (simulated run):
Recommendations applied for 0.1.7:
Error Handling Table (new for 0.1.7):
FailureSymptomFix / GateRender fail (Mermaid syntax)Blank or error in viewerFallback to flowchart + subgraph; re-validate with G5Token overflow in large diagramAgent context exceededSplit per degradation strategy; use scene-contractContrast failUnreadable textEnforce G2 luminance check before ship3D CDN 404Canvas blankUse verified v4 paths; test with preview.htmlCJK font mismatchGarbled labelsUse Noto SC in tokens; termaid for terminalNo captionDiagram without contextEnforce G6 before embed
Self-Evolution Loop (darwin on self):
Integration Notes:
agy -p "use darwin and curation on /Users/mac/Developer/archviz-skills for 0.1.7; context: hsueh design teaching, absolute paths, restrained viz"Three.js + animejs v4 实战中遇到的坑,按出现顺序记录。
html
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/",
"animejs": "https://cdn.jsdelivr.net/npm/animejs@4.4.1/dist/bundles/anime.esm.js"
}
}
</script>
⚠️ animejs v4 路径不是 lib/anime.es.js — 那是 v3 的路径。v4.4.1 的正确路径是 dist/bundles/anime.esm.js。验证方法: curl -sI <CDN_URL> 返回 200 才可用。
v3(旧)v4.4.1(当前)import anime from 'animejs'``import { animate } from 'animejs'``anime({targets: obj, x: 1, duration: 500})``animate(obj, {x: 1, duration: 500})
包装函数(统一写法,避免每次改 API):
js
import { animate } from 'animejs';
function tween(target, props) { return animate(target, props); }
// 用法:tween(camera.position, {x: 6, y: 4, z: 8, duration: 800})
js
// ❌ 错误 — animate 与 animejs 导入冲突
function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); }
animate();
// ✅ 正确 — 用 renderLoop 或其他名称
function renderLoop() { requestAnimationFrame(renderLoop); renderer.render(scene, camera); }
renderLoop();
js
// ❌ 物体 y=0 会埋进地面
scene.add(dryer); // dryer.position.y 默认 0
// ✅ 物体抬高到地面之上
scene.add(dryer);
dryer.position.y = 2; // 或者降低地面:gMesh.position.y = -0.5
js
// ❌ 跳跃式,无过渡
camera.position.set(6, 4, 8);
// ✅ 用 tween 平滑过渡
tween(camera.position, {x: 6, y: 4, z: 8, duration: 800, easing: 'easeInOutCubic'});
模板约束 max 3 光源(1 HemisphereLight + 1 DirectionalLight + 1 AmbientLight)。超出会影响性能且难以控制阴影。