@akanjs/cli 2.4.2-rc.3 → 3.0.0-alpha.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 (79) hide show
  1. package/.build-stamp +1 -1
  2. package/{abstractCompactor-ghh1q9an.js → abstractCompactor-rk6twzvj.js} +4 -4
  3. package/{agent.command-de4r6vk8.js → agent.command-jfz8yfwy.js} +8 -7
  4. package/{application.command-nfsfm96y.js → application.command-3smsv7mq.js} +5 -5
  5. package/{applicationBuildRunner-554a2vnk.js → applicationBuildRunner-aq7mb3z6.js} +2 -1
  6. package/buildBatch.proc.js +7 -6
  7. package/{capacitorApp-yg9b4ajz.js → capacitorApp-q3mpmkkz.js} +3 -3
  8. package/{cloud.command-1qf95x67.js → cloud.command-rk4e9vrt.js} +10 -10
  9. package/{context.command-hhjyjtp7.js → context.command-ygzyb0xb.js} +16 -15
  10. package/{guideline.command-vj956kfr.js → guideline.command-1m1ctar3.js} +10 -10
  11. package/guidelines/componentRule/componentRule.instruction.md +2 -2
  12. package/guidelines/cssRule/cssRule.generate.json +1 -1
  13. package/guidelines/cssRule/cssRule.instruction.md +57 -34
  14. package/guidelines/framework/framework.instruction.md +1 -1
  15. package/guidelines/recipeRule/recipeRule.generate.json +31 -0
  16. package/guidelines/recipeRule/recipeRule.instruction.md +72 -0
  17. package/incrementalBuilder.proc.js +5 -5
  18. package/{index-v9jqrdd1.js → index-4yp06pn1.js} +100 -2
  19. package/{index-pfnh87f9.js → index-4zgs8g1w.js} +1 -1
  20. package/{index-7ppn9v4n.js → index-b978vs2e.js} +3 -3
  21. package/{index-s9s0n5fz.js → index-cn24dcqn.js} +2 -2
  22. package/{index-h971erkm.js → index-csqk9z5j.js} +3 -3
  23. package/{index-z36qzgzp.js → index-e3qskyt2.js} +3 -4
  24. package/{index-fbv96xaw.js → index-ev6rjw9n.js} +11 -11
  25. package/{index-h6eav7zx.js → index-f4gqk0dd.js} +6 -6
  26. package/{index-z5v766nx.js → index-fmgbwsr5.js} +6 -6
  27. package/{index-y1e79mz3.js → index-h0bngh79.js} +13 -13
  28. package/{index-dgeaqwmw.js → index-hjzr8ja1.js} +1 -1
  29. package/{index-d0h48d2f.js → index-jk9q6pse.js} +1 -1
  30. package/{index-xwfg9bam.js → index-jtm86byd.js} +120 -4
  31. package/{index-h5cvg9z9.js → index-ktprgc5g.js} +4 -4
  32. package/{index-zn9rh7sh.js → index-n0z3f2xg.js} +73 -24
  33. package/{index-7k9sj7j5.js → index-pyt2b4nw.js} +212 -0
  34. package/{index-acwxfncv.js → index-r4w8cry5.js} +4 -4
  35. package/{index-zfp1gz9f.js → index-sggm9qkv.js} +1 -1
  36. package/{index-04as43rp.js → index-vhv3xnjz.js} +16 -15
  37. package/index-xjd3rqzj.js +129 -0
  38. package/{index-xftstr5s.js → index-xwgm94zr.js} +1 -1
  39. package/index-xys926f2.js +136 -0
  40. package/index.js +19 -19
  41. package/{library.command-68ah07a3.js → library.command-pwfx8dx2.js} +4 -4
  42. package/{localRegistry.command-84dz000g.js → localRegistry.command-bxhqmd1d.js} +9 -9
  43. package/{module.command-t68xhamx.js → module.command-0t3ewata.js} +8 -8
  44. package/{package.command-00ncttab.js → package.command-7hmkxvpa.js} +4 -4
  45. package/package.json +2 -3
  46. package/{page.command-1096s18n.js → page.command-st6r4s0q.js} +4 -4
  47. package/{primitive.command-02eqpx6t.js → primitive.command-1qkxpzsn.js} +9 -9
  48. package/{quality.command-r9cageqb.js → quality.command-hy5vt1bh.js} +3 -3
  49. package/recipeScanner-tghkzrrt.js +12 -0
  50. package/{repair.command-7dynpnf1.js → repair.command-nakkq2zp.js} +7 -6
  51. package/{scalar.command-3kxy3fkh.js → scalar.command-fjq272gs.js} +7 -7
  52. package/templates/app/page/_index.tsx +55 -52
  53. package/templates/app/page/styles.css.template +12 -71
  54. package/templates/appSample/lib/task/Task.Template.tsx +2 -2
  55. package/templates/appSample/lib/task/Task.Unit.tsx +11 -11
  56. package/templates/appSample/lib/task/Task.Util.tsx +27 -28
  57. package/templates/appSample/lib/task/Task.View.tsx +22 -19
  58. package/templates/appSample/lib/task/Task.Zone.tsx +3 -3
  59. package/templates/appSample/page/task/[taskId]/_index.tsx +3 -3
  60. package/templates/appSample/page/task/[taskId]/edit.tsx +5 -5
  61. package/templates/appSample/page/task/_index.tsx +4 -4
  62. package/templates/appSample/page/task/_layout.tsx +1 -1
  63. package/templates/appSample/page/task/new.tsx +5 -5
  64. package/templates/appSample/ui/GlobalLoading.tsx +4 -4
  65. package/templates/appSample/ui/QuantityControl.tsx +5 -4
  66. package/templates/crudPages/[__model__Id]/page.tsx +1 -1
  67. package/templates/crudPages/page.tsx +1 -1
  68. package/templates/crudSinglePage/page.tsx +1 -1
  69. package/templates/module/__Model__.Template.tsx +2 -1
  70. package/templates/module/__Model__.Unit.tsx +2 -1
  71. package/templates/module/__Model__.Util.tsx +2 -1
  72. package/templates/module/__Model__.View.tsx +4 -3
  73. package/templates/module/__Model__.Zone.tsx +2 -1
  74. package/templates/workspaceRoot/AGENTS.md.template +11 -13
  75. package/templates/workspaceRoot/biome.json.template +1 -1
  76. package/{workflow.command-yy0d9gk3.js → workflow.command-jswbgk90.js} +15 -14
  77. package/{workspace.command-stv9g4a0.js → workspace.command-p9r9nckg.js} +87 -27
  78. package/{applicationReleasePackager-pjbxc793.js → applicationReleasePackager-yrrhbkv3.js} +3 -3
  79. package/{index-nsj2ftxj.js → index-3pgtw35d.js} +3 -3
@@ -26,7 +26,7 @@ export default function Page() {
26
26
  const appName = getEnv().appName;
27
27
  const { l } = usePage();
28
28
  return (
29
- <main className="relative min-h-screen overflow-hidden bg-base-100 text-base-content">
29
+ <main className="relative min-h-screen overflow-hidden bg-background text-foreground">
30
30
  <div className="absolute -top-48 -left-48 h-96 w-96 rounded-full bg-primary/25 blur-3xl" />
31
31
  <div className="absolute -right-40 -bottom-56 h-112 w-md rounded-full bg-accent/20 blur-3xl" />
32
32
  <div className="absolute inset-x-0 top-0 h-px bg-linear-to-r from-transparent via-primary/60 to-transparent" />
@@ -34,7 +34,7 @@ export default function Page() {
34
34
  <section className="relative mx-auto flex min-h-screen w-full max-w-7xl flex-col px-6 py-8 lg:px-8">
35
35
  <nav className="flex items-center justify-between">
36
36
  <div className="flex items-center gap-3">
37
- <div className="flex h-11 w-11 items-center justify-center overflow-hidden rounded-2xl bg-base-100 shadow-lg shadow-primary/20">
37
+ <div className="flex h-11 w-11 items-center justify-center overflow-hidden rounded-2xl bg-background shadow-lg shadow-primary/20">
38
38
  <img
39
39
  src="/logo.png"
40
40
  alt={l.trans({ en: "Akan.js logo", ko: "Akan.js 로고" })}
@@ -43,7 +43,7 @@ export default function Page() {
43
43
  </div>
44
44
  <div>
45
45
  <p className="font-semibold text-primary text-sm tracking-[0.25em]">Akan.js</p>
46
- <p className="text-base-content/60 text-xs">
46
+ <p className="text-foreground/60 text-xs">
47
47
  {l.trans({ en: "Full-stack TypeScript framework", ko: "풀스택 타입스크립트 프레임워크" })}
48
48
  </p>
49
49
  </div>
@@ -52,7 +52,7 @@ export default function Page() {
52
52
  <System.ThemeToggle themes={["light", "dark"]} />
53
53
  <System.SelectLanguage languages={["en", "ko"]} />
54
54
  <Link href="https://akanjs.com" target="_blank">
55
- <button className="btn btn-sm border-base-content/10 bg-base-content/10 text-base-content hover:border-primary hover:bg-primary hover:text-base-100">
55
+ <button className="inline-flex items-center gap-2 rounded-field border border-foreground/10 bg-foreground/10 px-3 py-2 text-foreground text-sm transition-colors hover:border-primary hover:bg-primary hover:text-background">
56
56
  {l.trans({ en: "Official Site", ko: "공식 사이트" })}
57
57
  <FaExternalLinkAlt />
58
58
  </button>
@@ -62,17 +62,17 @@ export default function Page() {
62
62
 
63
63
  <div className="grid flex-1 items-center gap-10 py-16 lg:grid-cols-[1.04fr_0.96fr] lg:py-10">
64
64
  <div>
65
- <div className="badge mb-6 border-primary/20 bg-primary/10 px-4 py-3 text-primary">
65
+ <div className="mb-6 inline-flex items-center gap-1 rounded-full border border-primary/20 bg-primary/10 px-4 py-3 text-primary">
66
66
  <FaCheckCircle />
67
67
  {l.trans({ en: "Your app is running", ko: "앱이 실행 중입니다" })}
68
68
  </div>
69
- <h1 className="max-w-4xl font-black text-5xl text-base-content tracking-tight sm:text-6xl lg:text-7xl">
69
+ <h1 className="max-w-4xl font-black text-5xl text-foreground tracking-tight sm:text-6xl lg:text-7xl">
70
70
  {l.trans({
71
71
  en: "Akan turns business intent into the whole product.",
72
72
  ko: "Akan은 비즈니스 의도를 제품 전체로 바꿉니다.",
73
73
  })}
74
74
  </h1>
75
- <p className="mt-6 max-w-2xl text-base-content/70 text-lg leading-8">
75
+ <p className="mt-6 max-w-2xl text-foreground/70 text-lg leading-8">
76
76
  {l.trans({
77
77
  en: "Agents Write. Keep It Minimal. Always Readable. Nice To Review. Build with less code, fewer repeated decisions, and a clearer path from idea to production.",
78
78
  ko: "Agents Write. Keep It Minimal. Always Readable. Nice To Review. 더 적은 코드, 더 적은 반복 결정, 더 선명한 출시 경로로 만드세요.",
@@ -80,29 +80,29 @@ export default function Page() {
80
80
  </p>
81
81
 
82
82
  <div className="mt-8 flex flex-wrap gap-3">
83
- <span className="badge badge-lg border-base-content/10 bg-base-content/10 text-base-content">
83
+ <span className="inline-flex items-center gap-1 rounded-full border border-foreground/10 bg-foreground/10 px-4 py-1.5 text-foreground text-sm">
84
84
  Agent-ready
85
85
  </span>
86
- <span className="badge badge-lg border-base-content/10 bg-base-content/10 text-base-content">
86
+ <span className="inline-flex items-center gap-1 rounded-full border border-foreground/10 bg-foreground/10 px-4 py-1.5 text-foreground text-sm">
87
87
  Minimal code
88
88
  </span>
89
- <span className="badge badge-lg border-base-content/10 bg-base-content/10 text-base-content">
89
+ <span className="inline-flex items-center gap-1 rounded-full border border-foreground/10 bg-foreground/10 px-4 py-1.5 text-foreground text-sm">
90
90
  Readable by default
91
91
  </span>
92
- <span className="badge badge-lg border-base-content/10 bg-base-content/10 text-base-content">
92
+ <span className="inline-flex items-center gap-1 rounded-full border border-foreground/10 bg-foreground/10 px-4 py-1.5 text-foreground text-sm">
93
93
  Review-friendly
94
94
  </span>
95
95
  </div>
96
96
 
97
97
  <div className="mt-10 flex flex-col gap-3 sm:flex-row">
98
98
  <Link href="https://akanjs.com/docs/intro/quickstart" target="_blank">
99
- <button className="btn border-none bg-primary text-base-100 hover:bg-primary/80">
99
+ <button className="inline-flex items-center justify-center gap-2 rounded-field bg-primary px-4 py-2 text-background text-sm transition-colors hover:bg-primary/80">
100
100
  {l.trans({ en: "Read Quick Start", ko: "빠른 시작 읽기" })}
101
101
  <FaBookOpen />
102
102
  </button>
103
103
  </Link>
104
104
  <Link href="https://akanjs.com/docs/intro/practice" target="_blank">
105
- <button className="btn border-base-content/10 bg-base-content/10 text-base-content hover:border-base-content/20 hover:bg-base-content/15">
105
+ <button className="inline-flex items-center justify-center gap-2 rounded-field border border-foreground/10 bg-foreground/10 px-4 py-2 text-foreground text-sm transition-colors hover:border-foreground/20 hover:bg-foreground/15">
106
106
  {l.trans({ en: "Learn By Building", ko: "만들면서 배우기" })}
107
107
  <FaCodeBranch />
108
108
  </button>
@@ -112,13 +112,13 @@ export default function Page() {
112
112
 
113
113
  <div className="relative">
114
114
  <div className="absolute inset-0 rotate-3 rounded-4xl bg-primary/20 blur-2xl" />
115
- <div className="relative overflow-hidden rounded-4xl border border-base-content/10 bg-base-content/6 p-5 shadow-2xl backdrop-blur">
116
- <div className="mb-5 flex items-center justify-between rounded-2xl border border-base-content/10 bg-base-100/70 px-4 py-3">
115
+ <div className="relative overflow-hidden rounded-4xl border border-foreground/10 bg-foreground/6 p-5 shadow-2xl backdrop-blur">
116
+ <div className="mb-5 flex items-center justify-between rounded-2xl border border-foreground/10 bg-background/70 px-4 py-3">
117
117
  <div>
118
- <p className="text-base-content/40 text-xs uppercase tracking-[0.24em]">
118
+ <p className="text-foreground/40 text-xs uppercase tracking-[0.24em]">
119
119
  {l.trans({ en: "Akan Acrostic", ko: "Akan 사행시" })}
120
120
  </p>
121
- <p className="font-semibold text-base-content text-lg">
121
+ <p className="font-semibold text-foreground text-lg">
122
122
  {l.trans({ en: "A framework for focused builders", ko: "집중하는 빌더를 위한 프레임워크" })}
123
123
  </p>
124
124
  </div>
@@ -126,14 +126,14 @@ export default function Page() {
126
126
  </div>
127
127
 
128
128
  <div className="grid gap-3">
129
- <div className="rounded-2xl border border-base-content/10 bg-base-100/80 p-4">
129
+ <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
130
130
  <div className="flex gap-4">
131
- <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-base-100 font-black text-primary text-xl">
131
+ <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-background font-black text-primary text-xl">
132
132
  A
133
133
  </div>
134
134
  <div>
135
- <p className="font-bold text-base-content">Agents Write</p>
136
- <p className="mt-1 text-base-content/60 text-sm leading-6">
135
+ <p className="font-bold text-foreground">Agents Write</p>
136
+ <p className="mt-1 text-foreground/60 text-sm leading-6">
137
137
  {l.trans({
138
138
  en: "Business definitions become the source code, so teams and agents can focus on what to build.",
139
139
  ko: "비즈니스 정의가 소스 코드가 되므로, 팀과 에이전트는 무엇을 만들지에 집중할 수 있습니다.",
@@ -142,14 +142,14 @@ export default function Page() {
142
142
  </div>
143
143
  </div>
144
144
  </div>
145
- <div className="rounded-2xl border border-base-content/10 bg-base-100/80 p-4">
145
+ <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
146
146
  <div className="flex gap-4">
147
- <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-base-100 font-black text-primary text-xl">
147
+ <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-background font-black text-primary text-xl">
148
148
  K
149
149
  </div>
150
150
  <div>
151
- <p className="font-bold text-base-content">Keep It Minimal</p>
152
- <p className="mt-1 text-base-content/60 text-sm leading-6">
151
+ <p className="font-bold text-foreground">Keep It Minimal</p>
152
+ <p className="mt-1 text-foreground/60 text-sm leading-6">
153
153
  {l.trans({
154
154
  en: "One definition flows into web, app, server, database, and infrastructure without repeated logic.",
155
155
  ko: "하나의 정의가 반복 로직 없이 웹, 앱, 서버, 데이터베이스, 인프라로 이어집니다.",
@@ -158,14 +158,14 @@ export default function Page() {
158
158
  </div>
159
159
  </div>
160
160
  </div>
161
- <div className="rounded-2xl border border-base-content/10 bg-base-100/80 p-4">
161
+ <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
162
162
  <div className="flex gap-4">
163
- <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-base-100 font-black text-primary text-xl">
163
+ <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-background font-black text-primary text-xl">
164
164
  A
165
165
  </div>
166
166
  <div>
167
- <p className="font-bold text-base-content">Always Readable</p>
168
- <p className="mt-1 text-base-content/60 text-sm leading-6">
167
+ <p className="font-bold text-foreground">Always Readable</p>
168
+ <p className="mt-1 text-foreground/60 text-sm leading-6">
169
169
  {l.trans({
170
170
  en: "Strict conventions keep the app easy to understand long after the first version ships.",
171
171
  ko: "엄격한 컨벤션은 첫 버전 출시 후에도 앱을 쉽게 이해할 수 있게 지켜줍니다.",
@@ -174,14 +174,14 @@ export default function Page() {
174
174
  </div>
175
175
  </div>
176
176
  </div>
177
- <div className="rounded-2xl border border-base-content/10 bg-base-100/80 p-4">
177
+ <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
178
178
  <div className="flex gap-4">
179
- <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-base-100 font-black text-primary text-xl">
179
+ <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-background font-black text-primary text-xl">
180
180
  N
181
181
  </div>
182
182
  <div>
183
- <p className="font-bold text-base-content">Nice To Review</p>
184
- <p className="mt-1 text-base-content/60 text-sm leading-6">
183
+ <p className="font-bold text-foreground">Nice To Review</p>
184
+ <p className="mt-1 text-foreground/60 text-sm leading-6">
185
185
  {l.trans({
186
186
  en: "Focused changes make business intent clear, so reviews stay fast and releases stay calm.",
187
187
  ko: "집중된 변경은 비즈니스 의도를 선명하게 만들어 리뷰를 빠르게 하고 배포를 안정적으로 유지합니다.",
@@ -192,17 +192,20 @@ export default function Page() {
192
192
  </div>
193
193
  </div>
194
194
 
195
- <div className="mockup-code mt-5 border border-base-content/10 bg-base-100 text-sm shadow-none">
196
- <pre data-prefix="$">
195
+ <div className="mt-5 overflow-x-auto rounded-box border border-foreground/10 bg-background py-4 font-mono text-sm">
196
+ <pre className="px-6">
197
+ <span className="select-none text-foreground/40">$ </span>
197
198
  <code className="text-primary">bun run akan start {appName}</code>
198
199
  </pre>
199
- <pre data-prefix="">
200
+ <pre className="px-6">
201
+ <span className="select-none text-foreground/40">✓ </span>
200
202
  <code className="text-accent">
201
203
  {l.trans({ en: "web, app, server, db, and infra ready", ko: "웹, 앱, 서버, DB, 인프라 준비 완료" })}
202
204
  </code>
203
205
  </pre>
204
- <pre data-prefix="">
205
- <code className="text-base-content/70">
206
+ <pre className="px-6">
207
+ <span className="select-none text-foreground/40">→ </span>
208
+ <code className="text-foreground/70">
206
209
  {l.trans({
207
210
  en: "edit page/_index.tsx around your business",
208
211
  ko: "비즈니스에 맞게 page/_index.tsx를 수정하세요",
@@ -215,56 +218,56 @@ export default function Page() {
215
218
  </div>
216
219
 
217
220
  <div className="grid gap-4 pb-8 md:grid-cols-2 xl:grid-cols-4">
218
- <div className="rounded-3xl border border-base-content/10 bg-base-content/4 p-6 backdrop-blur">
221
+ <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
219
222
  <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
220
223
  <FaTerminal />
221
224
  </div>
222
- <h2 className="font-bold text-base-content text-lg">
225
+ <h2 className="font-bold text-foreground text-lg">
223
226
  {l.trans({ en: "Agentic By Design", ko: "에이전틱 설계" })}
224
227
  </h2>
225
- <p className="mt-2 text-base-content/60 text-sm leading-6">
228
+ <p className="mt-2 text-foreground/60 text-sm leading-6">
226
229
  {l.trans({
227
230
  en: "Describe the business once and let Akan shape the application surfaces around it.",
228
231
  ko: "비즈니스를 한 번 설명하면 Akan이 그 주변의 애플리케이션 표면을 구성합니다.",
229
232
  })}
230
233
  </p>
231
234
  </div>
232
- <div className="rounded-3xl border border-base-content/10 bg-base-content/4 p-6 backdrop-blur">
235
+ <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
233
236
  <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
234
237
  <FaLayerGroup />
235
238
  </div>
236
- <h2 className="font-bold text-base-content text-lg">
239
+ <h2 className="font-bold text-foreground text-lg">
237
240
  {l.trans({ en: "One Definition", ko: "하나의 정의" })}
238
241
  </h2>
239
- <p className="mt-2 text-base-content/60 text-sm leading-6">
242
+ <p className="mt-2 text-foreground/60 text-sm leading-6">
240
243
  {l.trans({
241
244
  en: "Pages, services, database models, and deployment artifacts stay connected in one workspace.",
242
245
  ko: "페이지, 서비스, 데이터베이스 모델, 배포 산출물이 하나의 워크스페이스에서 연결됩니다.",
243
246
  })}
244
247
  </p>
245
248
  </div>
246
- <div className="rounded-3xl border border-base-content/10 bg-base-content/4 p-6 backdrop-blur">
249
+ <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
247
250
  <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
248
251
  <FaRocket />
249
252
  </div>
250
- <h2 className="font-bold text-base-content text-lg">
253
+ <h2 className="font-bold text-foreground text-lg">
251
254
  {l.trans({ en: "Less To Review", ko: "리뷰할 것이 적습니다" })}
252
255
  </h2>
253
- <p className="mt-2 text-base-content/60 text-sm leading-6">
256
+ <p className="mt-2 text-foreground/60 text-sm leading-6">
254
257
  {l.trans({
255
258
  en: "Smaller code surfaces make intent easier to inspect, approve, and ship.",
256
259
  ko: "더 작은 코드 표면은 의도를 확인하고 승인하고 배포하기 쉽게 만듭니다.",
257
260
  })}
258
261
  </p>
259
262
  </div>
260
- <div className="rounded-3xl border border-base-content/10 bg-base-content/4 p-6 backdrop-blur">
263
+ <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
261
264
  <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
262
265
  <FaShieldAlt />
263
266
  </div>
264
- <h2 className="font-bold text-base-content text-lg">
267
+ <h2 className="font-bold text-foreground text-lg">
265
268
  {l.trans({ en: "Type-Safe Growth", ko: "타입 안전한 성장" })}
266
269
  </h2>
267
- <p className="mt-2 text-base-content/60 text-sm leading-6">
270
+ <p className="mt-2 text-foreground/60 text-sm leading-6">
268
271
  {l.trans({
269
272
  en: "Conventions and contracts keep the stack readable as the product expands.",
270
273
  ko: "컨벤션과 계약은 제품이 확장되어도 스택을 읽기 쉽게 유지합니다.",
@@ -273,7 +276,7 @@ export default function Page() {
273
276
  </div>
274
277
  </div>
275
278
 
276
- <div className="flex flex-col items-start justify-between gap-4 rounded-3xl border border-base-content/10 bg-base-content/4 p-5 text-base-content/70 text-sm md:flex-row md:items-center">
279
+ <div className="flex flex-col items-start justify-between gap-4 rounded-3xl border border-foreground/10 bg-foreground/4 p-5 text-foreground/70 text-sm md:flex-row md:items-center">
277
280
  <div className="flex items-center gap-3">
278
281
  <FaTerminal className="text-primary" />
279
282
  <span>
@@ -283,7 +286,7 @@ export default function Page() {
283
286
  })}
284
287
  </span>
285
288
  </div>
286
- <div className="flex items-center gap-2 text-base-content/40">
289
+ <div className="flex items-center gap-2 text-foreground/40">
287
290
  <FaBoxOpen />
288
291
  <span>{l.trans({ en: "Akan.js template", ko: "Akan.js 템플릿" })}</span>
289
292
  </div>
@@ -1,76 +1,17 @@
1
1
  @import "tailwindcss";
2
2
  @import "akanjs/ui/styles.css";
3
3
 
4
- @plugin "daisyui" {
5
- logs: false;
6
- exclude: properties;
7
- themes: false;
8
- }
4
+ /* 테마 시스템(브랜드-중립 기본 팔레트 · @theme inline 매핑 · dark 변형 · 런타임 data-theme 전환)은
5
+ akanjs/ui/styles.css(프레임워크)가 전부 제공한다. 이 앱은 import 만으로 즉시 동작한다.
9
6
 
10
- @plugin "daisyui/theme" {
11
- name: "light";
12
- --color-primary: #c33c32;
13
- --color-secondary: #2b2e33;
14
- --color-accent: #e67e22;
15
- --color-accent-content: #ffffff;
16
- --color-base-content: #2c3e50;
17
- --color-base-100: #fafafa;
18
- --color-base-200: #f5f5f5;
19
- --color-info: #f1fdff;
20
- --color-info-content: #2c3e50;
21
- --color-neutral: #292c32;
22
- --color-neutral-content: #fafafa;
23
- --color-success: #2ecc71;
24
- --color-success-content: #fafafa;
25
- --color-warning: #f39c12;
26
- --color-warning-content: #fafafa;
27
- --color-error: #e74c3c;
28
- --color-error-content: #fafafa;
29
- --color-open: #27ae60;
30
- --color-open-content: #fafafa;
7
+ 앱만의 브랜드 색을 쓰려면 아래처럼 토큰만 override 하면 된다:
31
8
 
32
- /* Shape & feel — customize these too, not just colors, to make the theme yours.
33
- These are daisyUI v5 theme variables; the values below are the neutral defaults.
34
- See `akan guideline show cssRule` and https://daisyui.com/docs/themes/ for the full set. */
35
- --radius-selector: 1rem; /* checkbox, toggle, badge corner rounding */
36
- --radius-field: 0.5rem; /* button, input, select, tab corner rounding */
37
- --radius-box: 1rem; /* card, modal, alert corner rounding */
38
- --size-selector: 0.25rem; /* base scale (density) for selector controls */
39
- --size-field: 0.25rem; /* base scale (density) for field controls */
40
- --border: 1px; /* component border width */
41
- --depth: 0; /* 1 = subtle 3D depth on components */
42
- --noise: 0; /* 1 = grain texture on surfaces */
43
- }
44
-
45
- @plugin "daisyui/theme" {
46
- name: "dark";
47
- default: true;
48
- --color-primary: #ff493b;
49
- --color-secondary: #2b2e33;
50
- --color-accent: #d1a23b;
51
- --color-accent-content: #ffffff;
52
- --color-base-content: #ffffff;
53
- --color-base-100: #1a1a1a;
54
- --color-base-200: #2a2a2a;
55
- --color-info: #173b78;
56
- --color-info-content: #ffffff;
57
- --color-neutral: #3ed13b;
58
- --color-neutral-content: #ffffff;
59
- --color-success: #255fc3;
60
- --color-success-content: #ffffff;
61
- --color-warning: #ffcc00;
62
- --color-warning-content: #ffffff;
63
- --color-error: #f02020;
64
- --color-error-content: #ffffff;
65
- --color-open: #10fc00;
66
-
67
- /* Keep shape & feel consistent with the light theme (usually the same values across modes). */
68
- --radius-selector: 1rem;
69
- --radius-field: 0.5rem;
70
- --radius-box: 1rem;
71
- --size-selector: 0.25rem;
72
- --size-field: 0.25rem;
73
- --border: 1px;
74
- --depth: 0;
75
- --noise: 0;
76
- }
9
+ :root,
10
+ [data-theme="dark"] {
11
+ --primary: #xxxxxx;
12
+ --primary-foreground: #ffffff;
13
+ }
14
+ [data-theme="light"] {
15
+ --primary: #xxxxxx;
16
+ }
17
+ */
@@ -5,7 +5,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
5
5
  filename: "Task.Template.tsx",
6
6
  content: `"use client";
7
7
  import { st, usePage } from "@apps/${dict.appName}/client";
8
- import { clsx } from "akanjs/client";
8
+ import { cn } from "akanjs/client";
9
9
  import { Field, Layout } from "akanjs/ui";
10
10
 
11
11
  // ===== Task.Template.tsx =====
@@ -25,7 +25,7 @@ export const General = ({ className }: TaskEditProps) => {
25
25
  const { l } = usePage();
26
26
 
27
27
  return (
28
- <Layout.Template className={clsx("flex flex-col gap-4", className)}>
28
+ <Layout.Template className={cn("flex flex-col gap-4", className)}>
29
29
  <Field.Text
30
30
  label={l("task.title")}
31
31
  desc={l("task.title.desc")}
@@ -4,8 +4,8 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
4
4
  return {
5
5
  filename: "Task.Unit.tsx",
6
6
  content: `import { type cnst, usePage } from "@apps/${dict.appName}/client";
7
- import { type ModelProps, clsx } from "akanjs/client";
8
- import { Layout } from "akanjs/ui";
7
+ import { type ModelProps, cn } from "akanjs/client";
8
+ import { badgeRecipe, Layout } from "akanjs/ui";
9
9
 
10
10
  // ===== Task.Unit.tsx =====
11
11
  // Convention: lib/<module>/ — PascalCase .tsx, Unit suffix = card/list-item component.
@@ -22,25 +22,25 @@ interface CardProps extends ModelProps<"task", cnst.LightTask> {
22
22
  export const Card = ({ task, className, href }: CardProps) => {
23
23
  const { l } = usePage();
24
24
  const statusBadge = {
25
- todo: "badge-ghost",
26
- inProgress: "badge-primary",
27
- completed: "badge-success",
25
+ todo: badgeRecipe({ variant: "default" }),
26
+ inProgress: badgeRecipe({ variant: "primary" }),
27
+ completed: badgeRecipe({ variant: "success" }),
28
28
  }[task.status];
29
29
 
30
30
  return (
31
31
  <Layout.Unit
32
- className={clsx(
33
- "rounded-lg border border-base-content/10 bg-base-100 p-4 transition-shadow hover:shadow-md",
32
+ className={cn(
33
+ "rounded-lg border border-foreground/10 bg-background p-4 transition-shadow hover:shadow-md",
34
34
  className,
35
35
  )}
36
36
  href={href}
37
37
  >
38
38
  <div className="flex items-start justify-between gap-2">
39
- <span className="font-semibold text-base-content">{task.title}</span>
40
- <span className={clsx("badge badge-sm shrink-0", statusBadge)}>{l(\`taskStatus.\${task.status}\`)}</span>
39
+ <span className="font-semibold text-foreground">{task.title}</span>
40
+ <span className={cn(statusBadge, "shrink-0")}>{l(\`taskStatus.\${task.status}\`)}</span>
41
41
  </div>
42
42
  {task.due && (
43
- <div className="mt-2 text-base-content/60 text-xs">
43
+ <div className="mt-2 text-foreground/60 text-xs">
44
44
  {l("task.taskDueLabel")} {task.due.toDate().toLocaleDateString()}
45
45
  </div>
46
46
  )}
@@ -52,7 +52,7 @@ export const Card = ({ task, className, href }: CardProps) => {
52
52
  // Mini: smaller inline display (tag, chip style)
53
53
  // export const Mini = ({ task }: MiniProps) => (
54
54
  // <span className="inline-flex items-center gap-1 text-sm">
55
- // <span className={clsx("badge badge-xs", statusBadge)}>{task.status}</span>
55
+ // <span className={cn("badge badge-xs", statusBadge)}>{task.status}</span>
56
56
  // {task.title}
57
57
  // </span>
58
58
  // );
@@ -5,7 +5,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
5
5
  filename: "Task.Util.tsx",
6
6
  content: `"use client";
7
7
  import { fetch, st, usePage } from "@apps/${dict.appName}/client";
8
- import { Model } from "akanjs/ui";
8
+ import { buttonRecipe, Dropdown, Model } from "akanjs/ui";
9
9
 
10
10
  // ===== Task.Util.tsx =====
11
11
  // Convention: lib/<module>/ — PascalCase .tsx, Util suffix = action buttons/utility components.
@@ -20,7 +20,7 @@ interface StartProps {
20
20
 
21
21
  export const Start = ({ taskId }: StartProps) => (
22
22
  <button
23
- className="btn btn-xs border-primary/20 bg-primary/10 text-primary hover:bg-primary hover:text-primary-content"
23
+ className={buttonRecipe({ size: "xs" }, "border-primary/20 bg-primary/10 text-primary hover:bg-primary hover:text-primary-foreground")}
24
24
  onClick={() => st.do.startTask(taskId)}
25
25
  >
26
26
  {usePage().l("task.taskStart")}
@@ -33,7 +33,7 @@ interface CompleteProps {
33
33
 
34
34
  export const Complete = ({ taskId }: CompleteProps) => (
35
35
  <button
36
- className="btn btn-xs border-success/20 bg-success/10 text-success hover:bg-success hover:text-success-content"
36
+ className={buttonRecipe({ size: "xs" }, "border-success/20 bg-success/10 text-success hover:bg-success hover:text-success-foreground")}
37
37
  onClick={() => st.do.completeTask(taskId)}
38
38
  >
39
39
  {usePage().l("task.taskComplete")}
@@ -46,7 +46,7 @@ interface RemoveProps {
46
46
 
47
47
  export const Remove = ({ taskId }: RemoveProps) => (
48
48
  <Model.Remove modelId={taskId} slice={fetch.slice.task}>
49
- <button className="btn btn-xs btn-ghost text-error">{usePage().l("task.taskRemove")}</button>
49
+ <button className={buttonRecipe({ variant: "ghost", size: "xs" }, "text-destructive")}>{usePage().l("task.taskRemove")}</button>
50
50
  </Model.Remove>
51
51
  );
52
52
 
@@ -58,31 +58,30 @@ interface ToolboxProps {
58
58
  export const Toolbox = ({ taskId, status }: ToolboxProps) => {
59
59
  const { l } = usePage();
60
60
  return (
61
- <div className="dropdown dropdown-end">
62
- <button tabIndex={0} className="btn btn-xs btn-ghost">
63
- ···
64
- </button>
65
- <ul
66
- tabIndex={0}
67
- className="dropdown-content menu z-[1] w-40 rounded-box border border-base-content/10 bg-base-100 p-2 shadow"
68
- >
69
- {status === "todo" && (
61
+ <Dropdown
62
+ buttonClassName={buttonRecipe({ variant: "ghost", size: "xs" })}
63
+ value={<span>···</span>}
64
+ dropdownClassName="w-40 rounded-box border border-foreground/10 bg-background p-2"
65
+ content={
66
+ <>
67
+ {status === "todo" && (
68
+ <li>
69
+ <button onClick={() => st.do.startTask(taskId)}>{l("task.taskStart")}</button>
70
+ </li>
71
+ )}
72
+ {status === "inProgress" && (
73
+ <li>
74
+ <button onClick={() => st.do.completeTask(taskId)}>{l("task.taskComplete")}</button>
75
+ </li>
76
+ )}
70
77
  <li>
71
- <button onClick={() => st.do.startTask(taskId)}>{l("task.taskStart")}</button>
78
+ <button className="text-destructive" onClick={() => st.do.removeTask(taskId)}>
79
+ {l("task.taskRemove")}
80
+ </button>
72
81
  </li>
73
- )}
74
- {status === "inProgress" && (
75
- <li>
76
- <button onClick={() => st.do.completeTask(taskId)}>{l("task.taskComplete")}</button>
77
- </li>
78
- )}
79
- <li>
80
- <button className="text-error" onClick={() => st.do.removeTask(taskId)}>
81
- {l("task.taskRemove")}
82
- </button>
83
- </li>
84
- </ul>
85
- </div>
82
+ </>
83
+ }
84
+ />
86
85
  );
87
86
  };
88
87
 
@@ -97,7 +96,7 @@ export const Toolbox = ({ taskId, status }: ToolboxProps) => {
97
96
  // New Task Button: Model.NewWrapper — triggers new Task creation form
98
97
  // export const NewTask = () => (
99
98
  // <Model.NewWrapper partial={{}}>
100
- // <button className="btn btn-primary btn-sm">+ New Task</button>
99
+ // <button className={buttonRecipe({ variant: "primary", size: "sm" })}>+ New Task</button>
101
100
  // </Model.NewWrapper>
102
101
  // );
103
102
  `,