mikeneko-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
3
+ import { resolve, dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { createInterface } from "readline";
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const TEMPLATES = resolve(__dirname, "../templates");
8
+ const CWD = process.cwd();
9
+ // ── Colors ──
10
+ const bold = (s) => `\x1b[1m${s}\x1b[0m`;
11
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
12
+ const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
13
+ const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
14
+ const red = (s) => `\x1b[31m${s}\x1b[0m`;
15
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
16
+ function log(icon, msg) {
17
+ console.log(` ${icon} ${msg}`);
18
+ }
19
+ // ── Prompt ──
20
+ function ask(question) {
21
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
22
+ return new Promise((resolve) => {
23
+ rl.question(question, (answer) => {
24
+ rl.close();
25
+ resolve(answer.trim());
26
+ });
27
+ });
28
+ }
29
+ function detectFramework() {
30
+ const pkgPath = resolve(CWD, "package.json");
31
+ if (!existsSync(pkgPath))
32
+ return null;
33
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
34
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
35
+ if (deps["next"])
36
+ return "nextjs";
37
+ if (deps["react"])
38
+ return "react";
39
+ return null;
40
+ }
41
+ function detectShadcn() {
42
+ return existsSync(resolve(CWD, "components.json"));
43
+ }
44
+ // ── CSS file location ──
45
+ function findCssFile(framework) {
46
+ const candidates = framework === "nextjs"
47
+ ? [
48
+ "src/app/globals.css",
49
+ "app/globals.css",
50
+ "src/globals.css",
51
+ "styles/globals.css",
52
+ ]
53
+ : [
54
+ "src/index.css",
55
+ "src/globals.css",
56
+ "src/app.css",
57
+ "index.css",
58
+ ];
59
+ for (const c of candidates) {
60
+ if (existsSync(resolve(CWD, c)))
61
+ return c;
62
+ }
63
+ return null;
64
+ }
65
+ // ── Theme injection ──
66
+ function injectTheme(cssPath) {
67
+ const fullPath = resolve(CWD, cssPath);
68
+ const original = readFileSync(fullPath, "utf-8");
69
+ const themeBlock = readFileSync(resolve(TEMPLATES, "theme.css"), "utf-8");
70
+ // Check if already injected
71
+ if (original.includes("mikeneko UI Theme")) {
72
+ log(yellow("●"), `Theme already exists in ${cssPath}`);
73
+ return false;
74
+ }
75
+ // Find :root block and replace, or append
76
+ if (original.includes(":root {")) {
77
+ // Replace existing :root and .dark blocks with melta theme
78
+ const cleaned = original
79
+ .replace(/:root\s*\{[^}]*\}/s, "/* :root replaced by mikeneko-ui */")
80
+ .replace(/\.dark\s*\{[^}]*\}/s, "/* .dark replaced by mikeneko-ui */");
81
+ writeFileSync(fullPath, cleaned + "\n" + themeBlock);
82
+ }
83
+ else {
84
+ writeFileSync(fullPath, original + "\n" + themeBlock);
85
+ }
86
+ return true;
87
+ }
88
+ // ── File writers ──
89
+ function writeIfNotExists(relativePath, content) {
90
+ const fullPath = resolve(CWD, relativePath);
91
+ if (existsSync(fullPath)) {
92
+ log(yellow("●"), `${relativePath} already exists, skipping`);
93
+ return false;
94
+ }
95
+ const dir = dirname(fullPath);
96
+ if (!existsSync(dir))
97
+ mkdirSync(dir, { recursive: true });
98
+ writeFileSync(fullPath, content);
99
+ return true;
100
+ }
101
+ function copyTemplate(templateName, destPath) {
102
+ const content = readFileSync(resolve(TEMPLATES, templateName), "utf-8");
103
+ return writeIfNotExists(destPath, content);
104
+ }
105
+ function writeMcpJson() {
106
+ const mcpPath = resolve(CWD, ".mcp.json");
107
+ const mcpConfig = {
108
+ mcpServers: {
109
+ "mikeneko-ui": {
110
+ command: "npx",
111
+ args: ["-y", "mikeneko-ui", "mcp"],
112
+ },
113
+ },
114
+ };
115
+ if (existsSync(mcpPath)) {
116
+ // Merge into existing
117
+ const existing = JSON.parse(readFileSync(mcpPath, "utf-8"));
118
+ if (existing.mcpServers?.["mikeneko-ui"]) {
119
+ log(yellow("●"), ".mcp.json already has mikeneko-ui entry");
120
+ return false;
121
+ }
122
+ existing.mcpServers = existing.mcpServers || {};
123
+ existing.mcpServers["mikeneko-ui"] = mcpConfig.mcpServers["mikeneko-ui"];
124
+ writeFileSync(mcpPath, JSON.stringify(existing, null, 2) + "\n");
125
+ return true;
126
+ }
127
+ writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + "\n");
128
+ return true;
129
+ }
130
+ // ── Main ──
131
+ async function main() {
132
+ const args = process.argv.slice(2);
133
+ // Sub-command: mcp server mode
134
+ if (args[0] === "mcp") {
135
+ const { startMcp } = await import("./mcp.js");
136
+ await startMcp();
137
+ return;
138
+ }
139
+ console.log();
140
+ console.log(bold(" mikeneko UI") + dim(" — AI-ready design system"));
141
+ console.log();
142
+ // Step 1: Detect or ask framework
143
+ let framework = detectFramework();
144
+ if (framework) {
145
+ log(green("✔"), `Detected: ${bold(framework === "nextjs" ? "Next.js" : "React (Vite)")}`);
146
+ }
147
+ else {
148
+ console.log(" Which framework?");
149
+ console.log(` ${bold("1")} React (Vite)`);
150
+ console.log(` ${bold("2")} Next.js`);
151
+ console.log();
152
+ const choice = await ask(" Enter (1/2): ");
153
+ framework = choice === "2" ? "nextjs" : "react";
154
+ }
155
+ // Step 2: Check shadcn/ui
156
+ if (!detectShadcn()) {
157
+ console.log();
158
+ log(red("✖"), "shadcn/ui not found (no components.json)");
159
+ console.log();
160
+ console.log(` Run this first:`);
161
+ console.log(cyan(` npx shadcn@latest init`));
162
+ console.log();
163
+ process.exit(1);
164
+ }
165
+ log(green("✔"), "shadcn/ui detected");
166
+ // Step 3: Find CSS file
167
+ const cssFile = findCssFile(framework);
168
+ if (!cssFile) {
169
+ log(red("✖"), "Could not find globals.css / index.css");
170
+ process.exit(1);
171
+ }
172
+ console.log();
173
+ // Step 4: Inject theme
174
+ if (injectTheme(cssFile)) {
175
+ log(green("✔"), `Injected mikeneko-ui theme into ${bold(cssFile)}`);
176
+ }
177
+ // Step 5: Copy CLAUDE.md
178
+ if (copyTemplate("CLAUDE.md", "CLAUDE.md")) {
179
+ log(green("✔"), `Created ${bold("CLAUDE.md")}`);
180
+ }
181
+ // Step 6: Copy prohibited.md
182
+ if (copyTemplate("prohibited.md", "foundations/prohibited.md")) {
183
+ log(green("✔"), `Created ${bold("foundations/prohibited.md")}`);
184
+ }
185
+ // Step 7: Write .mcp.json
186
+ if (writeMcpJson()) {
187
+ log(green("✔"), `Added mikeneko-ui to ${bold(".mcp.json")}`);
188
+ }
189
+ console.log();
190
+ log("🎨", bold("Done!") + " Your project now uses mikeneko-ui design tokens.");
191
+ console.log();
192
+ console.log(dim(" AI tools will read CLAUDE.md and use MCP for design rules."));
193
+ console.log(dim(" Run `npx shadcn@latest add button` to add components."));
194
+ console.log();
195
+ }
196
+ main().catch((err) => {
197
+ console.error(red("Error:"), err.message);
198
+ process.exit(1);
199
+ });
package/dist/mcp.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function startMcp(): Promise<void>;
package/dist/mcp.js ADDED
@@ -0,0 +1,123 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { resolve } from "path";
3
+ // Lazy-load MCP SDK only when mcp subcommand is used
4
+ export async function startMcp() {
5
+ const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
6
+ const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
7
+ const { CallToolRequestSchema, ListToolsRequestSchema, } = await import("@modelcontextprotocol/sdk/types.js");
8
+ const CWD = process.cwd();
9
+ function loadFile(path) {
10
+ const full = resolve(CWD, path);
11
+ if (!existsSync(full))
12
+ return null;
13
+ return readFileSync(full, "utf-8");
14
+ }
15
+ function loadJSON(path) {
16
+ const content = loadFile(path);
17
+ return content ? JSON.parse(content) : null;
18
+ }
19
+ // Try to find templates dir (installed via npm or local dev)
20
+ const { dirname } = await import("path");
21
+ const { fileURLToPath } = await import("url");
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+ const TEMPLATES = resolve(__dirname, "../templates");
24
+ function loadTemplate(name) {
25
+ const full = resolve(TEMPLATES, name);
26
+ if (!existsSync(full))
27
+ return null;
28
+ return readFileSync(full, "utf-8");
29
+ }
30
+ const server = new Server({ name: "mikeneko-ui-mcp", version: "1.0.0" }, { capabilities: { tools: {} } });
31
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
32
+ tools: [
33
+ {
34
+ name: "get_token",
35
+ description: "mikeneko UI デザイントークンを取得。category: color, typography, spacing, elevation, radius, motion, zIndex, wireframe",
36
+ inputSchema: {
37
+ type: "object",
38
+ properties: {
39
+ category: {
40
+ type: "string",
41
+ description: "トークンカテゴリ",
42
+ enum: ["color", "typography", "spacing", "elevation", "radius", "motion", "zIndex", "wireframe"],
43
+ },
44
+ },
45
+ required: ["category"],
46
+ },
47
+ },
48
+ {
49
+ name: "get_component",
50
+ description: "shadcn/ui コンポーネント仕様を取得。name省略で全一覧。",
51
+ inputSchema: {
52
+ type: "object",
53
+ properties: {
54
+ name: { type: "string", description: "コンポーネント名 (例: Button, Card)" },
55
+ },
56
+ },
57
+ },
58
+ {
59
+ name: "get_prohibited",
60
+ description: "mikeneko UI 禁止パターンを取得。",
61
+ inputSchema: {
62
+ type: "object",
63
+ properties: {
64
+ section: { type: "string", description: "特定セクションのみ(省略で全量)" },
65
+ },
66
+ },
67
+ },
68
+ {
69
+ name: "get_quick_reference",
70
+ description: "CLAUDE.md (AI Quick Reference) を返す。",
71
+ inputSchema: {
72
+ type: "object",
73
+ properties: {},
74
+ },
75
+ },
76
+ ],
77
+ }));
78
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
79
+ const { name, arguments: args } = request.params;
80
+ const a = args;
81
+ const text = (s) => ({ content: [{ type: "text", text: s }] });
82
+ switch (name) {
83
+ case "get_token": {
84
+ // Try project-local tokens first, then bundled template
85
+ const tokens = loadJSON("tokens/tokens.json") ?? loadJSON(resolve(TEMPLATES, "tokens.json"));
86
+ if (!tokens)
87
+ return text("tokens.json not found");
88
+ const result = tokens[a.category];
89
+ return result ? text(JSON.stringify(result, null, 2)) : text(`Unknown category: ${a.category}`);
90
+ }
91
+ case "get_component": {
92
+ const data = loadJSON("metadata/components.json") ?? loadJSON(resolve(TEMPLATES, "components.json"));
93
+ if (!data)
94
+ return text("components.json not found");
95
+ if (!a.name) {
96
+ const list = data.components.map((c) => `${c.name} (${c.category})`);
97
+ return text(`Available (${list.length}):\n${list.join("\n")}`);
98
+ }
99
+ const comp = data.components.find((c) => c.name.toLowerCase() === a.name.toLowerCase());
100
+ return comp ? text(JSON.stringify(comp, null, 2)) : text(`Not found: ${a.name}`);
101
+ }
102
+ case "get_prohibited": {
103
+ const content = loadFile("foundations/prohibited.md") ?? loadTemplate("prohibited.md");
104
+ if (!content)
105
+ return text("prohibited.md not found");
106
+ if (!a.section)
107
+ return text(content);
108
+ const regex = new RegExp(`(##+ .*${a.section}[\\s\\S]*?)(?=\\n##[^#]|\\n---\\n|$)`, "i");
109
+ const match = content.match(regex);
110
+ return text(match ? match[1].trim() : `Section "${a.section}" not found`);
111
+ }
112
+ case "get_quick_reference": {
113
+ const content = loadFile("CLAUDE.md") ?? loadTemplate("CLAUDE.md");
114
+ return text(content ?? "CLAUDE.md not found");
115
+ }
116
+ default:
117
+ return text(`Unknown tool: ${name}`);
118
+ }
119
+ });
120
+ const transport = new StdioServerTransport();
121
+ await server.connect(transport);
122
+ console.error("mikeneko UI MCP Server running on stdio");
123
+ }
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "mikeneko-ui",
3
+ "version": "1.0.0",
4
+ "description": "mikeneko UI — AI-ready design system CLI. Injects theme + rules into your React/Next.js project.",
5
+ "type": "module",
6
+ "bin": {
7
+ "mikeneko-ui": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsx src/index.ts"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "templates"
16
+ ],
17
+ "keywords": ["design-system", "shadcn", "tailwind", "react", "nextjs", "mcp"],
18
+ "license": "MIT",
19
+ "dependencies": {
20
+ "@modelcontextprotocol/sdk": "^1.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "typescript": "^5.4.0",
24
+ "@types/node": "^20.0.0",
25
+ "tsx": "^4.0.0"
26
+ }
27
+ }
@@ -0,0 +1,306 @@
1
+ # mikeneko UI — AI Quick Reference
2
+
3
+ > ShadCN/ui ベースのデザインシステム。Primary: Blue (#2b70ef)、日本語ファーストのタイポグラフィ。
4
+
5
+ ## Design Tokens (抜粋)
6
+
7
+ ### Colors
8
+ ```
9
+ Primary: #2b70ef (500), #f0f5ff (50), #07194e (950)
10
+ Text: #0f172a (foreground/heading), #3d4b5f (body), #64748b (muted)
11
+ Border: #e2e8f0
12
+ Ring: #2b70ef (primary)
13
+ Success: #059669
14
+ Warning: #d97706
15
+ Danger: #ef4444
16
+ ```
17
+
18
+ ### Typography
19
+ ```
20
+ Font: Inter, Hiragino Sans, Hiragino Kaku Gothic ProN, Noto Sans JP, sans-serif
21
+ H1: 32px/1.4 bold (text-3xl)
22
+ H2: 26px/1.4 bold (text-2xl)
23
+ H3: 22px/1.4 semibold (text-xl)
24
+ Body: 18px/2.0 normal (text-base) letter-spacing: 0.02em
25
+ Small: 15px/1.7 (text-sm)
26
+ XS: 13px/1.4 (text-xs)
27
+ ```
28
+
29
+ ### Spacing
30
+ 4px grid (Tailwind default). Prefer multiples of 8.
31
+
32
+ ### Elevation
33
+ none → sm → md → overlay (shadow-xl max)
34
+
35
+ ### Radius
36
+ sm(4px), md(8px), lg(12px), full — globals.css: `--radius: 0.75rem`
37
+
38
+ ### Motion
39
+ Fast: 150ms, Normal: 200ms, Slow: 300ms (max)
40
+ Easing: ease-in-out (default)
41
+
42
+ ---
43
+
44
+ ## 設計原則(5つ)
45
+
46
+ 1. **Layered** — Background → Surface → Text/Object の3層でUIを構成する
47
+ 2. **Contrast** — テキストは背景に対してWCAG 2.1準拠(4.5:1以上)
48
+ 3. **Semantic** — 色は用途で指定する(`bg-primary` ≠ 生の `bg-blue-500`)
49
+ 4. **Minimal** — 1つのViewに使う色は3色まで(背景・アクセント・テキスト)
50
+ 5. **Grid** — スペーシングは4の倍数を基本、8の倍数を推奨する
51
+
52
+ ---
53
+
54
+ ## Components (45種 — shadcn/ui ベース)
55
+
56
+ ### Action
57
+ - **Button**: default / destructive / outline / secondary / ghost / link × sm / default / lg / icon
58
+
59
+ ### Input
60
+ - **Input**: default / disabled / error
61
+ - **Textarea**: default / disabled
62
+ - **Select**: SelectTrigger + SelectContent + SelectItem
63
+ - **Checkbox**: unchecked / checked / indeterminate / disabled
64
+ - **RadioGroup**: RadioGroupItem で構成
65
+ - **Switch**: on / off / disabled(旧 Toggle switch)
66
+ - **Slider**: single / range
67
+ - **Calendar**: single / range date selection
68
+ - **InputOTP**: verification code input
69
+ - **Toggle** / **ToggleGroup**: pressed state buttons
70
+ - **Label**: フォームラベル
71
+ - **Command**: 検索可能なコマンドパレット
72
+
73
+ ### Data Display
74
+ - **Badge**: default / secondary / destructive / outline
75
+ - **Avatar**: AvatarImage / AvatarFallback
76
+ - **Table**: TableHeader + TableBody + TableRow + TableHead + TableCell
77
+ - **Card**: CardHeader + CardTitle + CardDescription + CardContent + CardFooter
78
+ - **Carousel**: horizontal / vertical
79
+ - **Chart**: area / bar / line / pie / radar / radial (Recharts)
80
+
81
+ ### Navigation
82
+ - **Breadcrumb**: BreadcrumbList + BreadcrumbItem + BreadcrumbLink + BreadcrumbPage
83
+ - **Tabs**: TabsList + TabsTrigger + TabsContent
84
+ - **Pagination**: PaginationContent + PaginationItem + PaginationLink
85
+ - **NavigationMenu**: horizontal nav
86
+ - **Menubar**: application menubar
87
+ - **Sidebar**: SidebarProvider ベース、collapsible 対応
88
+
89
+ ### Feedback
90
+ - **Alert**: default / destructive
91
+ - **Sonner**: toast() で呼び出し(旧 Toast)
92
+ - **Progress**: determinate / indeterminate
93
+ - **Skeleton**: loading placeholder
94
+
95
+ ### Overlay
96
+ - **Dialog**: modal dialog(旧 Modal)
97
+ - **AlertDialog**: confirmation dialog
98
+ - **Sheet**: slide-in panel (top/right/bottom/left)
99
+ - **Drawer**: bottom drawer
100
+ - **DropdownMenu**: action menu(旧 Dropdown)
101
+ - **ContextMenu**: right-click menu
102
+ - **HoverCard**: hover popover
103
+ - **Popover**: generic popover
104
+ - **Tooltip**: TooltipProvider でラップ必須
105
+
106
+ ### Disclosure
107
+ - **Accordion**: single / multiple collapsible sections
108
+ - **Collapsible**: toggle content visibility
109
+
110
+ ### Layout
111
+ - **AspectRatio**: 1:1 / 16:9 / 4:3 / 3:2
112
+ - **Separator**: horizontal / vertical(旧 Divider)
113
+ - **ScrollArea**: custom scrollbar
114
+
115
+ ---
116
+
117
+ ## Tailwind CSS テーマ適用
118
+
119
+ ```css
120
+ /* app/src/app/globals.css — Primary: #2b70ef (oklch) */
121
+ :root {
122
+ --primary: oklch(0.5765 0.2038 261.31); /* #2b70ef */
123
+ --primary-foreground: oklch(1.0000 0 0);
124
+ --background: oklch(0.9846 0.0017 247.84); /* #f9fafb */
125
+ --foreground: oklch(0.2077 0.0398 265.75); /* #0f172a */
126
+ --muted-foreground: oklch(0.5544 0.0407 257.42); /* #64748b */
127
+ --border: oklch(0.9288 0.0126 255.51); /* #e2e8f0 */
128
+ --ring: oklch(0.5765 0.2038 261.31);
129
+ --destructive: oklch(0.6368 0.2078 25.33); /* #ef4444 */
130
+ --radius: 0.75rem;
131
+ }
132
+ ```
133
+
134
+ ---
135
+
136
+ ## 禁止パターン要約
137
+
138
+ | 禁止 | 代替 |
139
+ |------|------|
140
+ | `text-black` | `text-foreground` / `text-slate-900` |
141
+ | `bg-gray-300`以上の背景 | `bg-muted` / `bg-gray-50` 〜 `bg-gray-200` |
142
+ | `rounded-none` on cards | Card コンポーネントのデフォルト radius |
143
+ | `shadow-lg` / `shadow-2xl` | `shadow-sm` 〜 `shadow-md`(オーバーレイ: `shadow-xl`) |
144
+ | `border-gray-100` | `border-border` / `border-slate-200` |
145
+ | `text-gray-400` for body | `text-muted-foreground` |
146
+ | カード/Alert の `border-t-4` / `border-l-4` | shadcn Alert/Card のデフォルトスタイル |
147
+ | `bg-indigo-*` / `bg-blue-*` ハードコード | `bg-primary` / CSS変数を使用 |
148
+ | `tracking-tight` | 見出し 0.01em、本文 0.02em |
149
+ | 色だけで情報伝達 | アイコン/テキストを併用 |
150
+ | 300ms超のアニメーション | 150〜300ms に制限 |
151
+ | `<th>` の `scope` 省略 | Table コンポーネント使用 |
152
+
153
+ > 全禁止パターン(76項目): `foundations/prohibited.md` 参照
154
+
155
+ ---
156
+
157
+ ## ファイル構成
158
+
159
+ ```
160
+ mikeneko-ui/
161
+ ├── CLAUDE.md ← このファイル (AI Quick Reference)
162
+ ├── tokens/
163
+ │ └── tokens.json ← デザイントークン (SSOT)
164
+ ├── metadata/
165
+ │ └── components.json ← コンポーネント仕様 (shadcn/ui ベース)
166
+ ├── foundations/ ← デザイン基盤ドキュメント (10ファイル)
167
+ │ ├── color.md
168
+ │ ├── typography.md
169
+ │ ├── spacing.md
170
+ │ ├── elevation.md
171
+ │ ├── motion.md
172
+ │ ├── radius.md
173
+ │ ├── icons.md
174
+ │ ├── accessibility.md
175
+ │ ├── emotional-feedback.md
176
+ │ ├── design_philosophy.md
177
+ │ └── prohibited.md ← 禁止パターン (76項目)
178
+ ├── components/ ← コンポーネント詳細ドキュメント
179
+ ├── patterns/ ← パターンドキュメント (5ファイル)
180
+ ├── ai/
181
+ │ └── mcp/ ← MCP Server
182
+ │ ├── src/index.ts
183
+ │ └── dist/index.js
184
+ ├── app/ ← Next.js + shadcn/ui 実装
185
+ │ ├── src/
186
+ │ │ ├── app/globals.css ← テーマ (CSS変数)
187
+ │ │ ├── components/ui/ ← shadcn/ui コンポーネント (45個)
188
+ │ │ └── lib/utils.ts ← cn() ユーティリティ
189
+ │ └── components.json ← shadcn/ui 設定
190
+ └── docs/ ← ドキュメントサイト
191
+ ```
192
+
193
+ ---
194
+
195
+ ## MCP Server
196
+
197
+ 5つのツールを提供:
198
+
199
+ | ツール | 説明 |
200
+ |--------|------|
201
+ | `get_token` | デザイントークン取得 (color, typography, spacing, etc.) |
202
+ | `get_component` | コンポーネント仕様取得 (shadcn/ui ベース) |
203
+ | `get_foundation` | ファウンデーション MD 取得 |
204
+ | `get_prohibited` | 禁止パターン取得 |
205
+ | `get_quick_reference` | この CLAUDE.md を返す |
206
+
207
+ ```json
208
+ {
209
+ "mcpServers": {
210
+ "mikeneko-ui": {
211
+ "command": "node",
212
+ "args": ["./ai/mcp/dist/index.js"]
213
+ }
214
+ }
215
+ }
216
+ ```
217
+
218
+ ---
219
+
220
+ ## タスクベース読み込みガイド
221
+
222
+ | タスク | 読み込むファイル(順序) |
223
+ |--------|------------------------|
224
+ | 単体コンポーネント生成 | CLAUDE.md のみ |
225
+ | ページ生成 | + foundations/theme.md → patterns/layout.md → 関連 component md |
226
+ | ダークモード対応 | + foundations/theme.md → foundations/color.md |
227
+ | フォーム画面 | + patterns/form.md → Input / Select / Checkbox / Button |
228
+ | データ一覧 | + Table → Pagination → Badge |
229
+ | ダッシュボード | + Card / Table / Progress / Chart / Badge |
230
+ | 設定画面 | + Tabs → Switch / Select / RadioGroup |
231
+ | モーダル / 確認 | + Dialog / AlertDialog → Button |
232
+ | Loading / 空状態 | + Skeleton → interaction-states.md |
233
+ | 通知フィードバック | + Sonner → Alert → interaction-states.md |
234
+ | サイドバー付きページ | + Sidebar → layout.md |
235
+ | ナビゲーション | + navigation.md → Sidebar → Tabs / Breadcrumb |
236
+ | レスポンシブ対応 | + patterns/responsive.md → layout.md |
237
+ | アクセシビリティ確認 | + foundations/accessibility.md |
238
+ | テーマカスタマイズ | foundations/theme.md + app/src/app/globals.css |
239
+
240
+ ---
241
+
242
+ ## テーマ・カラー変数・ダークモード
243
+
244
+ > テーマ設定・CSS変数定義: `app/src/app/globals.css` を参照。
245
+
246
+ | 設定 | 値 |
247
+ |------|-----|
248
+ | **ダークモード** | `OFF` |
249
+
250
+ - `OFF`: ライトモードのみで設計・生成する(デフォルト)
251
+ - `ON`: ダークモード対応を含めて設計・生成する(`.dark` セクション参照)
252
+
253
+ ---
254
+
255
+ ## Design Context
256
+
257
+ ### Users
258
+ - **対象**: B2B / B2C 両方の汎用デザインシステム
259
+ - **エンドユーザー**: 業務SaaSを使うビジネスパーソンから、ECサイト・予約サービスの一般消費者まで
260
+ - **利用コンテキスト**: ダッシュボード、管理画面、EC、予約、学習、医療、行政など幅広いドメイン
261
+ - **DSの消費者**: 人間の開発者・デザイナー、および Claude Code / Cursor 等の AI コード生成エージェント
262
+
263
+ ### Brand Personality
264
+ - **3語で表すと**: 静謐・精緻・温もり(Quiet · Precise · Warm)
265
+ - **声のトーン**: 「声を張らずに伝わる」— 主張しすぎない、でも確かに伝わる
266
+ - **コアメタファー**: 「機能的な黒子であり、たまに微笑む」
267
+ - **感情目標**: 心地よい集中 → 洗練された効率 → 穏やかな親しみ(この順で優先)
268
+
269
+ ### Aesthetic Direction
270
+ - **ビジュアルトーン**: ミニマルだが冷たくない。フラットな基盤に Background → Surface → Text の3層で奥行きを出す
271
+ - **参考プロダクト**: Linear / Notion / Stripe / Vercel
272
+ - **アンチリファレンス**: 派手なグラデーション・ネオンカラー、Bootstrap 的な没個性テンプレート
273
+
274
+ ### Design Principles
275
+ 1. **Content First** — UIは黒子。コンテンツが主役であり、装飾ではなく構造で伝える
276
+ 2. **Calm Confidence** — 信頼感を静かに醸成する。過剰な演出より、正確なスペーシングとコントラストで品質を示す
277
+ 3. **Inclusive by Default** — WCAG 2.1 AA準拠はオプションではなくデフォルト
278
+ 4. **Systematic Warmth** — 4px グリッド・セマンティックカラー・制限されたシャドウで一貫性を保ちつつ、人間味を添える
279
+ 5. **Machine-Readable** — トークン・メタデータ・セマンティック命名により、AIエージェントが正確にUIを生成できる
280
+
281
+ ---
282
+
283
+ ## 参照先
284
+
285
+ - **トークン全量**: `tokens/tokens.json`
286
+ - **コンポーネント全量**: `metadata/components.json`
287
+ - **禁止パターン全量**: `foundations/prohibited.md`
288
+ - **ShadCN/ui docs**: `https://ui.shadcn.com/docs`
289
+
290
+ ---
291
+
292
+ ## デプロイ
293
+
294
+ | 項目 | 値 |
295
+ |------|-----|
296
+ | ホスティング | Netlify(手動デプロイ) |
297
+ | 本番URL | https://melta.tsubotax.com |
298
+ | publish ディレクトリ | `.`(リポジトリルート)— `netlify.toml` で設定済み |
299
+
300
+ ```bash
301
+ # ドキュメントサイトデプロイ
302
+ netlify deploy --prod
303
+
304
+ # Next.js アプリ (別途)
305
+ cd app && npm run build
306
+ ```