@akanjs/cli 3.0.0-beta.9 → 3.0.1

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 (224) hide show
  1. package/.build-stamp +1 -1
  2. package/CodeAgent-zfab7pkn.js +9 -0
  3. package/CodeAgentRpcHost-p7h6n2hp.js +7 -0
  4. package/CodeAgentRpcListener-7p7z5dd7.js +97 -0
  5. package/CodeTui-0zhnr0pw.js +1457 -0
  6. package/README.ko.md +83 -28
  7. package/README.md +70 -27
  8. package/TunnelShare-cwh9ezsm.js +9 -0
  9. package/{agent.command-0q17pnrs.js → agent.command-aja6z9mn.js} +8 -9
  10. package/akanCode.js +102 -0
  11. package/application.command-049ehgx3.js +246 -0
  12. package/{applicationBuildRunner-kxwbssgn.js → applicationBuildRunner-75n5rpwp.js} +121 -77
  13. package/buildBatch.proc.js +120 -32
  14. package/cloud.command-gw4kqxt8.js +95 -0
  15. package/cloud.script-c723cpcb.js +20 -0
  16. package/code.command-x9t6z5nw.js +154 -0
  17. package/commandManifest.json +1 -1
  18. package/consoleToStderr-h5bryj94.js +7 -0
  19. package/context.command-yfbe1rtd.js +48 -0
  20. package/context.runner-erfe68j5.js +21 -0
  21. package/{dependencyScanner-shs82ynp.js → dependencyScanner-06z2dmrr.js} +2 -2
  22. package/{devTui-m1atgkc9.js → devTui-q7k7bakd.js} +122 -40
  23. package/fileSys-wzzrntkw.js +9 -0
  24. package/guideline.command-kq9gp690.js +42 -0
  25. package/guidelines/agentRule/agentRule.instruction.md +154 -26
  26. package/guidelines/conventions/conventions.instruction.md +138 -48
  27. package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
  28. package/guidelines/queryRule/queryRule.instruction.md +21 -7
  29. package/guidelines/runtimeRule/runtimeRule.instruction.md +291 -6
  30. package/guidelines/ssrRule/ssrRule.instruction.md +4 -2
  31. package/guidelines/transportRule/transportRule.instruction.md +10 -8
  32. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +20 -0
  33. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +66 -3
  34. package/incrementalBuilder.proc.js +564 -109
  35. package/{index-2tv3fdx4.js → index-150s07n8.js} +1230 -1459
  36. package/{index-vyvre9en.js → index-25fvrxmy.js} +6 -2
  37. package/{index-kcxmv48c.js → index-2ahj896a.js} +45 -79
  38. package/index-2wc41k5w.js +49 -0
  39. package/index-3hx1z96c.js +87 -0
  40. package/{index-q0y2jq9j.js → index-52w0fvh8.js} +21 -4
  41. package/{index-04bk599g.js → index-5g4rkrvt.js} +10 -17
  42. package/index-5pvxf7z0.js +53 -0
  43. package/index-5q14pwzd.js +69 -0
  44. package/{index-vxtad5bd.js → index-66yspb67.js} +5 -8
  45. package/index-7md2g9vw.js +6 -0
  46. package/index-7p4c0yer.js +1058 -0
  47. package/{index-d43r08tf.js → index-8b639zes.js} +77 -150
  48. package/{index-ktb5njgy.js → index-8kvy8qb4.js} +49 -99
  49. package/index-94s080qm.js +266 -0
  50. package/index-9dp031by.js +12 -0
  51. package/{index-0g7r8xz3.js → index-a37by9hn.js} +114 -232
  52. package/{index-k2j1hc4r.js → index-b95yhqjr.js} +12 -12
  53. package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
  54. package/{index-2xp0kfkt.js → index-br8pkrk1.js} +37 -25
  55. package/index-c14nsvnv.js +700 -0
  56. package/index-c6eggbee.js +123 -0
  57. package/index-d2242ksy.js +99 -0
  58. package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
  59. package/{index-a64esmtb.js → index-fkvb79qe.js} +523 -1022
  60. package/index-h54yj9wr.js +1119 -0
  61. package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
  62. package/{index-y6n8nmny.js → index-kn5d4jmg.js} +75 -203
  63. package/index-m3xsb1ms.js +4300 -0
  64. package/{index-gyd220p2.js → index-mb59b8x0.js} +554 -577
  65. package/{index-j9yhg404.js → index-mzjb6zp4.js} +4 -7
  66. package/index-p6pbz9n5.js +25 -0
  67. package/{index-sj5vxr8f.js → index-qe71g4ze.js} +983 -898
  68. package/index-rfcz04w9.js +187 -0
  69. package/{index-hwkygn9s.js → index-senscydg.js} +331 -36
  70. package/{index-ffvk10zz.js → index-vs8mefhy.js} +107 -241
  71. package/index-wa5jbxj1.js +760 -0
  72. package/index-y5ga5w9t.js +2729 -0
  73. package/{index-9077wzd2.js → index-y7hx1ygz.js} +43 -26
  74. package/{index-h7yw2z9n.js → index-zzvvc845.js} +8 -14
  75. package/index.js +23 -22
  76. package/{library.command-qzzbj6d8.js → library.command-keqjevpp.js} +4 -5
  77. package/{localRegistry.command-vyrgg4xw.js → localRegistry.command-pydeq5zf.js} +23 -43
  78. package/{module.command-rq5hq3ax.js → module.command-dkrnqx3v.js} +8 -12
  79. package/{package.command-d9hd6v9n.js → package.command-wmc0ys5y.js} +6 -7
  80. package/package.json +15 -7
  81. package/{page.command-126d56te.js → page.command-tf3erhrv.js} +4 -5
  82. package/{primitive.command-taxd1538.js → primitive.command-7hqpegj4.js} +9 -23
  83. package/prompter-76k56b37.js +8 -0
  84. package/{quality.command-6gsna0a3.js → quality.command-8122axq3.js} +205 -377
  85. package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
  86. package/{repair.command-tq2dgy72.js → repair.command-mcy12h0n.js} +11 -35
  87. package/{routeSourceValidator-apyqw7wk.js → routeSourceValidator-7ycnfz0e.js} +0 -6
  88. package/{scalar.command-3bcmrrkv.js → scalar.command-vvvbzttc.js} +7 -11
  89. package/skills/akan-code/SKILL.md +130 -0
  90. package/skills/akan-debug/SKILL.md +42 -0
  91. package/skills/akan-deps/SKILL.md +50 -0
  92. package/skills/akan-err/SKILL.md +39 -0
  93. package/skills/akan-module/SKILL.md +45 -0
  94. package/skills/akan-scaffold/SKILL.md +76 -0
  95. package/skills/akan-scalar/SKILL.md +52 -0
  96. package/skills/akan-service/SKILL.md +34 -0
  97. package/skills/akan-store/SKILL.md +67 -0
  98. package/skills/akan-ui/SKILL.md +63 -0
  99. package/skills/akan-validate/SKILL.md +44 -0
  100. package/{subspace.command-eddzqpx3.js → subspace.command-pzvqfy5h.js} +53 -62
  101. package/templates/__scalar/__model__/__model__.abstract.md.template +8 -0
  102. package/templates/app/page/_index.tsx +257 -258
  103. package/templates/app/page/_layout.tsx +5 -1
  104. package/templates/app/page/_overrides.tsx +12 -0
  105. package/templates/app/page/styles.css.template +316 -14
  106. package/templates/app/public/apple-touch-icon.png +0 -0
  107. package/templates/app/public/favicon.ico +0 -0
  108. package/templates/app/public/jelly/cloud.webp +0 -0
  109. package/templates/app/public/jelly/comet.webp +0 -0
  110. package/templates/app/public/jelly/moon.webp +0 -0
  111. package/templates/app/public/jelly/planet.webp +0 -0
  112. package/templates/app/public/jelly/rocket.webp +0 -0
  113. package/templates/app/public/jelly/star.webp +0 -0
  114. package/templates/app/public/jelly/sugar.webp +0 -0
  115. package/templates/app/public/logo.png +0 -0
  116. package/templates/app/ui/Recipe/index.ts +9 -0
  117. package/templates/app/ui/Recipe/jellyButton.ts +63 -0
  118. package/templates/appSample/lib/__scalar/workHistory/workHistory.abstract.ts +8 -39
  119. package/templates/appSample/lib/_noti/noti.abstract.ts +6 -29
  120. package/templates/appSample/lib/task/Task.Unit.tsx +1 -1
  121. package/templates/appSample/lib/task/Task.Util.tsx +10 -13
  122. package/templates/appSample/lib/task/Task.View.tsx +2 -2
  123. package/templates/appSample/lib/task/Task.Zone.tsx +5 -2
  124. package/templates/appSample/lib/task/task.abstract.ts +12 -32
  125. package/templates/appSample/lib/task/task.signal.spec.ts +1 -15
  126. package/templates/appSample/lib/task/task.signal.test.ts +15 -1
  127. package/templates/appSample/lib/task/task.signal.ts +10 -8
  128. package/templates/appSample/page/task/[taskId]/_index.tsx +6 -6
  129. package/templates/appSample/page/task/[taskId]/edit.tsx +5 -4
  130. package/templates/appSample/page/task/_index.tsx +4 -3
  131. package/templates/appSample/page/task/_layout.tsx +1 -1
  132. package/templates/appSample/page/task/new.tsx +5 -4
  133. package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +7 -4
  134. package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +6 -4
  135. package/templates/appSample/ui/GlobalLoading.tsx +2 -1
  136. package/templates/appSample/ui/QuantityControl.tsx +3 -3
  137. package/templates/client.ts +7 -30
  138. package/templates/crudPages/[__model__Id]/edit/page.tsx +2 -1
  139. package/templates/crudPages/[__model__Id]/page.tsx +2 -1
  140. package/templates/crudPages/new/page.tsx +2 -1
  141. package/templates/crudPages/page.tsx +2 -1
  142. package/templates/crudSinglePage/page.tsx +2 -1
  143. package/templates/lib/__lib/lib.dictionary.ts +0 -2
  144. package/templates/lib/__lib/lib.document.ts +0 -2
  145. package/templates/lib/sig.ts +8 -30
  146. package/templates/localDev/docker-compose.yaml.template +3 -14
  147. package/templates/module/__model__.signal.ts +12 -4
  148. package/templates/pkgRoot/tsconfig.json.template +2 -7
  149. package/templates/server.ts +1 -3
  150. package/templates/service/__model__.abstract.md.template +8 -0
  151. package/templates/workspaceRoot/.gitignore.template +0 -1
  152. package/templates/workspaceRoot/AGENTS.md.template +6 -0
  153. package/templates/workspaceRoot/package.json.template +1 -3
  154. package/tunnel.command-82zz5xnq.js +129 -0
  155. package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
  156. package/typecheck.proc.js +1 -1
  157. package/workflow.command-y8x3kgjv.js +79 -0
  158. package/{workspace.command-06wvstgr.js → workspace.command-jvsb7brc.js} +79 -109
  159. package/abstractCompactor-gmkc0z8j.js +0 -102
  160. package/application.command-18y0s485.js +0 -204
  161. package/applicationReleasePackager-4yasxwv9.js +0 -244
  162. package/capacitorApp-36rbr858.js +0 -12
  163. package/cloud.command-av97ndh6.js +0 -94
  164. package/cloud.script-cm11xjdz.js +0 -20
  165. package/context.command-5v37ef3n.js +0 -81
  166. package/devTuiView-0hc2emhe.js +0 -9
  167. package/getDirname-dr3jz1xg.js +0 -7
  168. package/guideline.command-4pz9g1rt.js +0 -360
  169. package/guidelines/agentRule/agentRule.generate.json +0 -31
  170. package/guidelines/componentRule/componentRule.generate.json +0 -31
  171. package/guidelines/conventions/conventions.generate.json +0 -25
  172. package/guidelines/cssRule/cssRule.generate.json +0 -31
  173. package/guidelines/docPageRule/docPageRule.generate.json +0 -31
  174. package/guidelines/docPageRule/docPageRule.instruction.md +0 -25
  175. package/guidelines/docSyncRule/docSyncRule.generate.json +0 -31
  176. package/guidelines/docSyncRule/docSyncRule.instruction.md +0 -25
  177. package/guidelines/enumConstant/enumConstant.generate.json +0 -31
  178. package/guidelines/enumConstant/enumConstant.instruction.md +0 -28
  179. package/guidelines/fieldRule/fieldRule.generate.json +0 -31
  180. package/guidelines/framework/framework.generate.json +0 -32
  181. package/guidelines/mcpRule/mcpRule.generate.json +0 -35
  182. package/guidelines/modelConstant/modelConstant.generate.json +0 -32
  183. package/guidelines/modelDictionary/modelDictionary.generate.json +0 -32
  184. package/guidelines/modelDocument/modelDocument.generate.json +0 -31
  185. package/guidelines/modelService/modelService.generate.json +0 -31
  186. package/guidelines/modelSignal/modelSignal.generate.json +0 -31
  187. package/guidelines/modelStore/modelStore.generate.json +0 -31
  188. package/guidelines/modelTemplate/modelTemplate.generate.json +0 -31
  189. package/guidelines/modelUnit/modelUnit.generate.json +0 -31
  190. package/guidelines/modelUtil/modelUtil.generate.json +0 -31
  191. package/guidelines/modelView/modelView.generate.json +0 -31
  192. package/guidelines/modelZone/modelZone.generate.json +0 -31
  193. package/guidelines/moduleCodegen/moduleCodegen.generate.json +0 -31
  194. package/guidelines/moduleCodegen/moduleCodegen.instruction.md +0 -28
  195. package/guidelines/moduleOverview/moduleOverview.generate.json +0 -31
  196. package/guidelines/queryRule/queryRule.generate.json +0 -31
  197. package/guidelines/recipeRule/recipeRule.generate.json +0 -31
  198. package/guidelines/runtimeRule/runtimeRule.generate.json +0 -25
  199. package/guidelines/scalarConstant/scalarConstant.generate.json +0 -32
  200. package/guidelines/scalarDictionary/scalarDictionary.generate.json +0 -32
  201. package/guidelines/scalarModule/scalarModule.generate.json +0 -31
  202. package/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -31
  203. package/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +0 -25
  204. package/guidelines/ssrRule/ssrRule.generate.json +0 -31
  205. package/guidelines/transportRule/transportRule.generate.json +0 -31
  206. package/guidelines/utilUiUsage/utilUiUsage.generate.json +0 -31
  207. package/guidelines/utilUiUsage/utilUiUsage.instruction.md +0 -25
  208. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +0 -24
  209. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +0 -33
  210. package/index-47pj3aee.js +0 -76
  211. package/index-5ystnsd5.js +0 -841
  212. package/index-6wwzs1bc.js +0 -7
  213. package/index-a17x49vg.js +0 -229
  214. package/index-m0xccmmm.js +0 -228
  215. package/index-meh558jy.js +0 -65
  216. package/index-rtxxan88.js +0 -471
  217. package/index-te54x9zm.js +0 -338
  218. package/index-w8kmx1b6.js +0 -2176
  219. package/index-wt7qrtd4.js +0 -1516
  220. package/templates/__scalar/__model__/__model__.abstract.md +0 -28
  221. package/templates/module/__model__.abstract.md +0 -28
  222. package/templates/service/__model__.abstract.md +0 -28
  223. package/templates/workspaceRoot/patches/react-dom@19.2.7.patch.template +0 -62
  224. package/workflow.command-gtdnzvbz.js +0 -108
@@ -3,295 +3,294 @@ import type { AppInfo, LibInfo } from "akanjs";
3
3
  interface Dict {
4
4
  appName: string;
5
5
  }
6
- export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
6
+ interface Options {
7
+ libs?: string[];
8
+ sample?: boolean;
9
+ }
10
+ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict, options: Options = {}) {
11
+ const sampleButton = options.sample
12
+ ? `
13
+ <Link className={jellyButtonRecipe({ variant: "default", size: "lg" })} href="/task">
14
+ {l.trans({ en: "Open the Sample", ko: "샘플 열어 보기" })}
15
+ </Link>`
16
+ : `
17
+ <Link
18
+ className={jellyButtonRecipe({ variant: "default", size: "lg" })}
19
+ href="https://akanjs.com/docs/intro/practice"
20
+ target="_blank"
21
+ >
22
+ {l.trans({ en: "Learn By Building", ko: "만들면서 배우기" })}
23
+ </Link>`;
24
+ const sampleStep = options.sample
25
+ ? `
26
+ {
27
+ title: l.trans({ en: "Read the sample module", ko: "샘플 모듈을 읽어 보세요" }),
28
+ body: l.trans({
29
+ en: "The task module walks one feature end to end — the model, its guarded API, the store and the pages.",
30
+ ko: "task 모듈이 모델부터 가드가 걸린 API, 스토어, 페이지까지 기능 하나를 처음부터 끝까지 보여 줍니다.",
31
+ }),
32
+ code: "lib/task",
33
+ href: "/task",
34
+ },`
35
+ : "";
7
36
  return {
8
37
  filename: "_index.tsx",
9
38
  content: `
39
+ import { jellyButtonRecipe } from "@apps/${dict.appName}/ui";
10
40
  import { getEnv } from "akanjs/base";
11
- import { page, usePage } from "akanjs/client";
12
- import { Link, System } from "akanjs/ui";
13
- import {
14
- FaBookOpen,
15
- FaBoxOpen,
16
- FaCheckCircle,
17
- FaCodeBranch,
18
- FaExternalLinkAlt,
19
- FaLayerGroup,
20
- FaRocket,
21
- FaShieldAlt,
22
- FaTerminal,
23
- } from "react-icons/fa";
41
+ import { cn, page, usePage } from "akanjs/client";
42
+ import { Image, Link, System } from "akanjs/ui";
43
+
44
+ const friendFloat = {
45
+ planet: "[--float-delay:-0.4s] [--float-duration:6.2s]",
46
+ rocket: "[--float-delay:-2.2s] [--float-duration:5.2s] [--float-tilt:7deg]",
47
+ moon: "[--float-delay:-3.6s] [--float-duration:7s] [--float-tilt:-5deg]",
48
+ cloud: "[--float-delay:-1.4s] [--float-duration:8s] [--float-rise:0.6rem]",
49
+ comet: "[--float-delay:-4.8s] [--float-duration:4.6s] [--float-tilt:9deg]",
50
+ } as const;
51
+
52
+ const numeralTiles = [
53
+ "tint-planet text-white",
54
+ "tint-rocket text-black/70",
55
+ "tint-moon text-black/70",
56
+ "tint-comet text-white",
57
+ ] as const;
24
58
 
25
59
  export default page().render(() => {
26
60
  const appName = getEnv().appName;
27
61
  const { l } = usePage();
62
+ const friends = [
63
+ { name: "planet", role: l.trans({ en: "Web", ko: "웹" }) },
64
+ { name: "rocket", role: l.trans({ en: "App", ko: "앱" }) },
65
+ { name: "moon", role: l.trans({ en: "Server · DB", ko: "서버 · DB" }) },
66
+ { name: "cloud", role: l.trans({ en: "Infra", ko: "인프라" }) },
67
+ { name: "comet", role: l.trans({ en: "Agent", ko: "에이전트" }) },
68
+ ] as const;
69
+ const chapters = [
70
+ {
71
+ numeral: "1",
72
+ title: l.trans({ en: "The line you write.", ko: "당신이 쓰는 한 줄." }),
73
+ body: l.trans({
74
+ en: "A field is one declaration — a name and a type. The database, API, screens and agent tools all come from it.",
75
+ ko: "필드는 이름과 타입, 선언 한 줄입니다. DB, API, 화면, 에이전트 도구가 모두 이 한 줄에서 나옵니다.",
76
+ }),
77
+ },
78
+ {
79
+ numeral: "×8",
80
+ title: l.trans({ en: "Through every layer.", ko: "모든 레이어를 관통하고," }),
81
+ body: l.trans({
82
+ en: "Schema, query, service, API, fetch, client type, state and UI change together. Nothing to chase, nothing to miss.",
83
+ ko: "스키마, 쿼리, 서비스, API, fetch, 클라이언트 타입, 상태, UI가 함께 바뀝니다. 따라 고칠 곳도 빠뜨릴 곳도 없습니다.",
84
+ }),
85
+ },
86
+ {
87
+ numeral: "×6",
88
+ title: l.trans({ en: "Onto every platform.", ko: "모든 플랫폼에 닿고," }),
89
+ body: l.trans({
90
+ en: "The same code ships as SEO-ready web, iOS and Android apps, and macOS, Windows and Linux desktop apps.",
91
+ ko: "같은 코드가 SEO 웹, iOS·Android 앱, macOS·Windows·Linux 데스크톱 앱으로 배포됩니다.",
92
+ }),
93
+ },
94
+ {
95
+ numeral: "×2",
96
+ title: l.trans({ en: "For people and agents alike.", ko: "사람과 에이전트 모두에게." }),
97
+ body: l.trans({
98
+ en: "Guarded endpoints become MCP tools and on-screen controls become in-page agent tools, behind the same guards people pass.",
99
+ ko: "가드를 거친 엔드포인트는 MCP 도구가, 화면의 컨트롤은 인페이지 에이전트 도구가 됩니다. 사람과 같은 가드를 거쳐서요.",
100
+ }),
101
+ },
102
+ ];
103
+ const steps = [
104
+ {
105
+ title: l.trans({ en: "Make this page yours", ko: "이 페이지를 바꿔 보세요" }),
106
+ body: l.trans({
107
+ en: "This welcome screen is an ordinary page. Replace it with the first screen of your product.",
108
+ ko: "이 환영 화면은 평범한 페이지입니다. 제품의 첫 화면으로 바꿔 보세요.",
109
+ }),
110
+ code: "page/_index.tsx",
111
+ },
112
+ {
113
+ title: l.trans({ en: "Restyle the theme", ko: "테마를 바꿔 보세요" }),
114
+ body: l.trans({
115
+ en: "Swap the palette tokens, and every surface and button follows.",
116
+ ko: "팔레트 토큰을 바꾸면 모든 표면과 버튼이 따라옵니다.",
117
+ }),
118
+ code: "page/styles.css",
119
+ },
120
+ {
121
+ title: l.trans({ en: "Add a feature", ko: "기능을 추가해 보세요" }),
122
+ body: l.trans({
123
+ en: "One command scaffolds a domain module — model, service, API, store and UI.",
124
+ ko: "명령 하나로 도메인 모듈(모델, 서비스, API, 스토어, UI)을 만듭니다.",
125
+ }),
126
+ code: "akan create-module <name>",
127
+ },${sampleStep}
128
+ {
129
+ title: l.trans({ en: "Connect an agent", ko: "에이전트를 연결해 보세요" }),
130
+ body: l.trans({
131
+ en: "Every guarded endpoint is already published as an MCP tool.",
132
+ ko: "가드가 걸린 엔드포인트는 이미 MCP 도구로 공개되어 있습니다.",
133
+ }),
134
+ code: "POST /mcp",
135
+ href: "https://akanjs.com/docs/arch/agentic",
136
+ },
137
+ ];
28
138
  return (
29
- <main className="relative min-h-screen overflow-hidden bg-background text-foreground">
30
- <div className="absolute -top-48 -left-48 h-96 w-96 rounded-full bg-primary/25 blur-3xl" />
31
- <div className="absolute -right-40 -bottom-56 h-112 w-md rounded-full bg-accent/20 blur-3xl" />
32
- <div className="absolute inset-x-0 top-0 h-px bg-linear-to-r from-transparent via-primary/60 to-transparent" />
33
-
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
- <nav className="flex items-center justify-between">
139
+ <main className="relative min-h-screen overflow-x-clip break-keep text-foreground">
140
+ <div className="mx-auto flex min-h-screen w-full max-w-6xl flex-col px-6 py-6 lg:px-8">
141
+ <nav className="flex items-center justify-between gap-4">
36
142
  <div className="flex items-center gap-3">
37
- <div className="flex h-11 w-11 items-center justify-center overflow-hidden rounded-2xl bg-background shadow-lg shadow-primary/20">
38
- <img
39
- src="/logo.png"
40
- alt={l.trans({ en: "Akan.js logo", ko: "Akan.js 로고" })}
41
- className="h-full w-full object-cover"
42
- />
43
- </div>
44
- <div>
45
- <p className="font-semibold text-primary text-sm tracking-[0.25em]">Akan.js</p>
46
- <p className="text-foreground/60 text-xs">
47
- {l.trans({ en: "Full-stack TypeScript framework", ko: "풀스택 타입스크립트 프레임워크" })}
143
+ <Image
144
+ alt={l.trans({ en: "Logo", ko: "로고" })}
145
+ className="jelly-breathe size-10"
146
+ height={80}
147
+ priority
148
+ src="/logo.png"
149
+ width={80}
150
+ />
151
+ <div className="leading-tight">
152
+ <p className="font-black text-lg tracking-tight">{appName}</p>
153
+ <p className="text-foreground/50 text-xs">
154
+ {l.trans({ en: "Built with Akan.js", ko: "Akan.js로 만든 앱" })}
48
155
  </p>
49
156
  </div>
50
157
  </div>
51
158
  <div className="flex items-center gap-2">
52
159
  <System.ThemeToggle themes={["light", "dark"]} />
53
160
  <System.SelectLanguage languages={["en", "ko"]} />
54
- <Link href="https://akanjs.com" target="_blank">
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
- {l.trans({ en: "Official Site", ko: "공식 사이트" })}
57
- <FaExternalLinkAlt />
58
- </button>
161
+ <Link
162
+ className={jellyButtonRecipe({ variant: "default", size: "sm" }, "max-sm:hidden")}
163
+ href="https://akanjs.com"
164
+ target="_blank"
165
+ >
166
+ {l.trans({ en: "Official Site", ko: "공식 사이트" })} ↗
59
167
  </Link>
60
168
  </div>
61
169
  </nav>
62
170
 
63
- <div className="grid flex-1 items-center gap-10 py-16 lg:grid-cols-[1.04fr_0.96fr] lg:py-10">
64
- <div>
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
- <FaCheckCircle />
67
- {l.trans({ en: "Your app is running", ko: "앱이 실행 중입니다" })}
68
- </div>
69
- <h1 className="max-w-4xl font-black text-5xl text-foreground tracking-tight sm:text-6xl lg:text-7xl">
70
- {l.trans({
71
- en: "Akan turns business intent into the whole product.",
72
- ko: "Akan은 비즈니스 의도를 제품 전체로 바꿉니다.",
73
- })}
74
- </h1>
75
- <p className="mt-6 max-w-2xl text-foreground/70 text-lg leading-8">
76
- {l.trans({
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
- ko: "Agents Write. Keep It Minimal. Always Readable. Nice To Review. 더 적은 코드, 더 적은 반복 결정, 더 선명한 출시 경로로 만드세요.",
79
- })}
80
- </p>
81
-
82
- <div className="mt-8 flex flex-wrap gap-3">
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
- Agent-ready
85
- </span>
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
- Minimal code
88
- </span>
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
- Readable by default
91
- </span>
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
- Review-friendly
94
- </span>
95
- </div>
96
-
97
- <div className="mt-10 flex flex-col gap-3 sm:flex-row">
98
- <Link href="https://akanjs.com/docs/intro/quickstart" target="_blank">
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
- {l.trans({ en: "Read Quick Start", ko: "빠른 시작 읽기" })}
101
- <FaBookOpen />
102
- </button>
103
- </Link>
104
- <Link href="https://akanjs.com/docs/intro/practice" target="_blank">
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
- {l.trans({ en: "Learn By Building", ko: "만들면서 배우기" })}
107
- <FaCodeBranch />
108
- </button>
109
- </Link>
110
- </div>
111
- </div>
112
-
113
- <div className="relative">
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-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
- <div>
118
- <p className="text-foreground/40 text-xs uppercase tracking-[0.24em]">
119
- {l.trans({ en: "Akan Acrostic", ko: "Akan 사행시" })}
120
- </p>
121
- <p className="font-semibold text-foreground text-lg">
122
- {l.trans({ en: "A framework for focused builders", ko: "집중하는 빌더를 위한 프레임워크" })}
123
- </p>
124
- </div>
125
- <div className="rounded-xl bg-primary/10 px-3 py-2 font-medium text-primary text-sm">{appName}</div>
126
- </div>
127
-
128
- <div className="grid gap-3">
129
- <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
130
- <div className="flex gap-4">
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
- A
133
- </div>
134
- <div>
135
- <p className="font-bold text-foreground">Agents Write</p>
136
- <p className="mt-1 text-foreground/60 text-sm leading-6">
137
- {l.trans({
138
- en: "Business definitions become the source code, so teams and agents can focus on what to build.",
139
- ko: "비즈니스 정의가 소스 코드가 되므로, 팀과 에이전트는 무엇을 만들지에 집중할 수 있습니다.",
140
- })}
141
- </p>
142
- </div>
143
- </div>
144
- </div>
145
- <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
146
- <div className="flex gap-4">
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
- K
149
- </div>
150
- <div>
151
- <p className="font-bold text-foreground">Keep It Minimal</p>
152
- <p className="mt-1 text-foreground/60 text-sm leading-6">
153
- {l.trans({
154
- en: "One definition flows into web, app, server, database, and infrastructure without repeated logic.",
155
- ko: "하나의 정의가 반복 로직 없이 웹, 앱, 서버, 데이터베이스, 인프라로 이어집니다.",
156
- })}
157
- </p>
158
- </div>
159
- </div>
160
- </div>
161
- <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
162
- <div className="flex gap-4">
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
- A
165
- </div>
166
- <div>
167
- <p className="font-bold text-foreground">Always Readable</p>
168
- <p className="mt-1 text-foreground/60 text-sm leading-6">
169
- {l.trans({
170
- en: "Strict conventions keep the app easy to understand long after the first version ships.",
171
- ko: "엄격한 컨벤션은 첫 버전 출시 후에도 앱을 쉽게 이해할 수 있게 지켜줍니다.",
172
- })}
173
- </p>
174
- </div>
175
- </div>
176
- </div>
177
- <div className="rounded-2xl border border-foreground/10 bg-background/80 p-4">
178
- <div className="flex gap-4">
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
- N
181
- </div>
182
- <div>
183
- <p className="font-bold text-foreground">Nice To Review</p>
184
- <p className="mt-1 text-foreground/60 text-sm leading-6">
185
- {l.trans({
186
- en: "Focused changes make business intent clear, so reviews stay fast and releases stay calm.",
187
- ko: "집중된 변경은 비즈니스 의도를 선명하게 만들어 리뷰를 빠르게 하고 배포를 안정적으로 유지합니다.",
188
- })}
189
- </p>
190
- </div>
191
- </div>
192
- </div>
193
- </div>
194
-
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>
198
- <code className="text-primary">bun run akan start {appName}</code>
199
- </pre>
200
- <pre className="px-6">
201
- <span className="select-none text-foreground/40">✓ </span>
202
- <code className="text-accent">
203
- {l.trans({ en: "web, app, server, db, and infra ready", ko: "웹, 앱, 서버, DB, 인프라 준비 완료" })}
204
- </code>
205
- </pre>
206
- <pre className="px-6">
207
- <span className="select-none text-foreground/40">→ </span>
208
- <code className="text-foreground/70">
209
- {l.trans({
210
- en: "edit page/_index.tsx around your business",
211
- ko: "비즈니스에 맞게 page/_index.tsx를 수정하세요",
212
- })}
213
- </code>
214
- </pre>
215
- </div>
171
+ <section className="grid min-h-[calc(100svh-5rem)] items-center gap-6 py-12 lg:grid-cols-[0.8fr_1.2fr] lg:gap-10">
172
+ <div className="intro-rise group relative mx-auto aspect-square w-48 sm:w-64 lg:w-full lg:max-w-md">
173
+ <div className="absolute inset-x-[16%] bottom-[3%] h-[7%] rounded-full bg-black/25 blur-xl dark:bg-black/60" />
174
+ <div className="jelly-breathe group-hover:jelly-wobble size-full">
175
+ <Image
176
+ alt=""
177
+ className="pointer-events-none size-full select-none object-contain"
178
+ draggable={false}
179
+ height={640}
180
+ priority
181
+ src="/jelly/star.webp"
182
+ width={640}
183
+ />
216
184
  </div>
217
185
  </div>
218
- </div>
219
186
 
220
- <div className="grid gap-4 pb-8 md:grid-cols-2 xl:grid-cols-4">
221
- <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
222
- <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
223
- <FaTerminal />
224
- </div>
225
- <h2 className="font-bold text-foreground text-lg">
226
- {l.trans({ en: "Agentic By Design", ko: "에이전틱 설계" })}
227
- </h2>
228
- <p className="mt-2 text-foreground/60 text-sm leading-6">
229
- {l.trans({
230
- en: "Describe the business once and let Akan shape the application surfaces around it.",
231
- ko: "비즈니스를 한 번 설명하면 Akan이 그 주변의 애플리케이션 표면을 구성합니다.",
232
- })}
233
- </p>
234
- </div>
235
- <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
236
- <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
237
- <FaLayerGroup />
238
- </div>
239
- <h2 className="font-bold text-foreground text-lg">
240
- {l.trans({ en: "One Definition", ko: "하나의 정의" })}
241
- </h2>
242
- <p className="mt-2 text-foreground/60 text-sm leading-6">
243
- {l.trans({
244
- en: "Pages, services, database models, and deployment artifacts stay connected in one workspace.",
245
- ko: "페이지, 서비스, 데이터베이스 모델, 배포 산출물이 하나의 워크스페이스에서 연결됩니다.",
246
- })}
187
+ <div className="flex flex-col items-center text-center lg:items-start lg:text-left">
188
+ <p className="intro-rise jelly-glass inline-flex items-center gap-2 rounded-full px-4 py-1.5 font-bold text-foreground/75 text-sm [--intro-delay:40ms]">
189
+ <span className="size-2 rounded-full bg-success ring-4 ring-success/20" />
190
+ {l.trans({ en: "Your app is running", ko: "앱이 실행 중입니다" })}
247
191
  </p>
248
- </div>
249
- <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
250
- <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
251
- <FaRocket />
252
- </div>
253
- <h2 className="font-bold text-foreground text-lg">
254
- {l.trans({ en: "Less To Review", ko: "리뷰할 것이 적습니다" })}
255
- </h2>
256
- <p className="mt-2 text-foreground/60 text-sm leading-6">
192
+ <h1 className="intro-rise wrap-anywhere mt-6 max-w-full font-black text-[clamp(3.5rem,12vw,8.5rem)] leading-[0.85] tracking-[-0.06em] [--intro-delay:80ms]">
193
+ {appName}
194
+ </h1>
195
+ <p className="intro-rise mt-6 max-w-xl font-bold text-foreground/60 text-lg leading-8 [--intro-delay:160ms]">
257
196
  {l.trans({
258
- en: "Smaller code surfaces make intent easier to inspect, approve, and ship.",
259
- ko: "더 작은 코드 표면은 의도를 확인하고 승인하고 배포하기 쉽게 만듭니다.",
197
+ en: "Built on Akan.js — the TypeScript framework, agents included.",
198
+ ko: "에이전트까지 들어 있는 TypeScript 프레임워크, Akan.js로 만들었습니다.",
260
199
  })}
261
200
  </p>
262
- </div>
263
- <div className="rounded-3xl border border-foreground/10 bg-foreground/4 p-6 backdrop-blur">
264
- <div className="mb-5 flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary text-xl">
265
- <FaShieldAlt />
201
+ <ul className="intro-rise mt-8 flex items-end gap-2 [--intro-delay:240ms] sm:gap-4">
202
+ {friends.map((friend) => (
203
+ <li className="group flex flex-col items-center gap-2" key={friend.name}>
204
+ <span className={cn("jelly-float block", friendFloat[friend.name])}>
205
+ <span className="group-hover:jelly-wobble block">
206
+ <Image
207
+ alt=""
208
+ className="pointer-events-none size-14 select-none sm:size-18"
209
+ draggable={false}
210
+ height={200}
211
+ src={\`/jelly/\${friend.name}.webp\`}
212
+ width={200}
213
+ />
214
+ </span>
215
+ </span>
216
+ <span className="whitespace-nowrap rounded-full bg-foreground/6 px-2.5 py-0.5 font-bold text-[11px] text-foreground/60">
217
+ {friend.role}
218
+ </span>
219
+ </li>
220
+ ))}
221
+ </ul>
222
+ <div className="intro-rise mt-10 flex flex-wrap justify-center gap-3 [--intro-delay:320ms] lg:justify-start">
223
+ <Link
224
+ className={jellyButtonRecipe({ size: "lg" })}
225
+ href="https://akanjs.com/docs/intro/quickstart"
226
+ target="_blank"
227
+ >
228
+ {l.trans({ en: "Read Quick Start", ko: "빠른 시작 읽기" })}
229
+ </Link>${sampleButton}
266
230
  </div>
267
- <h2 className="font-bold text-foreground text-lg">
268
- {l.trans({ en: "Type-Safe Growth", ko: "타입 안전한 성장" })}
269
- </h2>
270
- <p className="mt-2 text-foreground/60 text-sm leading-6">
271
- {l.trans({
272
- en: "Conventions and contracts keep the stack readable as the product expands.",
273
- ko: "컨벤션과 계약은 제품이 확장되어도 스택을 읽기 쉽게 유지합니다.",
274
- })}
275
- </p>
276
231
  </div>
277
- </div>
232
+ </section>
278
233
 
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">
280
- <div className="flex items-center gap-3">
281
- <FaTerminal className="text-primary" />
282
- <span>
283
- {l.trans({
284
- en: "Next: define the business once, then let Akan carry it across every surface.",
285
- ko: "다음 단계: 비즈니스를 한 번 정의하고, Akan이 모든 표면으로 이어가게 하세요.",
286
- })}
287
- </span>
288
- </div>
289
- <div className="flex items-center gap-2 text-foreground/40">
290
- <FaBoxOpen />
291
- <span>{l.trans({ en: "Akan.js template", ko: "Akan.js 템플릿" })}</span>
234
+ <section className="py-12">
235
+ <p className="font-bold text-primary text-sm">{l.trans({ en: "How it works", ko: "작동 방식" })}</p>
236
+ <h2 className="mt-2 font-black text-3xl sm:text-4xl">
237
+ {l.trans({ en: "One line reaches the whole product.", ko: "한 줄이 제품 전체에 닿습니다." })}
238
+ </h2>
239
+ <div className="mt-8 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
240
+ {chapters.map((chapter, idx) => (
241
+ <article className="jelly-glass rounded-box p-6" key={chapter.numeral}>
242
+ <span
243
+ className={cn(
244
+ "jelly flex size-12 items-center justify-center rounded-2xl font-black text-xl",
245
+ numeralTiles[idx],
246
+ )}
247
+ >
248
+ {chapter.numeral}
249
+ </span>
250
+ <h3 className="mt-5 font-bold text-lg">{chapter.title}</h3>
251
+ <p className="mt-2 text-foreground/60 text-sm leading-6">{chapter.body}</p>
252
+ </article>
253
+ ))}
292
254
  </div>
293
- </div>
294
- </section>
255
+ </section>
256
+
257
+ <section className="py-12">
258
+ <p className="font-bold text-primary text-sm">{l.trans({ en: "Next steps", ko: "다음 단계" })}</p>
259
+ <h2 className="mt-2 font-black text-3xl sm:text-4xl">
260
+ {l.trans({ en: "Start here.", ko: "여기서 시작하세요." })}
261
+ </h2>
262
+ <ol className="jelly-glass mt-8 divide-y divide-foreground/8 rounded-box">
263
+ {steps.map((step, idx) => (
264
+ <li className="flex items-start gap-4 p-5 sm:p-6" key={step.code}>
265
+ <span className="jelly tint-primary flex size-9 shrink-0 items-center justify-center rounded-full font-black text-primary-foreground text-sm">
266
+ {idx + 1}
267
+ </span>
268
+ <div className="min-w-0 flex-1">
269
+ <h3 className="font-bold">{step.title}</h3>
270
+ <p className="mt-1 text-foreground/60 text-sm leading-6">{step.body}</p>
271
+ <code className="mt-2 inline-block rounded-full bg-foreground/6 px-3 py-1 font-mono text-foreground/75 text-xs">
272
+ {step.code}
273
+ </code>
274
+ </div>
275
+ {step.href ? (
276
+ <Link
277
+ aria-label={step.title}
278
+ className={jellyButtonRecipe({ variant: "ghost", size: "icon" }, "shrink-0 self-center")}
279
+ href={step.href}
280
+ target={step.href.startsWith("http") ? "_blank" : undefined}
281
+ >
282
+ →
283
+ </Link>
284
+ ) : null}
285
+ </li>
286
+ ))}
287
+ </ol>
288
+ </section>
289
+
290
+ <footer className="py-10 text-center text-foreground/45 text-sm">
291
+ {l.trans({ en: "Made with Akan.js · Powered by Bun", ko: "Akan.js로 만들고 Bun으로 구동합니다" })}
292
+ </footer>
293
+ </div>
295
294
  </main>
296
295
  );
297
296
  });`,
@@ -30,10 +30,14 @@ export default rootLayout()
30
30
  ],
31
31
  },
32
32
  ])
33
+ .theme("light")
33
34
  .head(
34
35
  <>
35
36
  <title>${dict.appName}</title>
36
- <link rel="icon" href="/favicon.ico" />
37
+ <link rel="icon" href="/favicon.ico" sizes="32x32" />
38
+ <link rel="icon" type="image/png" sizes="512x512" href="/logo.png" />
39
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
40
+ <meta name="theme-color" content="#f1f1ee" />
37
41
  </>,
38
42
  )
39
43
  .render(({ children }) => {
@@ -0,0 +1,12 @@
1
+ import type { AppInfo, LibInfo } from "akanjs";
2
+
3
+ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
4
+ return {
5
+ filename: "_overrides.tsx",
6
+ content: `import { jellyButtonRecipe } from "@apps/${dict.appName}/ui";
7
+ import { override } from "akanjs/ui";
8
+
9
+ export default override({ recipes: { button: jellyButtonRecipe } });
10
+ `,
11
+ };
12
+ }