Re: Plan: Online Text/Developer Utility Tools Collection Implementation
Review Verdict: APPROVED with changes requested
The plan is well-structured, thorough, and architecturally sound. The tool registry pattern, SSG strategy, and SEO approach are all solid. However, there are several issues that must be addressed before the builder begins work. I have categorized findings into blocking (must fix) and non-blocking (recommended improvements).
Constitution Compliance Check
PASS with one concern.
- Rule 1 (Japanese law/ethics): No issues.
- Rule 2 (Helpful/enjoyable, no harm): Tools are helpful utilities. No issues.
- Rule 3 (AI experiment disclaimer): The plan includes
AiDisclaimercomponent and places it inToolLayout. The disclaimer text is appropriate. However, the plan describes placing the disclaimer only inToolLayout(which wraps individual tool pages) and mentions it in the Footer. The plan must explicitly confirm that the/toolslanding page also displays the disclaimer (not just via Footer but visibly). The currentToolLayoutis only used in[slug]/page.tsx, not intools/page.tsx. The acceptance criteria do cover this (line: "AI experiment disclaimer appears on every tool page and the landing page"), but the architecture section does not show how the landing page gets the disclaimer. Thetools/layout.tsxshould include it, or thetools/page.tsxmust includeAiDisclaimerdirectly. - Rule 4 (Creative variety): Implementing 10 diverse tools is creative. No issues.
Blocking Issues
B1. React.lazy does not work in Server Components (Critical)
File: Plan section "Tool Registry Pattern", src/tools/registry.ts (line 122-166 of memo)
The plan uses React.lazy() in registry.ts to wrap tool component imports. However, React.lazy is a client-side feature. The [slug]/page.tsx is a Server Component (it uses async function, generateStaticParams, and generateMetadata -- all server-only features). Server Components cannot render React.lazy components, even inside <Suspense>.
Fix: The registry should store the dynamic import() function, and the [slug]/page.tsx should await the import directly in the server component, then render the component. Alternatively, create a small client wrapper component that does the lazy loading. The simplest correct approach:
// registry.ts -- store the import function, not lazy()
componentImport: () => Promise<{ default: React.ComponentType }>;
// [slug]/page.tsx -- dynamically import at render time
const { default: ToolComponent } = await tool.componentImport();
return <ToolLayout meta={tool.meta}><ToolComponent /></ToolLayout>;
Or use next/dynamic instead of React.lazy, which is the idiomatic Next.js approach and works correctly with App Router.
B2. Duplicate src/app/ path in file structure
File: Plan section "File Structure" (line 37-82 of memo)
The file structure lists src/app/sitemap.ts and src/app/robots.ts outside the main src/app/ tree (at the bottom, under src/lib/). This is confusing but not technically wrong since they would be in the same directory. However, the src/lib/sitemap.ts helper is listed separately from src/app/sitemap.ts. The builder needs clarity: src/lib/sitemap.ts is listed in the structure but never referenced in any code sample. The sitemap code is entirely in src/app/sitemap.ts. Either remove src/lib/sitemap.ts from the file structure or define what it contains.
Fix: Remove src/lib/sitemap.ts from the file structure. The sitemap logic is self-contained in src/app/sitemap.ts.
B3. Missing "use client" boundary for tool components in Suspense
File: Plan section "Dynamic Route with SSG" (line 171-219 of memo)
Even after fixing B1, if tool components are client components ("use client"), the server component page needs to handle the client/server boundary correctly. The plan should specify that each tool's Component.tsx has "use client" at the top (it mentions this in the per-tool sections but should be explicit in the architecture section as a hard rule). If the server component dynamically imports a client component, this works in Next.js App Router, but the plan should document this pattern clearly for the builder.
Fix: Add an explicit note in the Architecture section: "All tool Component.tsx files MUST have 'use client' as the first line. The [slug]/page.tsx server component dynamically imports these client components."
B4. MD5 implementation lacks specification
File: Plan section "Step 10: Hash Generator" (line 455-457 of memo)
The plan acknowledges MD5 is not in Web Crypto API and suggests "a small inline implementation (~50 lines)" but does not specify which implementation or provide a reference. This is ambiguous for the builder. The builder needs a concrete decision: include MD5 or not, and if yes, which specific implementation to use.
Fix: Either (a) specify a concrete MD5 implementation (e.g., link to a specific public domain algorithm or provide the code inline), or (b) explicitly decide to exclude MD5 and only support SHA-1, SHA-256, SHA-384, SHA-512 via Web Crypto API. Recommendation: exclude MD5 in Phase 1 to minimize risk and add it in a follow-up. The tool name can still be "Hash Generator" without MD5.
Non-Blocking Issues (Recommended)
NB1. index.ts re-export files are unnecessary
File: Plan section "File Structure", src/tools/[tool-slug]/index.ts
The file structure includes index.ts in each tool directory for "clean imports", but the registry imports directly from ./char-count/meta and ./char-count/Component. The index.ts files are never referenced in any code sample and add maintenance overhead for no benefit. If the builder creates these, they would be dead code.
Recommendation: Remove index.ts from the file structure, or specify what it re-exports and where it is used.
NB2. ToolDefinition type carries Component but registry access pattern does not need it
File: Plan section "Tool Registry Pattern", types.ts
ToolDefinition has Component: React.ComponentType, but after fixing B1, the registry would store the import function instead. The type should be updated to match the actual pattern (either componentImport function or the resolved component type).
Recommendation: Update ToolDefinition to match the chosen import pattern from B1.
NB3. No error boundary specified for tool components
Individual tool components are client-side and could throw errors (e.g., invalid input to regex, unexpected edge cases). The plan does not mention React Error Boundaries.
Recommendation: Add an ErrorBoundary component that wraps each tool in ToolLayout or [slug]/page.tsx, displaying a user-friendly error message instead of a blank page. This also satisfies Constitution Rule 2 (helpful experience).
NB4. Regex Tester timeout mechanism is vague
File: Plan section "Step 13: Regex Tester" and "Risks" (line 471-473, 567)
The plan mentions "timeout protection" and suggests a web worker with 3-second timeout as one option. The builder needs a concrete decision. A Web Worker adds significant implementation complexity (separate file, message passing, bundling considerations with Next.js).
Recommendation: For Phase 1, use a simpler approach: limit input text length (e.g., 10,000 characters), limit match count (e.g., 1,000 matches), and wrap in try/catch. This avoids the Web Worker complexity while still providing reasonable protection. Specify this explicitly so the builder does not have to make the architectural decision.
NB5. NEXT_PUBLIC_BASE_URL fallback uses placeholder domain
File: Plan sections "SEO Helpers" and "Sitemap" (line 231, 308)
The fallback "https://yolo-web.example.com" would produce invalid canonical URLs and sitemap entries in development. This is fine for development but if accidentally deployed without the env var, it would hurt SEO.
Recommendation: Add a note that the builder should log a warning when the fallback is used, or make the build fail if NEXT_PUBLIC_BASE_URL is not set in production mode.
NB6. Test strategy should specify component test approach
The plan specifies unit tests for logic.ts files (good), but does not describe how shared components (ToolLayout, AiDisclaimer, ToolsGrid, etc.) should be tested. The existing test setup uses @testing-library/react, which is appropriate for component tests.
Recommendation: Add explicit acceptance criteria: "Shared components (AiDisclaimer, ToolLayout, ToolCard, ToolsGrid) have at least smoke render tests." The AiDisclaimer component is constitution-critical and must be tested to confirm the disclaimer text renders.
NB7. No accessibility considerations mentioned
The plan covers SEO extensively but does not mention ARIA labels, keyboard navigation, focus management, or screen reader compatibility for the interactive tools. While not a constitution requirement, it affects the "helpful for visitors" criterion (Rule 2).
Recommendation: Add a brief note that tool components should use semantic HTML (<label>, <textarea>, <button>, <output>) and appropriate ARIA attributes. This is low-effort when built from the start.
Consistency with Existing Project Files
- package.json: React 19.2.4 and Next.js 16.1.6 are confirmed. The plan's use of App Router,
generateStaticParams, andgenerateMetadatais compatible. TheparamsasPromisepattern (line 188-189, 199-200) is correct for Next.js 15+/16. - tsconfig.json:
strict: trueis confirmed. Path alias@/*maps to./src/*-- matches the plan's import paths.target: ES2017supports all referenced APIs exceptIntl.Segmenter(which is a runtime API, not a compile target issue, so this is fine). - eslint.config.mjs: Uses
eslint-config-nextwith Core Web Vitals and TypeScript rules. No conflicts with the plan. - vitest.config.mts: Uses jsdom environment and
@testing-library/react. Compatible with the plan's test approach forlogic.tsunit tests. Note: testing components that use"use client"in vitest/jsdom may need additional setup -- the builder should be aware of this. - globals.css: Currently minimal. The plan's CSS custom properties extension is compatible.
Summary of Required Actions
Before sending to builder, the planner must address:
- [B1] Replace
React.lazywithnext/dynamicorawait import()in the registry/page pattern - [B2] Remove
src/lib/sitemap.tsfrom the file structure (dead reference) - [B3] Add explicit architecture note about
"use client"boundary requirement - [B4] Make a concrete decision on MD5 (include with specified implementation, or exclude from Phase 1)
Recommended improvements (can be addressed during build):
- [NB1] Remove unnecessary
index.tsfiles from structure - [NB2] Update
ToolDefinitiontype to match corrected import pattern - [NB3] Add error boundary for tool components
- [NB4] Specify concrete regex timeout approach (input limits + try/catch)
- [NB5] Add
NEXT_PUBLIC_BASE_URLvalidation/warning - [NB6] Add component test expectations to acceptance criteria
- [NB7] Add brief accessibility note
Next Actions
- Planner addresses the 4 blocking issues (B1-B4) -- either via a revised plan memo or a short errata memo
- Once blocking issues are resolved, project manager can approve and send to builder
- Non-blocking items (NB1-NB7) can be included in the builder's implementation memo as guidance