-
Notifications
You must be signed in to change notification settings - Fork 29
Architecture review & improvement opportunities #272
Description
Architecture Review
Review by Claude Opus 4.6 after analyzing the full codebase.
Analysis of the current codebase architecture with improvement opportunities, roughly ranked by impact.
1. Slots hardcoded to Pages Router
The slot system is tightly coupled to pages/_app.tsx, pages/_document.tsx, and next.config.js. No App Router support (app/layout.tsx, app/page.tsx), no next.config.ts support.
Fix: Abstract slot targets. Different template sets selected by a --router flag.
2. Website and CLI share no code
The website duplicates technology names, flag names, validation rules, and category groupings. Both are TypeScript in the same monorepo but share zero code.
Fix: Extract a shared package with technology metadata, flag definitions, and validation rules.
3. filterPlugins() called repeatedly with no caching
filterPlugins(inputs) re-evaluates every plugin's active property ~15+ times per run. Active plugins don't change mid-execution.
Fix: Evaluate once, pass the filtered list through context.
4. No shared execution context
Every step receives only { args, flags } but frequently needs filtered plugins, working directory, and package manager utilities. No SetupContext object exists.
Fix: Create a SetupContext with resolved plugins, working directory, package manager. Pass through steps.
5. The "god plugin" -- createNextStackPlugin
create-next-stack.ts owns framework-level orchestration concerns (install deps, write files, format, commit). These are pipeline stages, not a plugin. Creates circular dependency with setup.ts.
Fix: Separate orchestration steps from the plugin system.
6. No plugin dependency graph -- validation is ad-hoc
Inter-plugin constraints are scattered across create-next-stack-types.ts (imperative if/throw) and website form (duplicate validation). Neither derived from plugins.
Fix: Let plugins declare constraints (requires, conflicts). Derive validation from declarations.
7. No unit tests for generated output
Only E2E tests verify generated files (20 min per run). Zero unit tests for generateApp(), generateDocument(), generateNextConfig(), or slot composition.
Fix: Unit-test generate functions with mocked inputs. Parse output with TS compiler for validity.
8. Global mutable state
process.chdir() mutates global state. commandInstance is a module-level singleton. Makes code untestable in isolation.
Fix: Pass working directory through context. Replace singletons with dependency injection.
9. Sort order arrays are a maintenance trap
Three manually-maintained order arrays (stepsOrder, scriptsSortOrder, technologiesSortOrder). Adding a plugin means touching 3+ files.
Fix: Let plugins declare ordering constraints. Topological sort over constraints.
10. Pinned, stale dependency versions
Being addressed in #271.