specweave 0.23.16 → 0.24.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 (227) hide show
  1. package/.claude-plugin/marketplace.json +93 -38
  2. package/CLAUDE.md +159 -11
  3. package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
  4. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +57 -0
  5. package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
  6. package/dist/src/cli/commands/sync-spec-content.js +3 -0
  7. package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
  8. package/dist/src/cli/helpers/ado-area-path-mapper.d.ts +89 -0
  9. package/dist/src/cli/helpers/ado-area-path-mapper.d.ts.map +1 -0
  10. package/dist/src/cli/helpers/ado-area-path-mapper.js +213 -0
  11. package/dist/src/cli/helpers/ado-area-path-mapper.js.map +1 -0
  12. package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts +29 -0
  13. package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts.map +1 -0
  14. package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js +109 -0
  15. package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js.map +1 -0
  16. package/dist/src/cli/helpers/issue-tracker/ado.d.ts +1 -0
  17. package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
  18. package/dist/src/cli/helpers/issue-tracker/ado.js +2 -0
  19. package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
  20. package/dist/src/cli/helpers/smart-filter.d.ts +83 -0
  21. package/dist/src/cli/helpers/smart-filter.d.ts.map +1 -0
  22. package/dist/src/cli/helpers/smart-filter.js +265 -0
  23. package/dist/src/cli/helpers/smart-filter.js.map +1 -0
  24. package/dist/src/core/progress/progress-tracker.d.ts +4 -1
  25. package/dist/src/core/progress/progress-tracker.d.ts.map +1 -1
  26. package/dist/src/core/progress/progress-tracker.js +33 -4
  27. package/dist/src/core/progress/progress-tracker.js.map +1 -1
  28. package/dist/src/core/qa/quality-gate-decider.d.ts +1 -1
  29. package/dist/src/core/qa/quality-gate-decider.js +2 -2
  30. package/dist/src/core/qa/quality-gate-decider.js.map +1 -1
  31. package/dist/src/core/qa/risk-calculator.d.ts +2 -2
  32. package/dist/src/core/qa/risk-calculator.js +2 -2
  33. package/dist/src/core/spec-content-sync.d.ts +1 -1
  34. package/dist/src/core/spec-content-sync.d.ts.map +1 -1
  35. package/dist/src/core/validators/ac-presence-validator.d.ts +56 -0
  36. package/dist/src/core/validators/ac-presence-validator.d.ts.map +1 -0
  37. package/dist/src/core/validators/ac-presence-validator.js +149 -0
  38. package/dist/src/core/validators/ac-presence-validator.js.map +1 -0
  39. package/dist/src/integrations/ado/ado-dependency-loader.d.ts +1 -1
  40. package/dist/src/integrations/ado/ado-dependency-loader.d.ts.map +1 -1
  41. package/dist/src/integrations/ado/ado-dependency-loader.js +39 -7
  42. package/dist/src/integrations/ado/ado-dependency-loader.js.map +1 -1
  43. package/dist/src/integrations/ado/area-path-mapper.d.ts +137 -0
  44. package/dist/src/integrations/ado/area-path-mapper.d.ts.map +1 -0
  45. package/dist/src/integrations/ado/area-path-mapper.js +267 -0
  46. package/dist/src/integrations/ado/area-path-mapper.js.map +1 -0
  47. package/dist/src/integrations/jira/filter-processor.d.ts +126 -0
  48. package/dist/src/integrations/jira/filter-processor.d.ts.map +1 -0
  49. package/dist/src/integrations/jira/filter-processor.js +207 -0
  50. package/dist/src/integrations/jira/filter-processor.js.map +1 -0
  51. package/dist/src/integrations/jira/jira-client.d.ts +13 -0
  52. package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
  53. package/dist/src/integrations/jira/jira-client.js +33 -0
  54. package/dist/src/integrations/jira/jira-client.js.map +1 -1
  55. package/dist/src/utils/ac-embedder.d.ts +63 -0
  56. package/dist/src/utils/ac-embedder.d.ts.map +1 -0
  57. package/dist/src/utils/ac-embedder.js +217 -0
  58. package/dist/src/utils/ac-embedder.js.map +1 -0
  59. package/dist/src/utils/env-manager.d.ts +86 -0
  60. package/dist/src/utils/env-manager.d.ts.map +1 -0
  61. package/dist/src/utils/env-manager.js +188 -0
  62. package/dist/src/utils/env-manager.js.map +1 -0
  63. package/package.json +1 -1
  64. package/plugins/specweave/.claude-plugin/plugin.json +1 -1
  65. package/plugins/specweave/agents/AGENTS-INDEX.md +1 -1
  66. package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +9 -9
  67. package/plugins/specweave/commands/specweave-do.md +37 -0
  68. package/plugins/specweave/commands/specweave-done.md +159 -0
  69. package/plugins/specweave/commands/specweave-embed-acs.md +446 -0
  70. package/plugins/specweave/commands/specweave-next.md +148 -3
  71. package/plugins/specweave/commands/specweave-qa.md +2 -2
  72. package/plugins/specweave/hooks/lib/migrate-increment-work.sh +1 -1
  73. package/plugins/specweave/hooks/lib/migrate-increment-work.sh.bak +245 -0
  74. package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
  75. package/plugins/specweave/hooks/lib/sync-spec-content.sh.bak +149 -0
  76. package/plugins/specweave/hooks/lib/update-status-line.sh +34 -4
  77. package/plugins/specweave/hooks/lib/validate-spec-status.sh +1 -1
  78. package/plugins/specweave/hooks/lib/validate-spec-status.sh.bak +163 -0
  79. package/plugins/specweave/hooks/post-first-increment.sh +1 -1
  80. package/plugins/specweave/hooks/post-first-increment.sh.bak +61 -0
  81. package/plugins/specweave/hooks/post-spec-update.sh +1 -1
  82. package/plugins/specweave/hooks/post-spec-update.sh.bak +158 -0
  83. package/plugins/specweave/hooks/post-user-story-complete.sh +1 -1
  84. package/plugins/specweave/hooks/post-user-story-complete.sh.bak +179 -0
  85. package/plugins/specweave/hooks/pre-command-deduplication.sh +1 -1
  86. package/plugins/specweave/hooks/pre-command-deduplication.sh.bak +83 -0
  87. package/plugins/specweave/hooks/pre-increment-start.sh +168 -0
  88. package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
  89. package/plugins/specweave/hooks/user-prompt-submit.sh.bak +386 -0
  90. package/plugins/specweave/skills/SKILLS-INDEX.md +1 -1
  91. package/plugins/specweave/skills/specweave-framework/SKILL.md +1 -1
  92. package/plugins/specweave-ado/.claude-plugin/plugin.json +1 -1
  93. package/plugins/specweave-ado/agents/ado-manager/AGENT.md +23 -0
  94. package/plugins/specweave-ado/agents/ado-multi-project-mapper/AGENT.md +23 -0
  95. package/plugins/specweave-ado/agents/ado-sync-judge/AGENT.md +23 -0
  96. package/plugins/specweave-ado/commands/specweave-ado-import-projects.md +331 -0
  97. package/plugins/specweave-alternatives/.claude-plugin/plugin.json +10 -0
  98. package/plugins/specweave-alternatives/commands/alternatives-analyze.md +336 -0
  99. package/plugins/specweave-alternatives/skills/architecture-alternatives/SKILL.md +651 -0
  100. package/plugins/specweave-alternatives/skills/bmad-method/SKILL.md +420 -0
  101. package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +487 -0
  102. package/plugins/specweave-backend/agents/database-optimizer/AGENT.md +23 -0
  103. package/plugins/specweave-backend/commands/api-scaffold.md +80 -0
  104. package/plugins/specweave-backend/commands/crud-generate.md +109 -0
  105. package/plugins/specweave-backend/commands/migration-generate.md +139 -0
  106. package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +23 -0
  107. package/plugins/specweave-confluent/commands/connector-deploy.md +154 -0
  108. package/plugins/specweave-confluent/commands/ksqldb-query.md +179 -0
  109. package/plugins/specweave-confluent/commands/schema-register.md +123 -0
  110. package/plugins/specweave-core/.claude-plugin/plugin.json +21 -0
  111. package/plugins/specweave-core/commands/architecture-review.md +288 -0
  112. package/plugins/specweave-core/commands/code-review.md +213 -0
  113. package/plugins/specweave-core/commands/refactor-plan.md +249 -0
  114. package/plugins/specweave-core/skills/code-quality/SKILL.md +157 -0
  115. package/plugins/specweave-core/skills/design-patterns/SKILL.md +244 -0
  116. package/plugins/specweave-core/skills/software-architecture/SKILL.md +83 -0
  117. package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +22 -0
  118. package/plugins/specweave-cost-optimizer/commands/cost-analyze.md +360 -0
  119. package/plugins/specweave-cost-optimizer/commands/cost-optimize.md +480 -0
  120. package/plugins/specweave-cost-optimizer/skills/aws-cost-expert/SKILL.md +416 -0
  121. package/plugins/specweave-cost-optimizer/skills/cloud-pricing/SKILL.md +325 -0
  122. package/plugins/specweave-cost-optimizer/skills/cost-optimization/SKILL.md +337 -0
  123. package/plugins/specweave-diagrams/.claude-plugin/plugin.json +1 -1
  124. package/plugins/specweave-diagrams/agents/diagrams-architect/AGENT.md +23 -0
  125. package/plugins/specweave-diagrams/commands/diagrams-generate.md +168 -0
  126. package/plugins/specweave-docs/.claude-plugin/plugin.json +10 -0
  127. package/plugins/specweave-docs/commands/docs-generate.md +441 -0
  128. package/plugins/specweave-docs/commands/docs-init.md +334 -0
  129. package/plugins/specweave-docs/skills/docusaurus/SKILL.md +581 -0
  130. package/plugins/specweave-docs/skills/spec-driven-brainstorming/SKILL.md +689 -0
  131. package/plugins/specweave-docs/skills/technical-writing/SKILL.md +1039 -0
  132. package/plugins/specweave-docs-preview/.claude-plugin/plugin.json +1 -1
  133. package/plugins/specweave-figma/.claude-plugin/plugin.json +23 -0
  134. package/plugins/specweave-figma/commands/figma-import.md +690 -0
  135. package/plugins/specweave-figma/commands/figma-to-react.md +834 -0
  136. package/plugins/specweave-figma/commands/figma-tokens.md +815 -0
  137. package/plugins/specweave-frontend/.claude-plugin/plugin.json +21 -0
  138. package/plugins/specweave-frontend/agents/frontend-architect/AGENT.md +387 -0
  139. package/plugins/specweave-frontend/agents/frontend-architect/README.md +385 -0
  140. package/plugins/specweave-frontend/agents/frontend-architect/examples.md +590 -0
  141. package/plugins/specweave-frontend/agents/frontend-architect/templates/component-template.tsx +152 -0
  142. package/plugins/specweave-frontend/agents/frontend-architect/templates/hook-template.ts +311 -0
  143. package/plugins/specweave-frontend/agents/frontend-architect/templates/page-template.tsx +228 -0
  144. package/plugins/specweave-frontend/commands/component-generate.md +510 -0
  145. package/plugins/specweave-frontend/commands/design-system-init.md +494 -0
  146. package/plugins/specweave-frontend/commands/frontend-scaffold.md +207 -0
  147. package/plugins/specweave-frontend/commands/nextjs-setup.md +396 -0
  148. package/plugins/specweave-frontend/skills/design-system-architect/SKILL.md +278 -0
  149. package/plugins/specweave-frontend/skills/frontend/SKILL.md +420 -0
  150. package/plugins/specweave-frontend/skills/nextjs/SKILL.md +546 -0
  151. package/plugins/specweave-github/.claude-plugin/plugin.json +1 -1
  152. package/plugins/specweave-github/agents/github-manager/AGENT.md +23 -0
  153. package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +25 -0
  154. package/plugins/specweave-github/agents/user-story-updater/AGENT.md +25 -0
  155. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +194 -0
  156. package/plugins/specweave-github/lib/github-spec-content-sync.js +49 -0
  157. package/plugins/specweave-github/lib/github-spec-content-sync.ts +67 -0
  158. package/plugins/specweave-infrastructure/.claude-plugin/plugin.json +1 -1
  159. package/plugins/specweave-infrastructure/agents/devops/AGENT.md +26 -0
  160. package/plugins/specweave-infrastructure/agents/network-engineer/AGENT.md +26 -0
  161. package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +26 -0
  162. package/plugins/specweave-infrastructure/agents/performance-engineer/AGENT.md +26 -0
  163. package/plugins/specweave-infrastructure/agents/sre/AGENT.md +26 -0
  164. package/plugins/specweave-jira/.claude-plugin/plugin.json +1 -1
  165. package/plugins/specweave-jira/agents/jira-manager/AGENT.md +26 -0
  166. package/plugins/specweave-jira/commands/import-projects.js +183 -0
  167. package/plugins/specweave-jira/commands/import-projects.md +97 -0
  168. package/plugins/specweave-jira/commands/import-projects.ts +288 -0
  169. package/plugins/specweave-jira/commands/specweave-jira-import-projects.md +298 -0
  170. package/plugins/specweave-kafka/.claude-plugin/plugin.json +1 -1
  171. package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +26 -0
  172. package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +26 -0
  173. package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +26 -0
  174. package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +1 -1
  175. package/plugins/specweave-kubernetes/agents/kubernetes-architect/AGENT.md +26 -0
  176. package/plugins/specweave-kubernetes/commands/cluster-setup.md +262 -0
  177. package/plugins/specweave-kubernetes/commands/deployment-generate.md +242 -0
  178. package/plugins/specweave-kubernetes/commands/helm-scaffold.md +333 -0
  179. package/plugins/specweave-ml/.claude-plugin/plugin.json +3 -3
  180. package/plugins/specweave-ml/agents/data-scientist/AGENT.md +26 -0
  181. package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +26 -0
  182. package/plugins/specweave-ml/agents/mlops-engineer/AGENT.md +26 -0
  183. package/plugins/specweave-mobile/agents/mobile-architect/AGENT.md +26 -0
  184. package/plugins/specweave-mobile/commands/app-scaffold.md +233 -0
  185. package/plugins/specweave-mobile/commands/build-config.md +256 -0
  186. package/plugins/specweave-mobile/commands/screen-generate.md +289 -0
  187. package/plugins/specweave-n8n/.claude-plugin/plugin.json +1 -1
  188. package/plugins/specweave-payments/agents/payment-integration/AGENT.md +26 -0
  189. package/plugins/specweave-plugin-dev/.claude-plugin/plugin.json +20 -0
  190. package/plugins/specweave-plugin-dev/commands/plugin-create.md +333 -0
  191. package/plugins/specweave-plugin-dev/commands/plugin-publish.md +339 -0
  192. package/plugins/specweave-plugin-dev/commands/plugin-test.md +293 -0
  193. package/plugins/specweave-plugin-dev/skills/claude-sdk/SKILL.md +162 -0
  194. package/plugins/specweave-plugin-dev/skills/marketplace-publishing/SKILL.md +263 -0
  195. package/plugins/specweave-plugin-dev/skills/plugin-development/SKILL.md +316 -0
  196. package/plugins/specweave-release/.claude-plugin/plugin.json +1 -1
  197. package/plugins/specweave-release/agents/release-manager/AGENT.md +27 -0
  198. package/plugins/specweave-release/commands/specweave-release-npm.md +110 -0
  199. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +168 -0
  200. package/plugins/specweave-testing/.claude-plugin/plugin.json +21 -0
  201. package/plugins/specweave-testing/agents/qa-engineer/AGENT.md +797 -0
  202. package/plugins/specweave-testing/agents/qa-engineer/README.md +443 -0
  203. package/plugins/specweave-testing/agents/qa-engineer/templates/playwright-e2e-test.ts +470 -0
  204. package/plugins/specweave-testing/agents/qa-engineer/templates/test-data-factory.ts +507 -0
  205. package/plugins/specweave-testing/agents/qa-engineer/templates/vitest-unit-test.ts +400 -0
  206. package/plugins/specweave-testing/agents/qa-engineer/test-strategies.md +726 -0
  207. package/plugins/specweave-testing/commands/e2e-setup.md +1081 -0
  208. package/plugins/specweave-testing/commands/test-coverage.md +979 -0
  209. package/plugins/specweave-testing/commands/test-generate.md +1156 -0
  210. package/plugins/specweave-testing/commands/test-init.md +409 -0
  211. package/plugins/specweave-testing/skills/e2e-playwright/SKILL.md +769 -0
  212. package/plugins/specweave-testing/skills/tdd-expert/SKILL.md +934 -0
  213. package/plugins/specweave-testing/skills/unit-testing-expert/SKILL.md +1011 -0
  214. package/plugins/specweave-tooling/.claude-plugin/plugin.json +22 -0
  215. package/plugins/specweave-tooling/commands/specweave-tooling-skill-create.md +691 -0
  216. package/plugins/specweave-tooling/commands/specweave-tooling-skill-package.md +751 -0
  217. package/plugins/specweave-tooling/commands/specweave-tooling-skill-validate.md +858 -0
  218. package/plugins/specweave-ui/.claude-plugin/plugin.json +10 -0
  219. package/plugins/specweave-ui/commands/ui-automate.md +199 -0
  220. package/plugins/specweave-ui/commands/ui-inspect.md +70 -0
  221. package/plugins/specweave-ui/skills/browser-automation/SKILL.md +314 -0
  222. package/plugins/specweave-ui/skills/ui-testing/SKILL.md +716 -0
  223. package/plugins/specweave-ui/skills/visual-regression/SKILL.md +728 -0
  224. package/plugins/specweave/commands/check-hooks.md +0 -257
  225. package/plugins/specweave/commands/specweave-archive-increments.md +0 -82
  226. package/plugins/specweave/skills/plugin-expert/SKILL.md +0 -340
  227. /package/plugins/specweave/{agents/code-reviewer.md → skills/code-reviewer/SKILL.md} +0 -0
@@ -0,0 +1,152 @@
1
+ /**
2
+ * React Component Template
3
+ *
4
+ * This template provides a starting point for creating well-structured,
5
+ * type-safe React components following best practices.
6
+ *
7
+ * Usage:
8
+ * 1. Copy this template to your components directory
9
+ * 2. Rename file and component
10
+ * 3. Define props interface
11
+ * 4. Implement component logic
12
+ * 5. Add tests and Storybook stories
13
+ */
14
+
15
+ import React from 'react';
16
+ import { cn } from '@/lib/utils'; // Utility for className merging (clsx + tailwind-merge)
17
+
18
+ // ============================================================================
19
+ // TYPES
20
+ // ============================================================================
21
+
22
+ /**
23
+ * Props for the ComponentName component
24
+ *
25
+ * @property prop1 - Description of prop1
26
+ * @property prop2 - Description of prop2 (optional)
27
+ * @property className - Additional CSS classes (optional)
28
+ * @property children - React children (optional)
29
+ */
30
+ export interface ComponentNameProps {
31
+ /** Required prop with specific type */
32
+ prop1: string;
33
+
34
+ /** Optional prop with default value */
35
+ prop2?: number;
36
+
37
+ /** Callback function */
38
+ onAction?: (value: string) => void;
39
+
40
+ /** Additional CSS classes for customization */
41
+ className?: string;
42
+
43
+ /** React children */
44
+ children?: React.ReactNode;
45
+ }
46
+
47
+ // ============================================================================
48
+ // CONSTANTS
49
+ // ============================================================================
50
+
51
+ const DEFAULT_PROP2 = 42;
52
+
53
+ // ============================================================================
54
+ // COMPONENT
55
+ // ============================================================================
56
+
57
+ /**
58
+ * ComponentName - Brief description of what this component does
59
+ *
60
+ * More detailed description of the component's purpose, use cases,
61
+ * and any important implementation notes.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * <ComponentName
66
+ * prop1="value"
67
+ * prop2={100}
68
+ * onAction={(value) => console.log(value)}
69
+ * >
70
+ * Content
71
+ * </ComponentName>
72
+ * ```
73
+ */
74
+ export const ComponentName = React.forwardRef<
75
+ HTMLDivElement,
76
+ ComponentNameProps
77
+ >(
78
+ (
79
+ {
80
+ prop1,
81
+ prop2 = DEFAULT_PROP2,
82
+ onAction,
83
+ className,
84
+ children,
85
+ ...restProps
86
+ },
87
+ ref
88
+ ) => {
89
+ // ========================================================================
90
+ // STATE
91
+ // ========================================================================
92
+
93
+ const [internalState, setInternalState] = React.useState<string>('');
94
+
95
+ // ========================================================================
96
+ // EFFECTS
97
+ // ========================================================================
98
+
99
+ React.useEffect(() => {
100
+ // Side effects here
101
+ }, [prop1]);
102
+
103
+ // ========================================================================
104
+ // HANDLERS
105
+ // ========================================================================
106
+
107
+ const handleClick = React.useCallback(() => {
108
+ if (onAction) {
109
+ onAction(internalState);
110
+ }
111
+ }, [internalState, onAction]);
112
+
113
+ // ========================================================================
114
+ // RENDER
115
+ // ========================================================================
116
+
117
+ return (
118
+ <div
119
+ ref={ref}
120
+ className={cn(
121
+ // Base styles
122
+ 'rounded-lg border bg-white p-4 shadow-sm',
123
+ // Conditional styles
124
+ prop2 > 50 && 'border-blue-500',
125
+ // Custom className
126
+ className
127
+ )}
128
+ {...restProps}
129
+ >
130
+ <h2 className="text-lg font-semibold">{prop1}</h2>
131
+ <p className="text-sm text-gray-600">Value: {prop2}</p>
132
+
133
+ {children && <div className="mt-4">{children}</div>}
134
+
135
+ <button
136
+ onClick={handleClick}
137
+ className="mt-4 rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
138
+ >
139
+ Click Me
140
+ </button>
141
+ </div>
142
+ );
143
+ }
144
+ );
145
+
146
+ ComponentName.displayName = 'ComponentName';
147
+
148
+ // ============================================================================
149
+ // EXPORTS
150
+ // ============================================================================
151
+
152
+ export default ComponentName;
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Custom React Hook Template
3
+ *
4
+ * This template provides a starting point for creating reusable
5
+ * custom hooks following React best practices.
6
+ *
7
+ * Usage:
8
+ * 1. Copy this template to your hooks directory
9
+ * 2. Rename file and hook
10
+ * 3. Define input parameters and return type
11
+ * 4. Implement hook logic
12
+ * 5. Add tests and documentation
13
+ */
14
+
15
+ import { useState, useEffect, useCallback, useRef } from 'react';
16
+
17
+ // ============================================================================
18
+ // TYPES
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Options for the useCustomHook
23
+ */
24
+ export interface UseCustomHookOptions {
25
+ /** Enable/disable the hook */
26
+ enabled?: boolean;
27
+
28
+ /** Callback when data is loaded */
29
+ onSuccess?: (data: string) => void;
30
+
31
+ /** Callback when error occurs */
32
+ onError?: (error: Error) => void;
33
+
34
+ /** Retry count */
35
+ retryCount?: number;
36
+ }
37
+
38
+ /**
39
+ * Return type of useCustomHook
40
+ */
41
+ export interface UseCustomHookResult {
42
+ /** Current data */
43
+ data: string | null;
44
+
45
+ /** Loading state */
46
+ isLoading: boolean;
47
+
48
+ /** Error state */
49
+ error: Error | null;
50
+
51
+ /** Refetch function */
52
+ refetch: () => void;
53
+
54
+ /** Reset function */
55
+ reset: () => void;
56
+ }
57
+
58
+ // ============================================================================
59
+ // CONSTANTS
60
+ // ============================================================================
61
+
62
+ const DEFAULT_OPTIONS: Required<UseCustomHookOptions> = {
63
+ enabled: true,
64
+ onSuccess: () => {},
65
+ onError: () => {},
66
+ retryCount: 3,
67
+ };
68
+
69
+ // ============================================================================
70
+ // HOOK
71
+ // ============================================================================
72
+
73
+ /**
74
+ * useCustomHook - Brief description of what this hook does
75
+ *
76
+ * More detailed description of the hook's purpose, use cases,
77
+ * and any important implementation notes.
78
+ *
79
+ * @param param1 - Description of param1
80
+ * @param options - Configuration options
81
+ * @returns Hook result with data, loading, error states and utility functions
82
+ *
83
+ * @example
84
+ * ```tsx
85
+ * function MyComponent() {
86
+ * const { data, isLoading, error, refetch } = useCustomHook('value', {
87
+ * enabled: true,
88
+ * onSuccess: (data) => console.log('Success:', data),
89
+ * });
90
+ *
91
+ * if (isLoading) return <Spinner />;
92
+ * if (error) return <Error message={error.message} />;
93
+ *
94
+ * return <div>{data}</div>;
95
+ * }
96
+ * ```
97
+ */
98
+ export function useCustomHook(
99
+ param1: string,
100
+ options: UseCustomHookOptions = {}
101
+ ): UseCustomHookResult {
102
+ // ========================================================================
103
+ // OPTIONS
104
+ // ========================================================================
105
+
106
+ const {
107
+ enabled = DEFAULT_OPTIONS.enabled,
108
+ onSuccess = DEFAULT_OPTIONS.onSuccess,
109
+ onError = DEFAULT_OPTIONS.onError,
110
+ retryCount = DEFAULT_OPTIONS.retryCount,
111
+ } = options;
112
+
113
+ // ========================================================================
114
+ // STATE
115
+ // ========================================================================
116
+
117
+ const [data, setData] = useState<string | null>(null);
118
+ const [isLoading, setIsLoading] = useState<boolean>(false);
119
+ const [error, setError] = useState<Error | null>(null);
120
+
121
+ // ========================================================================
122
+ // REFS
123
+ // ========================================================================
124
+
125
+ // Use refs for values that shouldn't trigger re-renders
126
+ const retryCountRef = useRef(0);
127
+ const mountedRef = useRef(true);
128
+
129
+ // ========================================================================
130
+ // CLEANUP
131
+ // ========================================================================
132
+
133
+ useEffect(() => {
134
+ mountedRef.current = true;
135
+
136
+ return () => {
137
+ mountedRef.current = false;
138
+ };
139
+ }, []);
140
+
141
+ // ========================================================================
142
+ // FETCH LOGIC
143
+ // ========================================================================
144
+
145
+ const fetchData = useCallback(async () => {
146
+ if (!enabled) return;
147
+
148
+ setIsLoading(true);
149
+ setError(null);
150
+
151
+ try {
152
+ // Simulate async operation
153
+ const result = await new Promise<string>((resolve, reject) => {
154
+ setTimeout(() => {
155
+ if (Math.random() > 0.8) {
156
+ reject(new Error('Random error'));
157
+ } else {
158
+ resolve(`Data for ${param1}`);
159
+ }
160
+ }, 1000);
161
+ });
162
+
163
+ // Only update state if component is still mounted
164
+ if (mountedRef.current) {
165
+ setData(result);
166
+ setIsLoading(false);
167
+ onSuccess(result);
168
+ retryCountRef.current = 0; // Reset retry count on success
169
+ }
170
+ } catch (err) {
171
+ if (mountedRef.current) {
172
+ const error = err instanceof Error ? err : new Error('Unknown error');
173
+
174
+ // Retry logic
175
+ if (retryCountRef.current < retryCount) {
176
+ retryCountRef.current++;
177
+ setTimeout(() => fetchData(), 1000 * retryCountRef.current); // Exponential backoff
178
+ } else {
179
+ setError(error);
180
+ setIsLoading(false);
181
+ onError(error);
182
+ }
183
+ }
184
+ }
185
+ }, [enabled, param1, onSuccess, onError, retryCount]);
186
+
187
+ // ========================================================================
188
+ // EFFECTS
189
+ // ========================================================================
190
+
191
+ useEffect(() => {
192
+ if (enabled) {
193
+ fetchData();
194
+ }
195
+
196
+ // Cleanup function
197
+ return () => {
198
+ // Cancel any pending operations
199
+ };
200
+ }, [enabled, fetchData]);
201
+
202
+ // ========================================================================
203
+ // HANDLERS
204
+ // ========================================================================
205
+
206
+ const refetch = useCallback(() => {
207
+ retryCountRef.current = 0; // Reset retry count
208
+ fetchData();
209
+ }, [fetchData]);
210
+
211
+ const reset = useCallback(() => {
212
+ setData(null);
213
+ setError(null);
214
+ setIsLoading(false);
215
+ retryCountRef.current = 0;
216
+ }, []);
217
+
218
+ // ========================================================================
219
+ // RETURN
220
+ // ========================================================================
221
+
222
+ return {
223
+ data,
224
+ isLoading,
225
+ error,
226
+ refetch,
227
+ reset,
228
+ };
229
+ }
230
+
231
+ // ============================================================================
232
+ // HELPER HOOKS (Optional)
233
+ // ============================================================================
234
+
235
+ /**
236
+ * useDebounce - Debounce a value
237
+ *
238
+ * Useful for search inputs, window resize handlers, etc.
239
+ *
240
+ * @example
241
+ * ```tsx
242
+ * const [searchTerm, setSearchTerm] = useState('');
243
+ * const debouncedSearchTerm = useDebounce(searchTerm, 500);
244
+ *
245
+ * useEffect(() => {
246
+ * // API call with debounced value
247
+ * searchAPI(debouncedSearchTerm);
248
+ * }, [debouncedSearchTerm]);
249
+ * ```
250
+ */
251
+ export function useDebounce<T>(value: T, delay: number): T {
252
+ const [debouncedValue, setDebouncedValue] = useState<T>(value);
253
+
254
+ useEffect(() => {
255
+ const handler = setTimeout(() => {
256
+ setDebouncedValue(value);
257
+ }, delay);
258
+
259
+ return () => {
260
+ clearTimeout(handler);
261
+ };
262
+ }, [value, delay]);
263
+
264
+ return debouncedValue;
265
+ }
266
+
267
+ /**
268
+ * useLocalStorage - Sync state with localStorage
269
+ *
270
+ * @example
271
+ * ```tsx
272
+ * const [theme, setTheme] = useLocalStorage('theme', 'light');
273
+ * ```
274
+ */
275
+ export function useLocalStorage<T>(
276
+ key: string,
277
+ initialValue: T
278
+ ): [T, (value: T | ((val: T) => T)) => void] {
279
+ const [storedValue, setStoredValue] = useState<T>(() => {
280
+ try {
281
+ const item = window.localStorage.getItem(key);
282
+ return item ? JSON.parse(item) : initialValue;
283
+ } catch (error) {
284
+ console.error(`Error reading localStorage key "${key}":`, error);
285
+ return initialValue;
286
+ }
287
+ });
288
+
289
+ const setValue = useCallback(
290
+ (value: T | ((val: T) => T)) => {
291
+ try {
292
+ const valueToStore =
293
+ value instanceof Function ? value(storedValue) : value;
294
+
295
+ setStoredValue(valueToStore);
296
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
297
+ } catch (error) {
298
+ console.error(`Error setting localStorage key "${key}":`, error);
299
+ }
300
+ },
301
+ [key, storedValue]
302
+ );
303
+
304
+ return [storedValue, setValue];
305
+ }
306
+
307
+ // ============================================================================
308
+ // EXPORTS
309
+ // ============================================================================
310
+
311
+ export default useCustomHook;
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Next.js App Router Page Template
3
+ *
4
+ * This template demonstrates best practices for creating pages
5
+ * in Next.js 14+ App Router with Server Components.
6
+ *
7
+ * Key Features:
8
+ * - Server Component by default (no 'use client' needed)
9
+ * - SEO metadata generation
10
+ * - Suspense boundaries for streaming
11
+ * - Error handling
12
+ * - TypeScript types
13
+ */
14
+
15
+ import { Metadata } from 'next';
16
+ import { Suspense } from 'react';
17
+ import { notFound } from 'next/navigation';
18
+
19
+ // Components
20
+ import { PageHeader } from '@/components/organisms/PageHeader';
21
+ import { DataTable } from '@/components/organisms/DataTable';
22
+ import { Skeleton } from '@/components/atoms/Skeleton';
23
+
24
+ // ============================================================================
25
+ // TYPES
26
+ // ============================================================================
27
+
28
+ interface PageProps {
29
+ params: {
30
+ id: string;
31
+ };
32
+ searchParams: {
33
+ page?: string;
34
+ sort?: string;
35
+ };
36
+ }
37
+
38
+ // ============================================================================
39
+ // METADATA (SEO)
40
+ // ============================================================================
41
+
42
+ /**
43
+ * Generate static metadata for SEO
44
+ *
45
+ * This function runs on the server and generates metadata
46
+ * for search engines and social media.
47
+ */
48
+ export async function generateMetadata({
49
+ params,
50
+ }: PageProps): Promise<Metadata> {
51
+ // Fetch data needed for metadata
52
+ const data = await fetchData(params.id);
53
+
54
+ if (!data) {
55
+ return {
56
+ title: 'Not Found',
57
+ };
58
+ }
59
+
60
+ return {
61
+ title: `${data.title} | Your App Name`,
62
+ description: data.description,
63
+ openGraph: {
64
+ title: data.title,
65
+ description: data.description,
66
+ images: [data.imageUrl],
67
+ },
68
+ twitter: {
69
+ card: 'summary_large_image',
70
+ title: data.title,
71
+ description: data.description,
72
+ images: [data.imageUrl],
73
+ },
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Optional: Generate static paths for Static Site Generation (SSG)
79
+ *
80
+ * Uncomment this function if you want to pre-render pages at build time.
81
+ */
82
+ // export async function generateStaticParams() {
83
+ // const items = await fetchAllItems();
84
+ //
85
+ // return items.map((item) => ({
86
+ // id: item.id,
87
+ // }));
88
+ // }
89
+
90
+ // ============================================================================
91
+ // DATA FETCHING
92
+ // ============================================================================
93
+
94
+ /**
95
+ * Fetch data on the server
96
+ *
97
+ * This runs on the server, so you can safely access databases,
98
+ * private APIs, etc.
99
+ */
100
+ async function fetchData(id: string) {
101
+ const response = await fetch(`https://api.example.com/items/${id}`, {
102
+ next: {
103
+ revalidate: 3600, // ISR: Revalidate every hour
104
+ // OR use 'force-cache' for static generation
105
+ // OR use 'no-store' for dynamic rendering
106
+ },
107
+ });
108
+
109
+ if (!response.ok) {
110
+ return null;
111
+ }
112
+
113
+ return response.json();
114
+ }
115
+
116
+ async function fetchRelatedData(filters: { page: number; sort: string }) {
117
+ const response = await fetch(
118
+ `https://api.example.com/related?page=${filters.page}&sort=${filters.sort}`,
119
+ {
120
+ next: { revalidate: 60 }, // Revalidate every minute
121
+ }
122
+ );
123
+
124
+ return response.json();
125
+ }
126
+
127
+ // ============================================================================
128
+ // PAGE COMPONENT
129
+ // ============================================================================
130
+
131
+ /**
132
+ * Page Component (Server Component by default)
133
+ *
134
+ * Server Components:
135
+ * - Run on the server only
136
+ * - Can access backend resources directly
137
+ * - Don't add JavaScript to the client bundle
138
+ * - Can't use hooks like useState, useEffect
139
+ * - Can't add event handlers
140
+ */
141
+ export default async function Page({ params, searchParams }: PageProps) {
142
+ // ========================================================================
143
+ // DATA FETCHING (Server-side)
144
+ // ========================================================================
145
+
146
+ // Parse search params
147
+ const page = searchParams.page ? parseInt(searchParams.page) : 1;
148
+ const sort = searchParams.sort || 'desc';
149
+
150
+ // Fetch data in parallel for performance
151
+ const [mainData, relatedData] = await Promise.all([
152
+ fetchData(params.id),
153
+ fetchRelatedData({ page, sort }),
154
+ ]);
155
+
156
+ // Handle not found
157
+ if (!mainData) {
158
+ notFound(); // Renders app/not-found.tsx
159
+ }
160
+
161
+ // ========================================================================
162
+ // RENDER
163
+ // ========================================================================
164
+
165
+ return (
166
+ <div className="container mx-auto px-4 py-8">
167
+ {/* Page Header */}
168
+ <PageHeader
169
+ title={mainData.title}
170
+ description={mainData.description}
171
+ breadcrumbs={[
172
+ { label: 'Home', href: '/' },
173
+ { label: 'Items', href: '/items' },
174
+ { label: mainData.title, href: `/items/${params.id}` },
175
+ ]}
176
+ />
177
+
178
+ {/* Main Content */}
179
+ <section className="mt-8">
180
+ <h2 className="text-2xl font-bold">Details</h2>
181
+ <div className="mt-4 grid grid-cols-1 gap-6 md:grid-cols-2">
182
+ <div>
183
+ <p className="text-gray-600">ID: {mainData.id}</p>
184
+ <p className="text-gray-600">Created: {mainData.createdAt}</p>
185
+ </div>
186
+ </div>
187
+ </section>
188
+
189
+ {/* Related Data with Suspense */}
190
+ <section className="mt-12">
191
+ <h2 className="text-2xl font-bold">Related Items</h2>
192
+ <Suspense fallback={<Skeleton className="mt-4 h-96" />}>
193
+ <DataTable
194
+ data={relatedData.items}
195
+ columns={['id', 'name', 'status']}
196
+ pagination={{
197
+ currentPage: page,
198
+ totalPages: relatedData.totalPages,
199
+ }}
200
+ />
201
+ </Suspense>
202
+ </section>
203
+ </div>
204
+ );
205
+ }
206
+
207
+ // ============================================================================
208
+ // CLIENT COMPONENT EXAMPLE (if needed)
209
+ // ============================================================================
210
+
211
+ /**
212
+ * If you need interactivity, create a separate Client Component:
213
+ *
214
+ * 'use client';
215
+ *
216
+ * export function InteractiveSection({ initialData }) {
217
+ * const [state, setState] = useState(initialData);
218
+ *
219
+ * return (
220
+ * <div>
221
+ * <button onClick={() => setState(...)}>Click me</button>
222
+ * </div>
223
+ * );
224
+ * }
225
+ *
226
+ * Then use it in the Server Component:
227
+ * <InteractiveSection initialData={mainData} />
228
+ */