@mandujs/mcp 0.12.2 → 0.13.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.
Files changed (141) hide show
  1. package/README.md +367 -367
  2. package/package.json +2 -2
  3. package/src/activity-monitor.ts +847 -847
  4. package/src/adapters/index.ts +20 -20
  5. package/src/adapters/monitor-adapter.ts +100 -100
  6. package/src/adapters/tool-adapter.ts +88 -88
  7. package/src/executor/error-handler.ts +250 -250
  8. package/src/executor/index.ts +22 -22
  9. package/src/executor/tool-executor.ts +148 -148
  10. package/src/hooks/config-watcher.ts +174 -174
  11. package/src/hooks/index.ts +23 -23
  12. package/src/hooks/mcp-hooks.ts +227 -227
  13. package/src/index.ts +106 -106
  14. package/src/logging/index.ts +15 -15
  15. package/src/logging/mcp-transport.ts +134 -134
  16. package/src/registry/index.ts +13 -13
  17. package/src/registry/mcp-tool-registry.ts +298 -298
  18. package/src/resources/skills/guides.ts +1136 -1136
  19. package/src/resources/skills/index.ts +12 -12
  20. package/src/resources/skills/loader.ts +218 -218
  21. package/src/resources/skills/mandu-composition/SKILL.md +91 -91
  22. package/src/resources/skills/mandu-composition/metadata.json +13 -13
  23. package/src/resources/skills/mandu-composition/rules/_sections.md +26 -26
  24. package/src/resources/skills/mandu-composition/rules/_template.md +77 -77
  25. package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +146 -146
  26. package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +164 -164
  27. package/src/resources/skills/mandu-composition/rules/comp-island-event.md +161 -161
  28. package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +167 -167
  29. package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +149 -149
  30. package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +148 -148
  31. package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +150 -150
  32. package/src/resources/skills/mandu-deployment/SKILL.md +92 -92
  33. package/src/resources/skills/mandu-deployment/_sections.md +41 -41
  34. package/src/resources/skills/mandu-deployment/_template.md +38 -38
  35. package/src/resources/skills/mandu-deployment/metadata.json +13 -13
  36. package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +109 -109
  37. package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +115 -115
  38. package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +219 -219
  39. package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +150 -150
  40. package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +223 -223
  41. package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +152 -152
  42. package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +179 -179
  43. package/src/resources/skills/mandu-deployment/rules/deploy-platform-supabase.md +323 -323
  44. package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +140 -140
  45. package/src/resources/skills/mandu-fs-routes/SKILL.md +82 -82
  46. package/src/resources/skills/mandu-fs-routes/metadata.json +12 -12
  47. package/src/resources/skills/mandu-fs-routes/rules/_sections.md +36 -36
  48. package/src/resources/skills/mandu-fs-routes/rules/_template.md +69 -69
  49. package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +65 -65
  50. package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +93 -93
  51. package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +55 -55
  52. package/src/resources/skills/mandu-guard/SKILL.md +129 -129
  53. package/src/resources/skills/mandu-guard/metadata.json +12 -12
  54. package/src/resources/skills/mandu-guard/rules/_sections.md +36 -36
  55. package/src/resources/skills/mandu-guard/rules/_template.md +82 -82
  56. package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +100 -100
  57. package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +76 -76
  58. package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +81 -81
  59. package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +80 -80
  60. package/src/resources/skills/mandu-hydration/SKILL.md +91 -91
  61. package/src/resources/skills/mandu-hydration/metadata.json +12 -12
  62. package/src/resources/skills/mandu-hydration/rules/_sections.md +31 -31
  63. package/src/resources/skills/mandu-hydration/rules/_template.md +72 -72
  64. package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +109 -109
  65. package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +55 -55
  66. package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +113 -113
  67. package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +68 -68
  68. package/src/resources/skills/mandu-performance/SKILL.md +85 -85
  69. package/src/resources/skills/mandu-performance/metadata.json +14 -14
  70. package/src/resources/skills/mandu-performance/rules/_sections.md +31 -31
  71. package/src/resources/skills/mandu-performance/rules/_template.md +64 -64
  72. package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +103 -103
  73. package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +95 -95
  74. package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +124 -124
  75. package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +125 -125
  76. package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +80 -80
  77. package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +145 -145
  78. package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +98 -98
  79. package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +154 -154
  80. package/src/resources/skills/mandu-security/SKILL.md +87 -87
  81. package/src/resources/skills/mandu-security/metadata.json +13 -13
  82. package/src/resources/skills/mandu-security/rules/_sections.md +31 -31
  83. package/src/resources/skills/mandu-security/rules/_template.md +74 -74
  84. package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +127 -127
  85. package/src/resources/skills/mandu-security/rules/sec-env-management.md +133 -133
  86. package/src/resources/skills/mandu-security/rules/sec-input-validate.md +148 -148
  87. package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +146 -146
  88. package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +138 -138
  89. package/src/resources/skills/mandu-slot/SKILL.md +85 -85
  90. package/src/resources/skills/mandu-slot/metadata.json +12 -12
  91. package/src/resources/skills/mandu-slot/rules/_sections.md +36 -36
  92. package/src/resources/skills/mandu-slot/rules/_template.md +63 -63
  93. package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +38 -38
  94. package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +56 -56
  95. package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +59 -59
  96. package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +64 -64
  97. package/src/resources/skills/mandu-styling/SKILL.md +154 -154
  98. package/src/resources/skills/mandu-styling/_sections.md +43 -43
  99. package/src/resources/skills/mandu-styling/_template.md +32 -32
  100. package/src/resources/skills/mandu-styling/metadata.json +15 -15
  101. package/src/resources/skills/mandu-styling/rules/style-component-compound.md +235 -235
  102. package/src/resources/skills/mandu-styling/rules/style-component-slots.md +255 -255
  103. package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +205 -205
  104. package/src/resources/skills/mandu-styling/rules/style-island-animations.md +272 -272
  105. package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +167 -167
  106. package/src/resources/skills/mandu-styling/rules/style-island-variants.md +221 -221
  107. package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +209 -209
  108. package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +192 -192
  109. package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +162 -162
  110. package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +164 -164
  111. package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +170 -170
  112. package/src/resources/skills/mandu-styling/rules/style-tailwind-v4-gotchas.md +179 -179
  113. package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +229 -229
  114. package/src/resources/skills/mandu-testing/SKILL.md +99 -99
  115. package/src/resources/skills/mandu-testing/metadata.json +13 -13
  116. package/src/resources/skills/mandu-testing/rules/_sections.md +26 -26
  117. package/src/resources/skills/mandu-testing/rules/_template.md +65 -65
  118. package/src/resources/skills/mandu-testing/rules/test-component-island.md +195 -195
  119. package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +196 -196
  120. package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +219 -219
  121. package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +192 -192
  122. package/src/resources/skills/mandu-ui/SKILL.md +117 -117
  123. package/src/resources/skills/mandu-ui/_sections.md +23 -23
  124. package/src/resources/skills/mandu-ui/_template.md +32 -32
  125. package/src/resources/skills/mandu-ui/metadata.json +13 -13
  126. package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +232 -232
  127. package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +238 -238
  128. package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +259 -259
  129. package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +258 -258
  130. package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +213 -213
  131. package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +209 -209
  132. package/src/resources/skills/recipes.ts +932 -932
  133. package/src/tools/generate.ts +7 -4
  134. package/src/tools/guard.ts +17 -4
  135. package/src/tools/hydration.ts +10 -10
  136. package/src/tools/project.ts +334 -334
  137. package/src/tools/runtime.ts +497 -497
  138. package/src/tools/seo.ts +417 -417
  139. package/src/tools/spec.ts +80 -159
  140. package/src/utils/project.ts +22 -12
  141. package/src/utils/withWarnings.ts +83 -83
@@ -1,229 +1,229 @@
1
- ---
2
- title: Dark Mode Implementation
3
- impact: MEDIUM
4
- impactDescription: User preference and accessibility support
5
- tags: styling, theme, darkmode, accessibility
6
- ---
7
-
8
- ## Dark Mode Implementation
9
-
10
- **Impact: MEDIUM (User preference and accessibility support)**
11
-
12
- 다크모드를 구현하여 사용자 선호도와 접근성을 지원하세요.
13
-
14
- ## CSS Variables 기반 테마
15
-
16
- ```css
17
- /* app/globals.css */
18
- @layer base {
19
- :root {
20
- --background: 0 0% 100%;
21
- --foreground: 222.2 84% 4.9%;
22
- --card: 0 0% 100%;
23
- --card-foreground: 222.2 84% 4.9%;
24
- --primary: 221.2 83.2% 53.3%;
25
- --primary-foreground: 210 40% 98%;
26
- --muted: 210 40% 96.1%;
27
- --muted-foreground: 215.4 16.3% 46.9%;
28
- --border: 214.3 31.8% 91.4%;
29
- }
30
-
31
- .dark {
32
- --background: 222.2 84% 4.9%;
33
- --foreground: 210 40% 98%;
34
- --card: 222.2 84% 4.9%;
35
- --card-foreground: 210 40% 98%;
36
- --primary: 217.2 91.2% 59.8%;
37
- --primary-foreground: 222.2 47.4% 11.2%;
38
- --muted: 217.2 32.6% 17.5%;
39
- --muted-foreground: 215 20.2% 65.1%;
40
- --border: 217.2 32.6% 17.5%;
41
- }
42
- }
43
- ```
44
-
45
- ## Tailwind dark: 활성화
46
-
47
- ```typescript
48
- // tailwind.config.ts
49
- export default {
50
- darkMode: "class", // 또는 "media"
51
- // ...
52
- };
53
- ```
54
-
55
- ## 테마 Provider Island
56
-
57
- ```tsx
58
- // app/theme/client.tsx
59
- "use client";
60
-
61
- import { createContext, useContext, useEffect, useState } from "react";
62
-
63
- type Theme = "light" | "dark" | "system";
64
-
65
- interface ThemeContextValue {
66
- theme: Theme;
67
- setTheme: (theme: Theme) => void;
68
- resolvedTheme: "light" | "dark";
69
- }
70
-
71
- const ThemeContext = createContext<ThemeContextValue | null>(null);
72
-
73
- export function ThemeProviderIsland({ children }: { children: React.ReactNode }) {
74
- const [theme, setTheme] = useState<Theme>("system");
75
- const [resolvedTheme, setResolvedTheme] = useState<"light" | "dark">("light");
76
-
77
- useEffect(() => {
78
- // 저장된 테마 복원
79
- const stored = localStorage.getItem("theme") as Theme | null;
80
- if (stored) {
81
- setTheme(stored);
82
- }
83
- }, []);
84
-
85
- useEffect(() => {
86
- const root = document.documentElement;
87
-
88
- if (theme === "system") {
89
- const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
90
- setResolvedTheme(systemDark ? "dark" : "light");
91
- root.classList.toggle("dark", systemDark);
92
- } else {
93
- setResolvedTheme(theme);
94
- root.classList.toggle("dark", theme === "dark");
95
- }
96
-
97
- localStorage.setItem("theme", theme);
98
- }, [theme]);
99
-
100
- // System 변경 감지
101
- useEffect(() => {
102
- if (theme !== "system") return;
103
-
104
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
105
- const handler = (e: MediaQueryListEvent) => {
106
- setResolvedTheme(e.matches ? "dark" : "light");
107
- document.documentElement.classList.toggle("dark", e.matches);
108
- };
109
-
110
- mq.addEventListener("change", handler);
111
- return () => mq.removeEventListener("change", handler);
112
- }, [theme]);
113
-
114
- return (
115
- <ThemeContext.Provider value={{ theme, setTheme, resolvedTheme }}>
116
- {children}
117
- </ThemeContext.Provider>
118
- );
119
- }
120
-
121
- export function useTheme() {
122
- const context = useContext(ThemeContext);
123
- if (!context) {
124
- throw new Error("useTheme must be used within ThemeProviderIsland");
125
- }
126
- return context;
127
- }
128
- ```
129
-
130
- ## 테마 토글 컴포넌트
131
-
132
- ```tsx
133
- // app/theme/toggle.tsx
134
- "use client";
135
-
136
- import { useTheme } from "./client";
137
-
138
- export function ThemeToggleIsland() {
139
- const { theme, setTheme, resolvedTheme } = useTheme();
140
-
141
- return (
142
- <button
143
- onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
144
- className="p-2 rounded-md hover:bg-muted"
145
- aria-label={`Switch to ${resolvedTheme === "dark" ? "light" : "dark"} mode`}
146
- >
147
- {resolvedTheme === "dark" ? "🌙" : "☀️"}
148
- </button>
149
- );
150
- }
151
- ```
152
-
153
- ## 플래시 방지 스크립트
154
-
155
- ```tsx
156
- // app/layout.tsx
157
- export default function RootLayout({ children }) {
158
- return (
159
- <html lang="ko" suppressHydrationWarning>
160
- <head>
161
- {/* 다크모드 플래시 방지 */}
162
- <script
163
- dangerouslySetInnerHTML={{
164
- __html: `
165
- (function() {
166
- const theme = localStorage.getItem('theme');
167
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
168
-
169
- if (theme === 'dark' || (!theme && prefersDark)) {
170
- document.documentElement.classList.add('dark');
171
- }
172
- })();
173
- `,
174
- }}
175
- />
176
- </head>
177
- <body>
178
- <ThemeProviderIsland>
179
- {children}
180
- </ThemeProviderIsland>
181
- </body>
182
- </html>
183
- );
184
- }
185
- ```
186
-
187
- ## Island 간 테마 동기화
188
-
189
- ```tsx
190
- // useIslandEvent로 테마 변경 전파
191
- import { useIslandEvent } from "@mandujs/core/client";
192
-
193
- export function ThemeProviderIsland({ children }) {
194
- const { emit } = useIslandEvent<{ theme: string }>("theme-change");
195
- const [theme, setTheme] = useState("system");
196
-
197
- const handleSetTheme = (newTheme: Theme) => {
198
- setTheme(newTheme);
199
- emit({ theme: newTheme }); // 다른 Island에 전파
200
- };
201
-
202
- // ...
203
- }
204
-
205
- // 다른 Island에서 수신
206
- export function AnotherIsland() {
207
- useIslandEvent<{ theme: string }>("theme-change", (data) => {
208
- console.log("Theme changed to:", data.theme);
209
- });
210
- }
211
- ```
212
-
213
- ## 다크모드 특화 스타일
214
-
215
- ```tsx
216
- // Tailwind dark: 접두사 사용
217
- <div className="bg-white dark:bg-gray-900">
218
- <p className="text-gray-900 dark:text-gray-100">
219
- Content
220
- </p>
221
- </div>
222
-
223
- // 복잡한 경우 CSS Variables 활용
224
- <div className="bg-[hsl(var(--background))]">
225
- {/* 자동으로 테마 반영 */}
226
- </div>
227
- ```
228
-
229
- Reference: [Tailwind Dark Mode](https://tailwindcss.com/docs/dark-mode)
1
+ ---
2
+ title: Dark Mode Implementation
3
+ impact: MEDIUM
4
+ impactDescription: User preference and accessibility support
5
+ tags: styling, theme, darkmode, accessibility
6
+ ---
7
+
8
+ ## Dark Mode Implementation
9
+
10
+ **Impact: MEDIUM (User preference and accessibility support)**
11
+
12
+ 다크모드를 구현하여 사용자 선호도와 접근성을 지원하세요.
13
+
14
+ ## CSS Variables 기반 테마
15
+
16
+ ```css
17
+ /* app/globals.css */
18
+ @layer base {
19
+ :root {
20
+ --background: 0 0% 100%;
21
+ --foreground: 222.2 84% 4.9%;
22
+ --card: 0 0% 100%;
23
+ --card-foreground: 222.2 84% 4.9%;
24
+ --primary: 221.2 83.2% 53.3%;
25
+ --primary-foreground: 210 40% 98%;
26
+ --muted: 210 40% 96.1%;
27
+ --muted-foreground: 215.4 16.3% 46.9%;
28
+ --border: 214.3 31.8% 91.4%;
29
+ }
30
+
31
+ .dark {
32
+ --background: 222.2 84% 4.9%;
33
+ --foreground: 210 40% 98%;
34
+ --card: 222.2 84% 4.9%;
35
+ --card-foreground: 210 40% 98%;
36
+ --primary: 217.2 91.2% 59.8%;
37
+ --primary-foreground: 222.2 47.4% 11.2%;
38
+ --muted: 217.2 32.6% 17.5%;
39
+ --muted-foreground: 215 20.2% 65.1%;
40
+ --border: 217.2 32.6% 17.5%;
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Tailwind dark: 활성화
46
+
47
+ ```typescript
48
+ // tailwind.config.ts
49
+ export default {
50
+ darkMode: "class", // 또는 "media"
51
+ // ...
52
+ };
53
+ ```
54
+
55
+ ## 테마 Provider Island
56
+
57
+ ```tsx
58
+ // app/theme/client.tsx
59
+ "use client";
60
+
61
+ import { createContext, useContext, useEffect, useState } from "react";
62
+
63
+ type Theme = "light" | "dark" | "system";
64
+
65
+ interface ThemeContextValue {
66
+ theme: Theme;
67
+ setTheme: (theme: Theme) => void;
68
+ resolvedTheme: "light" | "dark";
69
+ }
70
+
71
+ const ThemeContext = createContext<ThemeContextValue | null>(null);
72
+
73
+ export function ThemeProviderIsland({ children }: { children: React.ReactNode }) {
74
+ const [theme, setTheme] = useState<Theme>("system");
75
+ const [resolvedTheme, setResolvedTheme] = useState<"light" | "dark">("light");
76
+
77
+ useEffect(() => {
78
+ // 저장된 테마 복원
79
+ const stored = localStorage.getItem("theme") as Theme | null;
80
+ if (stored) {
81
+ setTheme(stored);
82
+ }
83
+ }, []);
84
+
85
+ useEffect(() => {
86
+ const root = document.documentElement;
87
+
88
+ if (theme === "system") {
89
+ const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
90
+ setResolvedTheme(systemDark ? "dark" : "light");
91
+ root.classList.toggle("dark", systemDark);
92
+ } else {
93
+ setResolvedTheme(theme);
94
+ root.classList.toggle("dark", theme === "dark");
95
+ }
96
+
97
+ localStorage.setItem("theme", theme);
98
+ }, [theme]);
99
+
100
+ // System 변경 감지
101
+ useEffect(() => {
102
+ if (theme !== "system") return;
103
+
104
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
105
+ const handler = (e: MediaQueryListEvent) => {
106
+ setResolvedTheme(e.matches ? "dark" : "light");
107
+ document.documentElement.classList.toggle("dark", e.matches);
108
+ };
109
+
110
+ mq.addEventListener("change", handler);
111
+ return () => mq.removeEventListener("change", handler);
112
+ }, [theme]);
113
+
114
+ return (
115
+ <ThemeContext.Provider value={{ theme, setTheme, resolvedTheme }}>
116
+ {children}
117
+ </ThemeContext.Provider>
118
+ );
119
+ }
120
+
121
+ export function useTheme() {
122
+ const context = useContext(ThemeContext);
123
+ if (!context) {
124
+ throw new Error("useTheme must be used within ThemeProviderIsland");
125
+ }
126
+ return context;
127
+ }
128
+ ```
129
+
130
+ ## 테마 토글 컴포넌트
131
+
132
+ ```tsx
133
+ // app/theme/toggle.tsx
134
+ "use client";
135
+
136
+ import { useTheme } from "./client";
137
+
138
+ export function ThemeToggleIsland() {
139
+ const { theme, setTheme, resolvedTheme } = useTheme();
140
+
141
+ return (
142
+ <button
143
+ onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
144
+ className="p-2 rounded-md hover:bg-muted"
145
+ aria-label={`Switch to ${resolvedTheme === "dark" ? "light" : "dark"} mode`}
146
+ >
147
+ {resolvedTheme === "dark" ? "🌙" : "☀️"}
148
+ </button>
149
+ );
150
+ }
151
+ ```
152
+
153
+ ## 플래시 방지 스크립트
154
+
155
+ ```tsx
156
+ // app/layout.tsx
157
+ export default function RootLayout({ children }) {
158
+ return (
159
+ <html lang="ko" suppressHydrationWarning>
160
+ <head>
161
+ {/* 다크모드 플래시 방지 */}
162
+ <script
163
+ dangerouslySetInnerHTML={{
164
+ __html: `
165
+ (function() {
166
+ const theme = localStorage.getItem('theme');
167
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
168
+
169
+ if (theme === 'dark' || (!theme && prefersDark)) {
170
+ document.documentElement.classList.add('dark');
171
+ }
172
+ })();
173
+ `,
174
+ }}
175
+ />
176
+ </head>
177
+ <body>
178
+ <ThemeProviderIsland>
179
+ {children}
180
+ </ThemeProviderIsland>
181
+ </body>
182
+ </html>
183
+ );
184
+ }
185
+ ```
186
+
187
+ ## Island 간 테마 동기화
188
+
189
+ ```tsx
190
+ // useIslandEvent로 테마 변경 전파
191
+ import { useIslandEvent } from "@mandujs/core/client";
192
+
193
+ export function ThemeProviderIsland({ children }) {
194
+ const { emit } = useIslandEvent<{ theme: string }>("theme-change");
195
+ const [theme, setTheme] = useState("system");
196
+
197
+ const handleSetTheme = (newTheme: Theme) => {
198
+ setTheme(newTheme);
199
+ emit({ theme: newTheme }); // 다른 Island에 전파
200
+ };
201
+
202
+ // ...
203
+ }
204
+
205
+ // 다른 Island에서 수신
206
+ export function AnotherIsland() {
207
+ useIslandEvent<{ theme: string }>("theme-change", (data) => {
208
+ console.log("Theme changed to:", data.theme);
209
+ });
210
+ }
211
+ ```
212
+
213
+ ## 다크모드 특화 스타일
214
+
215
+ ```tsx
216
+ // Tailwind dark: 접두사 사용
217
+ <div className="bg-white dark:bg-gray-900">
218
+ <p className="text-gray-900 dark:text-gray-100">
219
+ Content
220
+ </p>
221
+ </div>
222
+
223
+ // 복잡한 경우 CSS Variables 활용
224
+ <div className="bg-[hsl(var(--background))]">
225
+ {/* 자동으로 테마 반영 */}
226
+ </div>
227
+ ```
228
+
229
+ Reference: [Tailwind Dark Mode](https://tailwindcss.com/docs/dark-mode)
@@ -1,99 +1,99 @@
1
- ---
2
- name: mandu-testing
3
- description: |
4
- Testing patterns for Mandu applications. Use when writing unit tests,
5
- integration tests, or E2E tests. Triggers on test, spec, Bun test,
6
- Playwright, or testing tasks.
7
- license: MIT
8
- metadata:
9
- author: mandu
10
- version: "1.0.0"
11
- ---
12
-
13
- # Mandu Testing
14
-
15
- Mandu 애플리케이션의 테스트 패턴 가이드. Bun test를 활용한 단위 테스트, slot 테스트, Island 컴포넌트 테스트, Playwright E2E 테스트를 다룹니다.
16
-
17
- ## When to Apply
18
-
19
- Reference these guidelines when:
20
- - Writing unit tests for slots
21
- - Testing Island components
22
- - Setting up E2E tests with Playwright
23
- - Mocking external dependencies
24
- - Testing authentication flows
25
-
26
- ## Rule Categories by Priority
27
-
28
- | Priority | Category | Impact | Prefix |
29
- |----------|----------|--------|--------|
30
- | 1 | Slot Testing | HIGH | `test-slot-` |
31
- | 2 | Component Testing | HIGH | `test-component-` |
32
- | 3 | E2E Testing | MEDIUM | `test-e2e-` |
33
- | 4 | Mocking | MEDIUM | `test-mock-` |
34
-
35
- ## Quick Reference
36
-
37
- ### 1. Slot Testing (HIGH)
38
-
39
- - `test-slot-unit` - Unit test slot handlers
40
- - `test-slot-guard` - Test guard authentication
41
- - `test-slot-integration` - Integration test with database
42
-
43
- ### 2. Component Testing (HIGH)
44
-
45
- - `test-component-island` - Test Island components
46
- - `test-component-render` - Test rendering output
47
- - `test-component-interaction` - Test user interactions
48
-
49
- ### 3. E2E Testing (MEDIUM)
50
-
51
- - `test-e2e-playwright` - Playwright setup and patterns
52
- - `test-e2e-auth` - Test authentication flows
53
- - `test-e2e-navigation` - Test page navigation
54
-
55
- ### 4. Mocking (MEDIUM)
56
-
57
- - `test-mock-fetch` - Mock fetch requests
58
- - `test-mock-database` - Mock database operations
59
-
60
- ## Bun Test Quick Start
61
-
62
- ```bash
63
- # Run all tests
64
- bun test
65
-
66
- # Run specific test file
67
- bun test src/slots/user.test.ts
68
-
69
- # Watch mode
70
- bun test --watch
71
-
72
- # Coverage
73
- bun test --coverage
74
- ```
75
-
76
- ## Test File Convention
77
-
78
- ```
79
- spec/slots/
80
- ├── users.slot.ts
81
- ├── users.slot.test.ts # Slot tests
82
- app/
83
- ├── dashboard/
84
- │ ├── client.tsx
85
- │ └── client.test.tsx # Component tests
86
- tests/
87
- └── e2e/
88
- └── auth.spec.ts # E2E tests
89
- ```
90
-
91
- ## How to Use
92
-
93
- Read individual rule files for detailed explanations:
94
-
95
- ```
96
- rules/test-slot-unit.md
97
- rules/test-component-island.md
98
- rules/test-e2e-playwright.md
99
- ```
1
+ ---
2
+ name: mandu-testing
3
+ description: |
4
+ Testing patterns for Mandu applications. Use when writing unit tests,
5
+ integration tests, or E2E tests. Triggers on test, spec, Bun test,
6
+ Playwright, or testing tasks.
7
+ license: MIT
8
+ metadata:
9
+ author: mandu
10
+ version: "1.0.0"
11
+ ---
12
+
13
+ # Mandu Testing
14
+
15
+ Mandu 애플리케이션의 테스트 패턴 가이드. Bun test를 활용한 단위 테스트, slot 테스트, Island 컴포넌트 테스트, Playwright E2E 테스트를 다룹니다.
16
+
17
+ ## When to Apply
18
+
19
+ Reference these guidelines when:
20
+ - Writing unit tests for slots
21
+ - Testing Island components
22
+ - Setting up E2E tests with Playwright
23
+ - Mocking external dependencies
24
+ - Testing authentication flows
25
+
26
+ ## Rule Categories by Priority
27
+
28
+ | Priority | Category | Impact | Prefix |
29
+ |----------|----------|--------|--------|
30
+ | 1 | Slot Testing | HIGH | `test-slot-` |
31
+ | 2 | Component Testing | HIGH | `test-component-` |
32
+ | 3 | E2E Testing | MEDIUM | `test-e2e-` |
33
+ | 4 | Mocking | MEDIUM | `test-mock-` |
34
+
35
+ ## Quick Reference
36
+
37
+ ### 1. Slot Testing (HIGH)
38
+
39
+ - `test-slot-unit` - Unit test slot handlers
40
+ - `test-slot-guard` - Test guard authentication
41
+ - `test-slot-integration` - Integration test with database
42
+
43
+ ### 2. Component Testing (HIGH)
44
+
45
+ - `test-component-island` - Test Island components
46
+ - `test-component-render` - Test rendering output
47
+ - `test-component-interaction` - Test user interactions
48
+
49
+ ### 3. E2E Testing (MEDIUM)
50
+
51
+ - `test-e2e-playwright` - Playwright setup and patterns
52
+ - `test-e2e-auth` - Test authentication flows
53
+ - `test-e2e-navigation` - Test page navigation
54
+
55
+ ### 4. Mocking (MEDIUM)
56
+
57
+ - `test-mock-fetch` - Mock fetch requests
58
+ - `test-mock-database` - Mock database operations
59
+
60
+ ## Bun Test Quick Start
61
+
62
+ ```bash
63
+ # Run all tests
64
+ bun test
65
+
66
+ # Run specific test file
67
+ bun test src/slots/user.test.ts
68
+
69
+ # Watch mode
70
+ bun test --watch
71
+
72
+ # Coverage
73
+ bun test --coverage
74
+ ```
75
+
76
+ ## Test File Convention
77
+
78
+ ```
79
+ spec/slots/
80
+ ├── users.slot.ts
81
+ ├── users.slot.test.ts # Slot tests
82
+ app/
83
+ ├── dashboard/
84
+ │ ├── client.tsx
85
+ │ └── client.test.tsx # Component tests
86
+ tests/
87
+ └── e2e/
88
+ └── auth.spec.ts # E2E tests
89
+ ```
90
+
91
+ ## How to Use
92
+
93
+ Read individual rule files for detailed explanations:
94
+
95
+ ```
96
+ rules/test-slot-unit.md
97
+ rules/test-component-island.md
98
+ rules/test-e2e-playwright.md
99
+ ```
@@ -1,13 +1,13 @@
1
- {
2
- "version": "1.0.0",
3
- "organization": "Mandu Framework",
4
- "date": "February 2026",
5
- "abstract": "Mandu 애플리케이션 테스트 패턴 가이드. Bun test를 활용한 slot 단위/통합 테스트, Island 컴포넌트 테스트, Playwright E2E 테스트, 모킹 패턴을 다룹니다.",
6
- "references": [
7
- "https://bun.sh/docs/cli/test",
8
- "https://playwright.dev/docs/intro",
9
- "https://testing-library.com/docs/react-testing-library/intro",
10
- "https://kentcdodds.com/blog/write-tests"
11
- ],
12
- "tags": ["testing", "bun-test", "playwright", "e2e", "unit", "mandu"]
13
- }
1
+ {
2
+ "version": "1.0.0",
3
+ "organization": "Mandu Framework",
4
+ "date": "February 2026",
5
+ "abstract": "Mandu 애플리케이션 테스트 패턴 가이드. Bun test를 활용한 slot 단위/통합 테스트, Island 컴포넌트 테스트, Playwright E2E 테스트, 모킹 패턴을 다룹니다.",
6
+ "references": [
7
+ "https://bun.sh/docs/cli/test",
8
+ "https://playwright.dev/docs/intro",
9
+ "https://testing-library.com/docs/react-testing-library/intro",
10
+ "https://kentcdodds.com/blog/write-tests"
11
+ ],
12
+ "tags": ["testing", "bun-test", "playwright", "e2e", "unit", "mandu"]
13
+ }