Status: Draft

Depends on Framework Spec 28 for the modulesDirs config key and scanner changes. Everything in CLI Spec 18 not contradicted here carries over unchanged.

What's dropped from Spec 18

RemovedReplacement / reason
--type frontend | backend | fullstackDeleted. Every app is full-stack by default.
_backend/ template overlayDeleted. API-only work is an api/ module inside a full-stack app.
Monorepo gated on type=fullstackMonorepo is now asked unconditionally for all projects.
Patties UI gated on type ∈ {frontend, fullstack}Patties UI is always offered — all apps can have UI.
container excluded from non-fullstackAll deploy targets available to every app.
{{type}} template variableRemoved from templating pass.
Flat app/routes/ in default templateReplaced by modular monolith layout.

Warning

Passing --type is now a hard error with a clear message: "--type was removed; every patties app is full-stack by default."

Updated interactive flow

Four prompts instead of five. The project-type prompt and its sub-gates are gone.

  • 1. Project namePositional arg or prompt. Default my-patties-app. Validation: /^[a-z0-9][a-z0-9_-]*$/.
  • 2. Coding agent"Which coding agent are you using?"Claude (default) / Codex / old school. Flag: --agent claude|codex|none.
  • 3. Patties UI"Do you want a styled UI? (Patties UI)"Yes (default) / No. Flag: --ui / --no-ui. Always asked — not gated.
  • 4. Monorepo"Do you want a Bun workspace structure (multiple apps)?"No (default) / Yes. Flag: --monorepo / --no-monorepo. Always asked.
  • 5. Deploy target"Where will you deploy?"bun (default) / worker/edge / container/docker. Flag: --target bun|edge|container. Edge shows optional deploy-plugin sub-prompt.

The --yes profile

agent=claude, ui=yes, monorepo=no, target=bun. Deterministic, no prompts.

New scaffold template structure

Replaces the flat templates/default/app/ layout. Demonstrates two modules out of the box.

Directory tree

templates/default/
├── app/
│   ├── modules/
│   │   ├── home/
│   │   │   ├── routes/
│   │   │   │   └── index.tsx        # GET / — demo landing page
│   │   │   └── islands/
│   │   │       └── Counter.tsx      # interactive island
│   │   └── api/
│   │       └── routes/
│   │           └── api/
│   │               └── health.ts    # GET /api/health → { ok: true }
│   ├── _shared/
│   │   └── .gitkeep
│   └── middleware.ts
├── patties.config.ts
├── tsconfig.json
├── package.json
└── README-template.md

Landing page

// app/modules/home/routes/index.tsx
import { Island } from "patties/render"

export default function Home() {
  return (
    <main>
      <h1>{{name}}</h1>
      <Island name="home/Counter" />
    </main>
  )
}
// When --ui yes: imports <Button> and <Card> from stamped Patties UI components.

Health route

// app/modules/api/routes/api/health.ts
import type { Handler } from "patties"

export const GET: Handler = (_, ctx) => ctx.json({ ok: true })
// Demonstrates the API module pattern — no UI needed to test.

patties.config.ts

// patties.config.ts (generated with modulesDirs pre-filled)
import { defineConfig } from "patties/config"

export default defineConfig({
  target: "{{target}}",              // bun | edge
  modulesDirs: ["app/modules"],      // ← always present in scaffold
  server: { port: 3000 },
})

Monorepo (Bun workspace)

No longer gated on project type. When chosen, each app in the workspace is itself a modular monolith.

<name>/
  package.json            // private, "workspaces": ["apps/*", "packages/*"]
  biome.json
  apps/
    <app_name>/
      app/
        modules/          // modular monolith layout per app
          home/
          api/
        middleware.ts
      patties.config.ts   // modulesDirs: ["app/modules"]
      package.json
  packages/               // shared libraries (empty with README)
  <agent overlay>

Note

Bun workspaces only — no Turborepo/Nx. Polyglot (Python/Go) deferred. Prerequisite: framework/26-monorepo-react-resolution must ship before this flag is released (hoisted node_modules can otherwise load two React copies and crash SSR).

Agent overlay updates

The _claude/ overlay gains the new rule file from Spec 28. The /patties-init command is updated to scaffold features as modules.

  • New file.claude/rules/patties-modular-monolith.md — the LLM rules from Spec 28 §9. Ships in all --agent claude scaffolds.
  • /patties-init updateCommand text updated: "When adding a new feature, create app/modules/<domain>/ with the relevant subdirectories. Never add files directly to the top-level app/ unless they are global (middleware.ts) or shared (_shared/)."
  • Codex overlay.codex/rules/patties-patterns.md gets the same modular monolith rules appended.
--agentFiles scaffoldedNew in Spec 21
claude (default) CLAUDE.md, .claude/rules/patties-patterns.md, .claude/rules/patties-modular-monolith.md, .claude/skills/patties/, .claude/commands/patties-init.md patties-modular-monolith.md rule, updated patties-init.md
codex AGENTS.md, .codex/rules/patties-patterns.md Modular monolith rules appended to patterns file
none (old school) No change

Flags (non-interactive)

bunx create-patties [name]
  --agent      claude | codex | none            (default claude)
  --ui | --no-ui                                (default yes)
  --monorepo | --no-monorepo                    (default no)
  --target     bun | edge | container           (default bun)
  --deploy     cloudflare | vercel | deno | netlify | none   (edge only)
  --theme      neutral | slate | stone | zinc   (ui only, default neutral)
  --yes, -y
  --no-install
  --git

# Removed
# --type       REMOVED — hard error with clear message if passed
# --template   still an alias for --agent (spec 09/18 back-compat)

Scaffold behavior (ordered steps)

  1. Resolve options: flags → prompts (TTY) → defaults. Hard error on --type.
  2. Validate name; refuse non-empty target directory.
  3. Copy templates/default/ (modular monolith layout).
  4. Run templating pass: {{name}}, {{target}}, {{app_name}}, {{ui}}. ({{type}} no longer emitted.)
  5. Patch package.json (+ patties-ui when ui=yes) and patties.config.ts (target, modulesDirs).
  6. Apply agent overlay for claude / codex (including new modular monolith rule).
  7. If ui=yes: patties ui init --theme <theme> + stamp starter set (button, card, input, label).
  8. If target=container: emit Dockerfile + .dockerignore.
  9. If monorepo=yes: apply _monorepo/ overlay; move app/ into apps/<app_name>/.
  10. Unless --no-install: run bun install.
  11. Print next-steps output.

Next-steps output (claude, default)

✓ Created my-app  (modular monolith · bun target)

  cd my-app
  bun dev            → http://localhost:3000

Modules live under app/modules/. Want to scaffold a feature?
Open a NEW terminal in this project and run:

  claude --permission-mode plan "/patties-init"

That starts an interactive, plan-mode session that scaffolds domain
modules with you before writing any files.

Tests

  • --yesapp/modules/home/routes/index.tsx and app/modules/api/routes/api/health.ts exist; patties.config.ts contains modulesDirs.
  • --no-ui ⇒ no app/components/ui/; demo page uses plain markup.
  • --monorepoapps/<name>/app/modules/ exists; root package.json has workspaces.
  • --target containerDockerfile present; target: "bun" in config.
  • --agent none ⇒ no .claude/ or .codex/ directories.
  • --agent claude.claude/rules/patties-modular-monolith.md exists.
  • No test references --type. Passing --type exits with non-zero and prints the removal message.
  • Remove existing tests that assert flat app/routes/ / app/islands/ output.
  • CI scaffold-smoke: scaffold → bun installbun dev → curl / and /api/health → both 200.

Acceptance criteria

  • bunx create-patties has no project-type prompt. Every scaffolded app uses the modular monolith layout.
  • / and /api/health both return 200 from a freshly scaffolded app after bun install && bun dev.
  • patties.config.ts in every scaffold includes modulesDirs: ["app/modules"].
  • --ui yes yields components under the initial app's module directory, with the stamped Patties UI starter set.
  • --monorepo yes wraps the initial app inside apps/<name>/ with a Bun workspace root.
  • --agent claude scaffolds include .claude/rules/patties-modular-monolith.md.
  • Passing --type exits with a clear removal message and non-zero exit code.