↑ ↓ to move · Enter to open · Esc to closeTap a result

Blueprints

Pick the shape. The harness enforces it.

Each blueprint is a YAML file with modules, depends_on, forbidden_imports, a package map and mandatory trade-offs. Adding an architecture touches no skill, agent or prompt, and a CI job checks that on every push.

  • hexagonal

    Domain at the center, ports as interfaces, input and output adapters at the edges, one Maven module per adapter.

    More than one input or output channel: REST, messaging, batch.

  • hexagonal-single-module

    The same ports and adapters as packages of one Maven module. Adapters may not import each other.

    Several channels, without one POM per adapter.

  • clean-architecture-multi-module

    Domain, application and infrastructure as three Maven modules; the build enforces the dependency rule.

    Business rules that must stay isolated from infrastructure.

  • clean-architecture-single-module

    The same separation in one Maven module; modules become packages. bank-app uses it.

    Three POMs would be overhead nobody amortizes.

  • layered

    controller → service → repository, in the vocabulary most Spring Boot tutorials use.

    The team already speaks it, and port/adapter naming would be pure translation.

  • onion

    Palermo's own terms: Application Core and Gateway, one Maven module per ring.

    The team prefers them over hexagonal or clean terms.

  • onion-single-module

    Palermo's rings as packages of one Maven module. Persistence and presentation stay strangers.

    Application Core and Gateway, without one POM per ring.

  • vertical-slice

    Code grouped by feature: Command/Query, Handler, Endpoint and Response together.

    Features diverge more than they overlap.

  • modular-monolith

    Several bounded contexts in one deployable, with a boundary stronger than a polite request.

    Contexts that do not yet justify separate deployables.

  • custom-template

    Your own architecture, in YAML.

    None of the nine fits.

§ one declaration, three effects

forbidden_imports

# blueprints/hexagonal.yaml
modules:
  - id: domain
    depends_on: []
    forbidden_imports:
      - "org.springframework.."
      - "jakarta.persistence.."
      - "jakarta.validation.."
  - id: application
    depends_on: [domain, commons]
    forbidden_imports:
      - "jakarta.persistence.."
      - "org.springframework.web.."
  1. domain/CLAUDE.mdthe model knows
  2. .claude/forbidden-imports.txtthe check hook blocks the write, exit 2
  3. pom.xml · depends_onthe compiler refuses, in multi-module layouts

Norm globs (paths) are rewritten from the package map at generation time, so a norm loads only for the packages this blueprint actually has.

§ what CI checks

Validated as data, then generated and built

On every push, validate.yml runs these checks over the blueprints:

  • Every blueprint exports the same tree twice, with no dead citation.
  • Every templates.<role> resolves to a real file.
  • A new blueprint file changes no skill, agent or prompt.
  • hexagonal-single-module keeps its adapters apart, and its matrix of ten packages is complete.

validate.yml never builds a project, so blueprints.yml does. For each blueprint a change can affect, it generates a skeleton from the YAML, with no language model, and builds it with Maven and with Gradle: nine blueprints, two tools, 18 jobs.

  • The skeleton is the Initializr's starter, shaped by the blueprint: a reactor from modules[] and depends_on when multi-module, one package-info.java per role of the package map.
  • ArchHook.jar boundary-map and export write the project's .claude/, then ./mvnw verify or ./gradlew build runs, and doctor gate must be green.
  • Then one class per boundary rule imports what the rule forbids: doctor gate must fail naming every such file, and check must block one of them with exit 2.
  • It runs only when a blueprint, project-bootstrap, the hook or the schema changes. A change under one blueprint generates only that one. It is not a required check.

In the three -single-module blueprints the compiler does not enforce the boundary. The check hook on each edit, doctor gate in the project's CI and ArchUnit do. The skeleton is not the full generation: the test writes its own minimal build files, so the POMs project-bootstrap adapts from templates/pom.*.xml.example, the feature dependencies and the agent's own steps are not proven, and nothing here claims an end-to-end run of /init-project.