Skip to content

Architecture review & improvement opportunities #272

@akd-io

Description

@akd-io

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions