opencode-agent-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/README.md +796 -0
  2. package/bin/commands/init.mjs +221 -0
  3. package/bin/init.mjs +21 -0
  4. package/package.json +22 -0
  5. package/template/.opencode/agent-docs/backend/README.md +0 -0
  6. package/template/.opencode/agent-docs/backend/node/BACKEND_PATTERNS.md +82 -0
  7. package/template/.opencode/agent-docs/backend/node/BACKEND_QUICK_START.md +49 -0
  8. package/template/.opencode/agent-docs/frontend/next/README.md +0 -0
  9. package/template/.opencode/agent-docs/frontend/nuxt/API_PATTERNS.md +807 -0
  10. package/template/.opencode/agent-docs/frontend/nuxt/CHEATSHEET.md +676 -0
  11. package/template/.opencode/agent-docs/frontend/nuxt/COMPLETION_REPORT.md +613 -0
  12. package/template/.opencode/agent-docs/frontend/nuxt/EXAMPLES.md +956 -0
  13. package/template/.opencode/agent-docs/frontend/nuxt/INDEX.md +596 -0
  14. package/template/.opencode/agent-docs/frontend/nuxt/MCP_GUIDE.md +881 -0
  15. package/template/.opencode/agent-docs/frontend/nuxt/MENTOR_CURRICULUM_30_DAYS.md +256 -0
  16. package/template/.opencode/agent-docs/frontend/nuxt/MENTOR_CURRICULUM_CHECKLIST.md +156 -0
  17. package/template/.opencode/agent-docs/frontend/nuxt/MENTOR_WEEKLY_ASSIGNMENTS.md +191 -0
  18. package/template/.opencode/agent-docs/frontend/nuxt/QUICK_START.md +509 -0
  19. package/template/.opencode/agent-docs/frontend/nuxt/README.md +506 -0
  20. package/template/.opencode/agent-docs/frontend/nuxt/README_AGENTS.md +140 -0
  21. package/template/.opencode/agent-docs/frontend/nuxt/README_DOCS.md +65 -0
  22. package/template/.opencode/agent-docs/frontend/nuxt/SUMMARY.md +474 -0
  23. package/template/.opencode/agent-docs/frontend/nuxt/TEAM_OPERATING_GUIDE.md +54 -0
  24. package/template/.opencode/agent-docs/frontend/nuxt/TESTING_GUIDE.md +904 -0
  25. package/template/.opencode/agent-docs/frontend/nuxt/WORKFLOWS.md +758 -0
  26. package/template/.opencode/agent-docs/frontend/react/API_PATTERNS.md +187 -0
  27. package/template/.opencode/agent-docs/frontend/react/CHEATSHEET.md +87 -0
  28. package/template/.opencode/agent-docs/frontend/react/INDEX.md +45 -0
  29. package/template/.opencode/agent-docs/frontend/react/QUICK_START.md +43 -0
  30. package/template/.opencode/agent-docs/frontend/react/README.md +159 -0
  31. package/template/.opencode/agent-docs/frontend/vue/README.md +0 -0
  32. package/template/.opencode/agent-docs/mobile/android/README.md +45 -0
  33. package/template/.opencode/agent-docs/mobile/flutter/README.md +44 -0
  34. package/template/.opencode/agents/android-developer.md +418 -0
  35. package/template/.opencode/agents/code-igniter-3-fullstack.md +345 -0
  36. package/template/.opencode/agents/code-reviewer.md +517 -0
  37. package/template/.opencode/agents/database-specialist.md +455 -0
  38. package/template/.opencode/agents/devops-specialist.md +562 -0
  39. package/template/.opencode/agents/flutter-developer.md +556 -0
  40. package/template/.opencode/agents/it-leader.md +911 -0
  41. package/template/.opencode/agents/laravel-advanced.md +691 -0
  42. package/template/.opencode/agents/node-backend-developer.md +343 -0
  43. package/template/.opencode/agents/nuxt-frontend-developer-mentor.md +402 -0
  44. package/template/.opencode/agents/nuxt-frontend-developer.md +1573 -0
  45. package/template/.opencode/agents/react-frontend-developer.md +1017 -0
  46. package/template/.opencode/agents/seo-specialist.md +681 -0
  47. package/template/.opencode/agents/ui-ux-designer.md +783 -0
  48. package/template/.opencode/commands/android-build/command.md +25 -0
  49. package/template/.opencode/commands/android-test/command.md +23 -0
  50. package/template/.opencode/commands/build-fix.md +29 -0
  51. package/template/.opencode/commands/checkpoint.md +74 -0
  52. package/template/.opencode/commands/code-review.md +40 -0
  53. package/template/.opencode/commands/e2e.md +363 -0
  54. package/template/.opencode/commands/eval.md +120 -0
  55. package/template/.opencode/commands/evolve.md +193 -0
  56. package/template/.opencode/commands/flutter-build/command.md +25 -0
  57. package/template/.opencode/commands/flutter-test/command.md +24 -0
  58. package/template/.opencode/commands/go-build.md +183 -0
  59. package/template/.opencode/commands/go-review.md +148 -0
  60. package/template/.opencode/commands/go-test.md +268 -0
  61. package/template/.opencode/commands/gpc-release/command.md +30 -0
  62. package/template/.opencode/commands/instinct-export.md +91 -0
  63. package/template/.opencode/commands/instinct-import.md +142 -0
  64. package/template/.opencode/commands/instinct-status.md +86 -0
  65. package/template/.opencode/commands/learn.md +70 -0
  66. package/template/.opencode/commands/multi-backend.md +158 -0
  67. package/template/.opencode/commands/multi-execute.md +310 -0
  68. package/template/.opencode/commands/multi-frontend.md +158 -0
  69. package/template/.opencode/commands/multi-plan.md +261 -0
  70. package/template/.opencode/commands/multi-workflow.md +183 -0
  71. package/template/.opencode/commands/orchestrate.md +172 -0
  72. package/template/.opencode/commands/plan.md +113 -0
  73. package/template/.opencode/commands/pm2.md +271 -0
  74. package/template/.opencode/commands/python-review.md +297 -0
  75. package/template/.opencode/commands/refactor-clean.md +28 -0
  76. package/template/.opencode/commands/sessions.md +305 -0
  77. package/template/.opencode/commands/setup-pm.md +80 -0
  78. package/template/.opencode/commands/skill-create.md +174 -0
  79. package/template/.opencode/commands/tdd.md +326 -0
  80. package/template/.opencode/commands/test-coverage.md +27 -0
  81. package/template/.opencode/commands/update-codemaps.md +17 -0
  82. package/template/.opencode/commands/update-docs.md +31 -0
  83. package/template/.opencode/commands/verify.md +59 -0
  84. package/template/.opencode/config.example.json +309 -0
  85. package/template/.opencode/config.json +341 -0
  86. package/template/.opencode/contexts/dev.md +20 -0
  87. package/template/.opencode/contexts/research.md +26 -0
  88. package/template/.opencode/contexts/review.md +22 -0
  89. package/template/.opencode/hooks/hooks.json +169 -0
  90. package/template/.opencode/instructions/INSTRUCTIONS.md +388 -0
  91. package/template/.opencode/package.json +5 -0
  92. package/template/.opencode/rules/README.md +82 -0
  93. package/template/.opencode/rules/android/gradle.md +62 -0
  94. package/template/.opencode/rules/android/testing.md +27 -0
  95. package/template/.opencode/rules/common/agents.md +49 -0
  96. package/template/.opencode/rules/common/coding-style.md +48 -0
  97. package/template/.opencode/rules/common/git-workflow.md +45 -0
  98. package/template/.opencode/rules/common/hooks.md +30 -0
  99. package/template/.opencode/rules/common/patterns.md +31 -0
  100. package/template/.opencode/rules/common/performance.md +55 -0
  101. package/template/.opencode/rules/common/security.md +29 -0
  102. package/template/.opencode/rules/common/testing.md +29 -0
  103. package/template/.opencode/rules/flutter/state-management.md +57 -0
  104. package/template/.opencode/rules/flutter/testing.md +42 -0
  105. package/template/.opencode/rules/golang/coding-style.md +26 -0
  106. package/template/.opencode/rules/golang/hooks.md +11 -0
  107. package/template/.opencode/rules/golang/patterns.md +39 -0
  108. package/template/.opencode/rules/golang/security.md +28 -0
  109. package/template/.opencode/rules/golang/testing.md +25 -0
  110. package/template/.opencode/rules/mobile/performance.md +36 -0
  111. package/template/.opencode/rules/python/coding-style.md +37 -0
  112. package/template/.opencode/rules/python/hooks.md +14 -0
  113. package/template/.opencode/rules/python/patterns.md +34 -0
  114. package/template/.opencode/rules/python/security.md +25 -0
  115. package/template/.opencode/rules/python/testing.md +33 -0
  116. package/template/.opencode/rules/typescript/coding-style.md +58 -0
  117. package/template/.opencode/rules/typescript/hooks.md +15 -0
  118. package/template/.opencode/rules/typescript/patterns.md +45 -0
  119. package/template/.opencode/rules/typescript/security.md +21 -0
  120. package/template/.opencode/rules/typescript/testing.md +11 -0
  121. package/template/.opencode/skills/api-documentation/SKILL.md +188 -0
  122. package/template/.opencode/skills/backend-patterns/SKILL.md +587 -0
  123. package/template/.opencode/skills/building-components/SKILL.md +37 -0
  124. package/template/.opencode/skills/building-components/references/accessibility.mdx +819 -0
  125. package/template/.opencode/skills/building-components/references/as-child.mdx +324 -0
  126. package/template/.opencode/skills/building-components/references/composition.mdx +239 -0
  127. package/template/.opencode/skills/building-components/references/data-attributes.mdx +413 -0
  128. package/template/.opencode/skills/building-components/references/definitions.mdx +258 -0
  129. package/template/.opencode/skills/building-components/references/design-tokens.mdx +57 -0
  130. package/template/.opencode/skills/building-components/references/docs.mdx +155 -0
  131. package/template/.opencode/skills/building-components/references/marketplaces.mdx +144 -0
  132. package/template/.opencode/skills/building-components/references/npm.mdx +166 -0
  133. package/template/.opencode/skills/building-components/references/polymorphism.mdx +583 -0
  134. package/template/.opencode/skills/building-components/references/principles.mdx +61 -0
  135. package/template/.opencode/skills/building-components/references/registry.mdx +169 -0
  136. package/template/.opencode/skills/building-components/references/state.mdx +99 -0
  137. package/template/.opencode/skills/building-components/references/styling.mdx +286 -0
  138. package/template/.opencode/skills/building-components/references/types.mdx +191 -0
  139. package/template/.opencode/skills/clickhouse-io/SKILL.md +429 -0
  140. package/template/.opencode/skills/coding-standards/SKILL.md +520 -0
  141. package/template/.opencode/skills/configure-ecc/SKILL.md +298 -0
  142. package/template/.opencode/skills/continuous-learning/SKILL.md +110 -0
  143. package/template/.opencode/skills/continuous-learning/config.json +18 -0
  144. package/template/.opencode/skills/continuous-learning/evaluate-session.sh +60 -0
  145. package/template/.opencode/skills/continuous-learning-v2/SKILL.md +284 -0
  146. package/template/.opencode/skills/continuous-learning-v2/agents/observer.md +137 -0
  147. package/template/.opencode/skills/continuous-learning-v2/agents/start-observer.sh +134 -0
  148. package/template/.opencode/skills/continuous-learning-v2/config.json +41 -0
  149. package/template/.opencode/skills/continuous-learning-v2/hooks/observe.sh +153 -0
  150. package/template/.opencode/skills/continuous-learning-v2/scripts/instinct-cli.py +489 -0
  151. package/template/.opencode/skills/continuous-learning-v2/scripts/test_parse_instinct.py +82 -0
  152. package/template/.opencode/skills/dart-add-unit-test/SKILL.md +122 -0
  153. package/template/.opencode/skills/dart-build-cli-app/SKILL.md +185 -0
  154. package/template/.opencode/skills/dart-collect-coverage/SKILL.md +141 -0
  155. package/template/.opencode/skills/dart-fix-runtime-errors/SKILL.md +166 -0
  156. package/template/.opencode/skills/dart-generate-test-mocks/SKILL.md +155 -0
  157. package/template/.opencode/skills/dart-migrate-to-checks-package/SKILL.md +126 -0
  158. package/template/.opencode/skills/dart-resolve-package-conflicts/SKILL.md +116 -0
  159. package/template/.opencode/skills/dart-run-static-analysis/SKILL.md +104 -0
  160. package/template/.opencode/skills/dart-use-pattern-matching/SKILL.md +146 -0
  161. package/template/.opencode/skills/django-patterns/SKILL.md +733 -0
  162. package/template/.opencode/skills/django-security/SKILL.md +592 -0
  163. package/template/.opencode/skills/django-tdd/SKILL.md +728 -0
  164. package/template/.opencode/skills/django-verification/SKILL.md +460 -0
  165. package/template/.opencode/skills/eval-harness/SKILL.md +227 -0
  166. package/template/.opencode/skills/firebase-basics/SKILL.md +103 -0
  167. package/template/.opencode/skills/firebase-basics/references/additional-skills.md +113 -0
  168. package/template/.opencode/skills/firebase-basics/references/cli-usage.md +31 -0
  169. package/template/.opencode/skills/firebase-basics/references/client-library-usage.md +45 -0
  170. package/template/.opencode/skills/firebase-basics/references/core-concepts.md +61 -0
  171. package/template/.opencode/skills/firebase-basics/references/iac-usage.md +40 -0
  172. package/template/.opencode/skills/firebase-basics/references/iam-security.md +74 -0
  173. package/template/.opencode/skills/firebase-basics/references/mcp-usage.md +63 -0
  174. package/template/.opencode/skills/flutter/SKILL.md +292 -0
  175. package/template/.opencode/skills/flutter-add-integration-test/SKILL.md +163 -0
  176. package/template/.opencode/skills/flutter-add-widget-preview/SKILL.md +145 -0
  177. package/template/.opencode/skills/flutter-add-widget-test/SKILL.md +154 -0
  178. package/template/.opencode/skills/flutter-apply-architecture-best-practices/SKILL.md +162 -0
  179. package/template/.opencode/skills/flutter-build-responsive-layout/SKILL.md +139 -0
  180. package/template/.opencode/skills/flutter-fix-layout-issues/SKILL.md +130 -0
  181. package/template/.opencode/skills/flutter-implement-json-serialization/SKILL.md +153 -0
  182. package/template/.opencode/skills/flutter-setup-declarative-routing/SKILL.md +255 -0
  183. package/template/.opencode/skills/flutter-setup-localization/SKILL.md +210 -0
  184. package/template/.opencode/skills/flutter-use-http-package/SKILL.md +174 -0
  185. package/template/.opencode/skills/frontend-design/SKILL.md +89 -0
  186. package/template/.opencode/skills/frontend-patterns/SKILL.md +631 -0
  187. package/template/.opencode/skills/golang-patterns/SKILL.md +673 -0
  188. package/template/.opencode/skills/golang-testing/SKILL.md +719 -0
  189. package/template/.opencode/skills/impeccable/SKILL.md +165 -0
  190. package/template/.opencode/skills/impeccable/agents/impeccable-asset-producer.md +101 -0
  191. package/template/.opencode/skills/impeccable/reference/adapt.md +190 -0
  192. package/template/.opencode/skills/impeccable/reference/animate.md +175 -0
  193. package/template/.opencode/skills/impeccable/reference/audit.md +133 -0
  194. package/template/.opencode/skills/impeccable/reference/bolder.md +113 -0
  195. package/template/.opencode/skills/impeccable/reference/brand.md +118 -0
  196. package/template/.opencode/skills/impeccable/reference/clarify.md +174 -0
  197. package/template/.opencode/skills/impeccable/reference/codex.md +105 -0
  198. package/template/.opencode/skills/impeccable/reference/cognitive-load.md +106 -0
  199. package/template/.opencode/skills/impeccable/reference/color-and-contrast.md +105 -0
  200. package/template/.opencode/skills/impeccable/reference/colorize.md +154 -0
  201. package/template/.opencode/skills/impeccable/reference/craft.md +123 -0
  202. package/template/.opencode/skills/impeccable/reference/critique.md +273 -0
  203. package/template/.opencode/skills/impeccable/reference/delight.md +302 -0
  204. package/template/.opencode/skills/impeccable/reference/distill.md +111 -0
  205. package/template/.opencode/skills/impeccable/reference/document.md +427 -0
  206. package/template/.opencode/skills/impeccable/reference/extract.md +69 -0
  207. package/template/.opencode/skills/impeccable/reference/harden.md +347 -0
  208. package/template/.opencode/skills/impeccable/reference/heuristics-scoring.md +234 -0
  209. package/template/.opencode/skills/impeccable/reference/interaction-design.md +195 -0
  210. package/template/.opencode/skills/impeccable/reference/layout.md +141 -0
  211. package/template/.opencode/skills/impeccable/reference/live.md +622 -0
  212. package/template/.opencode/skills/impeccable/reference/motion-design.md +109 -0
  213. package/template/.opencode/skills/impeccable/reference/onboard.md +234 -0
  214. package/template/.opencode/skills/impeccable/reference/optimize.md +258 -0
  215. package/template/.opencode/skills/impeccable/reference/overdrive.md +130 -0
  216. package/template/.opencode/skills/impeccable/reference/personas.md +179 -0
  217. package/template/.opencode/skills/impeccable/reference/polish.md +242 -0
  218. package/template/.opencode/skills/impeccable/reference/product.md +62 -0
  219. package/template/.opencode/skills/impeccable/reference/quieter.md +99 -0
  220. package/template/.opencode/skills/impeccable/reference/responsive-design.md +114 -0
  221. package/template/.opencode/skills/impeccable/reference/shape.md +165 -0
  222. package/template/.opencode/skills/impeccable/reference/spatial-design.md +100 -0
  223. package/template/.opencode/skills/impeccable/reference/teach.md +156 -0
  224. package/template/.opencode/skills/impeccable/reference/typeset.md +124 -0
  225. package/template/.opencode/skills/impeccable/reference/typography.md +159 -0
  226. package/template/.opencode/skills/impeccable/reference/ux-writing.md +107 -0
  227. package/template/.opencode/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
  228. package/template/.opencode/skills/impeccable/scripts/command-metadata.json +94 -0
  229. package/template/.opencode/skills/impeccable/scripts/critique-storage.mjs +242 -0
  230. package/template/.opencode/skills/impeccable/scripts/design-parser.mjs +820 -0
  231. package/template/.opencode/skills/impeccable/scripts/detect-csp.mjs +198 -0
  232. package/template/.opencode/skills/impeccable/scripts/detect.mjs +21 -0
  233. package/template/.opencode/skills/impeccable/scripts/impeccable-paths.mjs +110 -0
  234. package/template/.opencode/skills/impeccable/scripts/is-generated.mjs +69 -0
  235. package/template/.opencode/skills/impeccable/scripts/live-accept.mjs +595 -0
  236. package/template/.opencode/skills/impeccable/scripts/live-browser-session.js +123 -0
  237. package/template/.opencode/skills/impeccable/scripts/live-browser.js +4860 -0
  238. package/template/.opencode/skills/impeccable/scripts/live-complete.mjs +75 -0
  239. package/template/.opencode/skills/impeccable/scripts/live-completion.mjs +18 -0
  240. package/template/.opencode/skills/impeccable/scripts/live-inject.mjs +446 -0
  241. package/template/.opencode/skills/impeccable/scripts/live-poll.mjs +200 -0
  242. package/template/.opencode/skills/impeccable/scripts/live-resume.mjs +48 -0
  243. package/template/.opencode/skills/impeccable/scripts/live-server.mjs +838 -0
  244. package/template/.opencode/skills/impeccable/scripts/live-session-store.mjs +254 -0
  245. package/template/.opencode/skills/impeccable/scripts/live-status.mjs +47 -0
  246. package/template/.opencode/skills/impeccable/scripts/live-wrap.mjs +632 -0
  247. package/template/.opencode/skills/impeccable/scripts/live.mjs +247 -0
  248. package/template/.opencode/skills/impeccable/scripts/load-context.mjs +141 -0
  249. package/template/.opencode/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  250. package/template/.opencode/skills/impeccable/scripts/pin.mjs +214 -0
  251. package/template/.opencode/skills/iterative-retrieval/SKILL.md +202 -0
  252. package/template/.opencode/skills/java-coding-standards/SKILL.md +138 -0
  253. package/template/.opencode/skills/jetpack-compose/.skillfish.json +10 -0
  254. package/template/.opencode/skills/jetpack-compose/SKILL.md +420 -0
  255. package/template/.opencode/skills/jpa-patterns/SKILL.md +141 -0
  256. package/template/.opencode/skills/nutrient-document-processing/SKILL.md +165 -0
  257. package/template/.opencode/skills/nuxt-ui/SKILL.md +334 -0
  258. package/template/.opencode/skills/nuxt-ui/references/components.md +377 -0
  259. package/template/.opencode/skills/nuxt-ui/references/composables.md +127 -0
  260. package/template/.opencode/skills/nuxt-ui/references/layouts/chat.md +266 -0
  261. package/template/.opencode/skills/nuxt-ui/references/layouts/dashboard.md +220 -0
  262. package/template/.opencode/skills/nuxt-ui/references/layouts/docs.md +141 -0
  263. package/template/.opencode/skills/nuxt-ui/references/layouts/editor.md +168 -0
  264. package/template/.opencode/skills/nuxt-ui/references/layouts/page.md +260 -0
  265. package/template/.opencode/skills/nuxt-ui/references/theming.md +427 -0
  266. package/template/.opencode/skills/postgres-patterns/SKILL.md +146 -0
  267. package/template/.opencode/skills/project-guidelines-example/SKILL.md +345 -0
  268. package/template/.opencode/skills/python-patterns/SKILL.md +749 -0
  269. package/template/.opencode/skills/python-testing/SKILL.md +815 -0
  270. package/template/.opencode/skills/security-review/SKILL.md +494 -0
  271. package/template/.opencode/skills/security-review/cloud-infrastructure-security.md +361 -0
  272. package/template/.opencode/skills/shadcn-ui/README.md +248 -0
  273. package/template/.opencode/skills/shadcn-ui/SKILL.md +326 -0
  274. package/template/.opencode/skills/shadcn-ui/examples/auth-layout.tsx +177 -0
  275. package/template/.opencode/skills/shadcn-ui/examples/data-table.tsx +313 -0
  276. package/template/.opencode/skills/shadcn-ui/examples/form-pattern.tsx +177 -0
  277. package/template/.opencode/skills/shadcn-ui/resources/component-catalog.md +481 -0
  278. package/template/.opencode/skills/shadcn-ui/resources/customization-guide.md +516 -0
  279. package/template/.opencode/skills/shadcn-ui/resources/migration-guide.md +463 -0
  280. package/template/.opencode/skills/shadcn-ui/resources/setup-guide.md +412 -0
  281. package/template/.opencode/skills/shadcn-ui/scripts/verify-setup.sh +134 -0
  282. package/template/.opencode/skills/springboot-patterns/SKILL.md +304 -0
  283. package/template/.opencode/skills/springboot-security/SKILL.md +119 -0
  284. package/template/.opencode/skills/springboot-tdd/SKILL.md +157 -0
  285. package/template/.opencode/skills/springboot-verification/SKILL.md +100 -0
  286. package/template/.opencode/skills/strategic-compact/SKILL.md +63 -0
  287. package/template/.opencode/skills/strategic-compact/suggest-compact.sh +52 -0
  288. package/template/.opencode/skills/tdd-workflow/SKILL.md +409 -0
  289. package/template/.opencode/skills/vercel-composition-patterns/AGENTS.md +946 -0
  290. package/template/.opencode/skills/vercel-composition-patterns/SKILL.md +89 -0
  291. package/template/.opencode/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  292. package/template/.opencode/skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
  293. package/template/.opencode/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  294. package/template/.opencode/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
  295. package/template/.opencode/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
  296. package/template/.opencode/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
  297. package/template/.opencode/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
  298. package/template/.opencode/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
  299. package/template/.opencode/skills/vercel-react-best-practices/AGENTS.md +2934 -0
  300. package/template/.opencode/skills/vercel-react-best-practices/SKILL.md +136 -0
  301. package/template/.opencode/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  302. package/template/.opencode/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  303. package/template/.opencode/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  304. package/template/.opencode/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  305. package/template/.opencode/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  306. package/template/.opencode/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  307. package/template/.opencode/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  308. package/template/.opencode/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  309. package/template/.opencode/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  310. package/template/.opencode/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  311. package/template/.opencode/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  312. package/template/.opencode/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  313. package/template/.opencode/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  314. package/template/.opencode/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  315. package/template/.opencode/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  316. package/template/.opencode/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  317. package/template/.opencode/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  318. package/template/.opencode/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  319. package/template/.opencode/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  320. package/template/.opencode/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  321. package/template/.opencode/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  322. package/template/.opencode/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  323. package/template/.opencode/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  324. package/template/.opencode/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  325. package/template/.opencode/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  326. package/template/.opencode/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  327. package/template/.opencode/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  328. package/template/.opencode/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  329. package/template/.opencode/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  330. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  331. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  332. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  333. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  334. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  335. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  336. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  337. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  338. package/template/.opencode/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  339. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  340. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  341. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  342. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  343. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  344. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  345. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  346. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  347. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  348. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  349. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  350. package/template/.opencode/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  351. package/template/.opencode/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  352. package/template/.opencode/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  353. package/template/.opencode/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  354. package/template/.opencode/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  355. package/template/.opencode/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  356. package/template/.opencode/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  357. package/template/.opencode/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  358. package/template/.opencode/skills/verification-loop/SKILL.md +120 -0
  359. package/template/.opencode/skills/web-design-guidelines/SKILL.md +39 -0
  360. package/template/AGENTS.md +32 -0
  361. package/template/opencode.json +354 -0
@@ -0,0 +1,807 @@
1
+ # API Patterns Guide - useApi Composable
2
+
3
+ Comprehensive guide untuk menggunakan custom `useApi` composable dalam project ini.
4
+
5
+ ## 📋 Daftar Isi
6
+
7
+ 1. [Overview](#overview)
8
+ 2. [Why useApi?](#why-useapi)
9
+ 3. [Basic Usage](#basic-usage)
10
+ 4. [Advanced Patterns](#advanced-patterns)
11
+ 5. [Error Handling](#error-handling)
12
+ 6. [Authentication](#authentication)
13
+ 7. [Best Practices](#best-practices)
14
+ 8. [Migration Guide](#migration-guide)
15
+
16
+ ---
17
+
18
+ ## Overview
19
+
20
+ `useApi` adalah custom composable yang menyatukan `useFetch` dan `$fetch` dengan satu interface yang konsisten, plus automatic authentication dan enhanced error handling.
21
+
22
+ **Location:** `app/composables/useApi.ts`
23
+
24
+ ### Key Features
25
+
26
+ - ✅ **Unified API** - Single interface untuk GET, POST, PUT, DELETE
27
+ - ✅ **Smart SSR/CSR** - Otomatis pakai `useFetch` di SSR, `$fetch` di CSR
28
+ - ✅ **Auto Authentication** - Cookies forwarded otomatis
29
+ - ✅ **Enhanced Errors** - `error.value.message` langsung accessible
30
+ - ✅ **Auto Redirect** - 401 otomatis redirect ke login
31
+ - ✅ **Type Safe** - Full TypeScript support dengan generics
32
+ - ✅ **Promise-like** - Bisa di-await seperti Promise
33
+
34
+ ---
35
+
36
+ ## Why useApi?
37
+
38
+ ### Problem dengan Native Composables
39
+
40
+ **useFetch:**
41
+
42
+ ```typescript
43
+ // ❌ Auth tidak automatic
44
+ const { data } = await useFetch('/api/users', {
45
+ headers: useRequestHeaders(['cookie']), // Manual!
46
+ })
47
+
48
+ // ❌ Error message susah diakses
49
+ if (error.value) {
50
+ // error.value.data?.message? error.value.message? Who knows!
51
+ console.log(error.value?.data?.message)
52
+ }
53
+
54
+ // ❌ POST/PUT/DELETE butuh useAsyncData
55
+ const { data } = await useAsyncData('create-user', () =>
56
+ $fetch('/api/users', { method: 'POST', body: formData })
57
+ )
58
+ ```
59
+
60
+ **$fetch:**
61
+
62
+ ```typescript
63
+ // ❌ Tidak bisa di-await di component root
64
+ const data = await $fetch('/api/users') // Hydration error!
65
+
66
+ // ❌ No reactive state
67
+ const loading = ref(false)
68
+ const error = ref(null)
69
+ // Manual state management diperlukan
70
+ ```
71
+
72
+ ### Solution dengan useApi
73
+
74
+ ```typescript
75
+ // ✅ Simple, automatic, type-safe
76
+ const { data, pending, error } = await useApi<User[]>('/users')
77
+
78
+ // ✅ Works untuk semua HTTP methods
79
+ const { data: created } = await useApi('/users', {
80
+ method: 'POST',
81
+ body: newUser,
82
+ })
83
+
84
+ // ✅ Error message langsung accessible
85
+ if (error.value) {
86
+ console.log(error.value.message) // Consistent!
87
+ }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Basic Usage
93
+
94
+ ### GET Request
95
+
96
+ ```typescript
97
+ <script setup lang="ts">
98
+ interface User {
99
+ id: string
100
+ name: string
101
+ email: string
102
+ }
103
+
104
+ // Simple GET
105
+ const { data, pending, error } = await useApi<User[]>('/users')
106
+
107
+ // With query parameters
108
+ const { data: filteredUsers } = await useApi<User[]>('/users', {
109
+ query: {
110
+ role: 'admin',
111
+ page: 1,
112
+ limit: 10
113
+ }
114
+ })
115
+
116
+ // Reactive query
117
+ const search = ref('')
118
+ const { data: searchResults } = await useApi<User[]>('/users', {
119
+ query: { q: search },
120
+ watch: [search] // Refetch when search changes
121
+ })
122
+ </script>
123
+
124
+ <template>
125
+ <div v-if="pending">Loading...</div>
126
+ <div v-else-if="error">{{ error.message }}</div>
127
+ <ul v-else>
128
+ <li v-for="user in data?.data" :key="user.id">
129
+ {{ user.name }}
130
+ </li>
131
+ </ul>
132
+ </template>
133
+ ```
134
+
135
+ ### POST Request
136
+
137
+ ```typescript
138
+ <script setup lang="ts">
139
+ interface CreateUserDto {
140
+ name: string
141
+ email: string
142
+ password: string
143
+ }
144
+
145
+ interface User {
146
+ id: string
147
+ name: string
148
+ email: string
149
+ }
150
+
151
+ const form = reactive<CreateUserDto>({
152
+ name: '',
153
+ email: '',
154
+ password: ''
155
+ })
156
+
157
+ const createUser = async () => {
158
+ const { data, error } = await useApi<User>('/users', {
159
+ method: 'POST',
160
+ body: form
161
+ })
162
+
163
+ if (error.value) {
164
+ useToast().add({
165
+ title: 'Error',
166
+ description: error.value.message,
167
+ color: 'red'
168
+ })
169
+ return
170
+ }
171
+
172
+ useToast().add({
173
+ title: 'Success',
174
+ description: `User ${data.value?.data.name} created!`
175
+ })
176
+
177
+ navigateTo(`/users/${data.value?.data.id}`)
178
+ }
179
+ </script>
180
+ ```
181
+
182
+ ### PUT/PATCH Request
183
+
184
+ ```typescript
185
+ const updateUser = async (userId: string) => {
186
+ const { data, error } = await useApi<User>(`/users/${userId}`, {
187
+ method: 'PATCH',
188
+ body: {
189
+ name: 'Updated Name',
190
+ email: 'updated@example.com',
191
+ },
192
+ })
193
+
194
+ if (!error.value) {
195
+ console.log('Updated:', data.value?.data)
196
+ }
197
+ }
198
+ ```
199
+
200
+ ### DELETE Request
201
+
202
+ ```typescript
203
+ const deleteUser = async (userId: string) => {
204
+ const confirmed = confirm('Are you sure?')
205
+ if (!confirmed) return
206
+
207
+ const { error } = await useApi(`/users/${userId}`, {
208
+ method: 'DELETE',
209
+ })
210
+
211
+ if (error.value) {
212
+ alert(error.value.message)
213
+ } else {
214
+ // Refresh list atau remove dari UI
215
+ users.value = users.value.filter((u) => u.id !== userId)
216
+ }
217
+ }
218
+ ```
219
+
220
+ ---
221
+
222
+ ## Advanced Patterns
223
+
224
+ ### Manual Trigger (immediate: false)
225
+
226
+ ```typescript
227
+ <script setup lang="ts">
228
+ // Don't execute immediately
229
+ const { data, execute, pending } = await useApi<User>('/users/123', {
230
+ immediate: false
231
+ })
232
+
233
+ const loadUser = async () => {
234
+ await execute()
235
+ // data.value now populated
236
+ }
237
+
238
+ // Or use in onMounted
239
+ onMounted(() => {
240
+ loadUser()
241
+ })
242
+ </script>
243
+
244
+ <template>
245
+ <button @click="loadUser" :disabled="pending">
246
+ Load User
247
+ </button>
248
+ </template>
249
+ ```
250
+
251
+ ### Optimistic Updates
252
+
253
+ ```typescript
254
+ const deleteUser = async (userId: string) => {
255
+ // Save original state
256
+ const originalUsers = [...users.value]
257
+
258
+ // Optimistic update
259
+ users.value = users.value.filter((u) => u.id !== userId)
260
+
261
+ // Perform API call
262
+ const { error } = await useApi(`/users/${userId}`, {
263
+ method: 'DELETE',
264
+ })
265
+
266
+ if (error.value) {
267
+ // Rollback on error
268
+ users.value = originalUsers
269
+ useToast().add({
270
+ title: 'Error',
271
+ description: error.value.message,
272
+ color: 'red',
273
+ })
274
+ }
275
+ }
276
+ ```
277
+
278
+ ### Refresh & Refetch
279
+
280
+ ```typescript
281
+ const { data, refresh, execute } = await useApi<User[]>('/users')
282
+
283
+ // Refresh (same parameters)
284
+ const reloadUsers = async () => {
285
+ await refresh()
286
+ }
287
+
288
+ // Execute again
289
+ const loadMore = async () => {
290
+ await execute()
291
+ }
292
+
293
+ // Auto-refresh every 30s
294
+ onMounted(() => {
295
+ const interval = setInterval(refresh, 30000)
296
+ onUnmounted(() => clearInterval(interval))
297
+ })
298
+ ```
299
+
300
+ ### Dependent Requests
301
+
302
+ ```typescript
303
+ // First request
304
+ const { data: user } = await useApi<User>(`/users/${userId}`)
305
+
306
+ // Second request depends on first
307
+ const { data: posts } = await useApi<Post[]>('/posts', {
308
+ query: {
309
+ authorId: computed(() => user.value?.data.id),
310
+ },
311
+ immediate: computed(() => !!user.value), // Only fetch when user loaded
312
+ })
313
+ ```
314
+
315
+ ### Polling
316
+
317
+ ```typescript
318
+ const { data: status, refresh } = await useApi<JobStatus>(`/jobs/${jobId}`)
319
+
320
+ // Poll every 2 seconds until complete
321
+ const pollJob = () => {
322
+ const interval = setInterval(async () => {
323
+ await refresh()
324
+
325
+ if (status.value?.data.status === 'completed') {
326
+ clearInterval(interval)
327
+ useToast().add({ title: 'Job completed!' })
328
+ }
329
+ }, 2000)
330
+
331
+ onUnmounted(() => clearInterval(interval))
332
+ }
333
+
334
+ onMounted(pollJob)
335
+ ```
336
+
337
+ ### Pagination
338
+
339
+ ```typescript
340
+ <script setup lang="ts">
341
+ const page = ref(1)
342
+ const limit = ref(10)
343
+
344
+ const { data: response, pending } = await useApi<User[]>('/users', {
345
+ query: { page, limit },
346
+ watch: [page, limit]
347
+ })
348
+
349
+ const users = computed(() => response.value?.data || [])
350
+ const total = computed(() => response.value?.total || 0)
351
+
352
+ const nextPage = () => {
353
+ if (page.value * limit.value < total.value) {
354
+ page.value++
355
+ }
356
+ }
357
+
358
+ const prevPage = () => {
359
+ if (page.value > 1) {
360
+ page.value--
361
+ }
362
+ }
363
+ </script>
364
+
365
+ <template>
366
+ <div>
367
+ <div v-if="pending">Loading...</div>
368
+ <ul v-else>
369
+ <li v-for="user in users" :key="user.id">{{ user.name }}</li>
370
+ </ul>
371
+
372
+ <div class="flex gap-2">
373
+ <button @click="prevPage" :disabled="page === 1">Previous</button>
374
+ <span>Page {{ page }} of {{ Math.ceil(total / limit) }}</span>
375
+ <button @click="nextPage" :disabled="page * limit >= total">Next</button>
376
+ </div>
377
+ </div>
378
+ </template>
379
+ ```
380
+
381
+ ### Infinite Scroll
382
+
383
+ ```typescript
384
+ <script setup lang="ts">
385
+ const page = ref(1)
386
+ const allUsers = ref<User[]>([])
387
+
388
+ const { data, pending, execute } = await useApi<User[]>('/users', {
389
+ query: computed(() => ({ page: page.value, limit: 20 })),
390
+ immediate: false
391
+ })
392
+
393
+ // Load initial page
394
+ onMounted(() => execute())
395
+
396
+ // Append results
397
+ watch(data, (newData) => {
398
+ if (newData?.data) {
399
+ allUsers.value = [...allUsers.value, ...newData.data]
400
+ }
401
+ })
402
+
403
+ // Load more
404
+ const loadMore = async () => {
405
+ page.value++
406
+ await execute()
407
+ }
408
+
409
+ // Infinite scroll observer
410
+ const sentinel = ref<HTMLElement>()
411
+ onMounted(() => {
412
+ const observer = new IntersectionObserver((entries) => {
413
+ if (entries[0].isIntersecting && !pending.value) {
414
+ loadMore()
415
+ }
416
+ })
417
+
418
+ if (sentinel.value) {
419
+ observer.observe(sentinel.value)
420
+ }
421
+
422
+ onUnmounted(() => observer.disconnect())
423
+ })
424
+ </script>
425
+
426
+ <template>
427
+ <div>
428
+ <div v-for="user in allUsers" :key="user.id">
429
+ {{ user.name }}
430
+ </div>
431
+ <div ref="sentinel" class="h-4" />
432
+ <div v-if="pending">Loading more...</div>
433
+ </div>
434
+ </template>
435
+ ```
436
+
437
+ ---
438
+
439
+ ## Error Handling
440
+
441
+ ### Basic Error Handling
442
+
443
+ ```typescript
444
+ const { data, error } = await useApi<User>('/users/123')
445
+
446
+ if (error.value) {
447
+ // error.value.message is always accessible
448
+ console.error(error.value.message)
449
+
450
+ // Show user-friendly message
451
+ useToast().add({
452
+ title: 'Error',
453
+ description: error.value.message,
454
+ color: 'red',
455
+ })
456
+ }
457
+ ```
458
+
459
+ ### Error Types
460
+
461
+ ```typescript
462
+ interface ApiErrorResponse {
463
+ status?: boolean | string
464
+ message?: string // Always present
465
+ data?: unknown // Additional error data
466
+ }
467
+
468
+ // Usage
469
+ const { error } = await useApi('/users')
470
+
471
+ if (error.value) {
472
+ console.log(error.value.message) // "User not found"
473
+ console.log(error.value.status) // false
474
+ console.log(error.value.data) // Additional error context
475
+ }
476
+ ```
477
+
478
+ ### Global Error Handler
479
+
480
+ ```typescript
481
+ // Create composable for consistent error handling
482
+ export const useApiError = () => {
483
+ const toast = useToast()
484
+
485
+ const handleError = (error: Ref<ApiErrorResponse | null>) => {
486
+ if (!error.value) return
487
+
488
+ const message = error.value.message || 'An error occurred'
489
+
490
+ // Log to monitoring service
491
+ if (import.meta.client) {
492
+ console.error('API Error:', error.value)
493
+ // trackError(error.value)
494
+ }
495
+
496
+ // Show toast
497
+ toast.add({
498
+ title: 'Error',
499
+ description: message,
500
+ color: 'red',
501
+ })
502
+ }
503
+
504
+ return { handleError }
505
+ }
506
+
507
+ // Usage
508
+ const { data, error } = await useApi('/users')
509
+ const { handleError } = useApiError()
510
+
511
+ watch(error, () => handleError(error))
512
+ ```
513
+
514
+ ### Retry Logic
515
+
516
+ ```typescript
517
+ const maxRetries = 3
518
+ let retryCount = 0
519
+
520
+ const { data, error, execute } = await useApi<User[]>('/users', {
521
+ immediate: false,
522
+ })
523
+
524
+ const fetchWithRetry = async () => {
525
+ while (retryCount < maxRetries) {
526
+ await execute()
527
+
528
+ if (!error.value) {
529
+ retryCount = 0
530
+ return
531
+ }
532
+
533
+ retryCount++
534
+
535
+ if (retryCount < maxRetries) {
536
+ await new Promise((resolve) => setTimeout(resolve, 1000 * retryCount))
537
+ }
538
+ }
539
+
540
+ // Max retries reached
541
+ useToast().add({
542
+ title: 'Failed after 3 retries',
543
+ description: error.value?.message,
544
+ color: 'red',
545
+ })
546
+ }
547
+
548
+ onMounted(fetchWithRetry)
549
+ ```
550
+
551
+ ---
552
+
553
+ ## Authentication
554
+
555
+ ### Automatic Cookie Forwarding
556
+
557
+ ```typescript
558
+ // ✅ Cookies automatically forwarded on SSR
559
+ const { data } = await useApi<User>('/me')
560
+
561
+ // No manual header management needed!
562
+ // useApi handles:
563
+ // - Server: useRequestHeaders(['cookie'])
564
+ // - Client: credentials: 'include'
565
+ ```
566
+
567
+ ### 401 Auto-Redirect
568
+
569
+ ```typescript
570
+ // If API returns 401, useApi automatically redirects to:
571
+ // - /cms/auth/login (for /cms/* routes)
572
+ // - /auth/login (for other routes)
573
+
574
+ // No manual redirect logic needed!
575
+ const { data } = await useApi<User>('/protected-resource')
576
+ // If unauthorized, user is redirected automatically
577
+ ```
578
+
579
+ ### Custom Auth Headers
580
+
581
+ ```typescript
582
+ // For Bearer token authentication (if needed)
583
+ const token = useCookie('auth_token')
584
+
585
+ const { data } = await useApi<User>('/users', {
586
+ headers: {
587
+ Authorization: `Bearer ${token.value}`,
588
+ },
589
+ })
590
+ ```
591
+
592
+ ### Skip Auto-Redirect
593
+
594
+ ```typescript
595
+ // Prevent auto-redirect on specific pages
596
+ // Already handled in useApi for public pages:
597
+ const publicPages = [
598
+ '/cms/auth/login',
599
+ '/blog',
600
+ '/services',
601
+ '/about',
602
+ // etc.
603
+ ]
604
+
605
+ // If you need custom handling, use try-catch
606
+ const { error } = await useApi('/protected')
607
+
608
+ if (error.value && error.value.status === 401) {
609
+ // Custom 401 handling
610
+ showLoginModal()
611
+ }
612
+ ```
613
+
614
+ ---
615
+
616
+ ## Best Practices
617
+
618
+ ### 1. Always Use Type Generics
619
+
620
+ ```typescript
621
+ // ❌ Bad - No type safety
622
+ const { data } = await useApi('/users')
623
+
624
+ // ✅ Good - Type safe
625
+ interface User {
626
+ id: string
627
+ name: string
628
+ email: string
629
+ }
630
+
631
+ const { data } = await useApi<User[]>('/users')
632
+ // data.value?.data is now typed as User[]
633
+ ```
634
+
635
+ ### 2. Handle Errors Gracefully
636
+
637
+ ```typescript
638
+ // ❌ Bad - Ignore errors
639
+ const { data } = await useApi('/users')
640
+
641
+ // ✅ Good - Always check errors
642
+ const { data, error } = await useApi('/users')
643
+
644
+ if (error.value) {
645
+ useToast().add({
646
+ title: 'Error',
647
+ description: error.value.message,
648
+ color: 'red',
649
+ })
650
+ return
651
+ }
652
+ ```
653
+
654
+ ### 3. Use Computed for Response Data
655
+
656
+ ```typescript
657
+ // ✅ Good - Extract data into computed
658
+ const { data: response } = await useApi<User[]>('/users')
659
+ const users = computed(() => response.value?.data || [])
660
+
661
+ // Now use users in template
662
+ <template>
663
+ <div v-for="user in users" :key="user.id">
664
+ {{ user.name }}
665
+ </div>
666
+ </template>
667
+ ```
668
+
669
+ ### 4. Leverage Immediate: false for Forms
670
+
671
+ ```typescript
672
+ // ✅ Good for submit handlers
673
+ const { execute, pending, error } = await useApi('/users', {
674
+ method: 'POST',
675
+ body: form,
676
+ immediate: false,
677
+ })
678
+
679
+ const handleSubmit = async () => {
680
+ await execute()
681
+ // Handle response
682
+ }
683
+ ```
684
+
685
+ ### 5. Use Watch for Reactive Queries
686
+
687
+ ```typescript
688
+ // ✅ Good - Reactive filters
689
+ const filters = reactive({
690
+ role: 'admin',
691
+ status: 'active',
692
+ })
693
+
694
+ const { data } = await useApi('/users', {
695
+ query: filters,
696
+ watch: [() => filters.role, () => filters.status],
697
+ })
698
+ ```
699
+
700
+ ---
701
+
702
+ ## Migration Guide
703
+
704
+ ### From useFetch to useApi
705
+
706
+ ```typescript
707
+ // Before
708
+ const { data, pending, error, refresh } = await useFetch('/api/users', {
709
+ headers: useRequestHeaders(['cookie']),
710
+ query: { page: 1 },
711
+ })
712
+
713
+ // After
714
+ const { data, pending, error, refresh } = await useApi('/users', {
715
+ query: { page: 1 },
716
+ })
717
+ // Simpler! Auth automatic.
718
+ ```
719
+
720
+ ### From $fetch to useApi
721
+
722
+ ```typescript
723
+ // Before
724
+ const loading = ref(false)
725
+ const error = ref(null)
726
+ const users = ref([])
727
+
728
+ const fetchUsers = async () => {
729
+ loading.value = true
730
+ try {
731
+ users.value = await $fetch('/api/users')
732
+ } catch (err) {
733
+ error.value = err
734
+ } finally {
735
+ loading.value = false
736
+ }
737
+ }
738
+
739
+ onMounted(fetchUsers)
740
+
741
+ // After
742
+ const { data: users, pending, error } = await useApi('/users')
743
+ // Much simpler! Reactive state automatic.
744
+ ```
745
+
746
+ ### From useAsyncData to useApi
747
+
748
+ ```typescript
749
+ // Before
750
+ const { data, pending, error } = await useAsyncData('users', () => $fetch('/api/users'))
751
+
752
+ // After
753
+ const { data, pending, error } = await useApi('/users')
754
+ // Cleaner! No manual key needed.
755
+ ```
756
+
757
+ ---
758
+
759
+ ## Common Patterns Cheatsheet
760
+
761
+ | Use Case | Code |
762
+ | -------------- | ------------------------------------------------------------ |
763
+ | Simple GET | `await useApi<T>('/endpoint')` |
764
+ | GET with query | `await useApi('/endpoint', { query: { key: 'value' } })` |
765
+ | POST | `await useApi('/endpoint', { method: 'POST', body: data })` |
766
+ | PUT/PATCH | `await useApi('/endpoint', { method: 'PATCH', body: data })` |
767
+ | DELETE | `await useApi('/endpoint', { method: 'DELETE' })` |
768
+ | Manual trigger | `await useApi('/endpoint', { immediate: false })` |
769
+ | Reactive query | `await useApi('/endpoint', { query, watch: [query] })` |
770
+ | Error handling | `if (error.value) { console.log(error.value.message) }` |
771
+ | Refresh | `await refresh()` |
772
+ | Re-execute | `await execute()` |
773
+
774
+ ---
775
+
776
+ ## Summary
777
+
778
+ **When to use useApi:**
779
+
780
+ - ✅ All internal API calls (recommended default)
781
+ - ✅ Protected routes requiring authentication
782
+ - ✅ Consistent error handling needed
783
+ - ✅ Want automatic SSR/CSR optimization
784
+
785
+ **When to use useFetch:**
786
+
787
+ - ⚠️ External third-party APIs
788
+ - ⚠️ Custom caching requirements
789
+ - ⚠️ Special configurations not supported by useApi
790
+
791
+ **When to use $fetch:**
792
+
793
+ - ⚠️ Server-side only code (server/api/\*)
794
+ - ⚠️ One-off requests without reactive state
795
+ - ⚠️ Background jobs or scheduled tasks
796
+
797
+ **Default choice: useApi for 99% of cases in this project.**
798
+
799
+ ---
800
+
801
+ For more examples, see:
802
+
803
+ - [EXAMPLES.md](./EXAMPLES.md) - Section 3: API Integration
804
+ - [CHEATSHEET.md](./CHEATSHEET.md) - Data Fetching section
805
+ - [frontend-developer.md](./frontend-developer.md) - Data Fetching Patterns
806
+
807
+ **Happy coding with useApi! 🚀**