本文へ移動
cccskills
無料GitHub で公開

crouton-generation-reference

Verified lookup pack for crouton's schema→CRUD generation domain — the fieldsFile JSON format, the complete field-type catalog with aliases, the naming contract, the exact artifact list one generate run produces, the seed/default-layout pipeline, dialect defaults, and rollback semantics. Use when writing or reviewing a collection schema, when asking "what field types exist / what does `crouton config` actually generate / where did this file name come from / why did I get a pg schema", when a generated file's name or path doesn't match the docs, or when removing/regenerating a collection. Trigger phrases — "what field types are supported", "schema JSON format", "what files does crouton generate", "naming convention for collections", "rollback a collection", "dialect default". The generation WORKFLOW (steps + sign-off gates) lives in the `crouton` skill — this is the reference it doesn't carry.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md23.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Crouton Generation Reference

The drift-corrected lookup tables for the generation domain: what a schema file is, what one generate run produces, and exactly how everything is named. Every command/path/line here was verified against the repo on 2026-07-02; where the shipped docs are wrong, this file says so explicitly.

When to use / when NOT to use

You needGo to
The generate workflow (gather fields → config → schema-review gate → generate → post-gen steps), MCP tool workflow, worked examplescrouton skill (.claude/skills/crouton.md) — defer to it; this file is the lookup pack under it
Human sign-off on a data model before generatingschema-review skill (#314)
Migration mechanics, the .nuxt/hub/db/schema.mjs build-first gotcha (#523), package-owned tablesdb-migrations skill
Why the system is shaped this way (two-halves rule, invariants, registries)sibling crouton-architecture-contract
Layout engine theory (LayoutTree, viability math, placer internals)sibling crouton-layout-reference — §6 here covers only the generate→seed handoff
Booting/seeding a running app, inspecting the DBsibling crouton-run-and-operate
Field-meta long-form descriptions, pagination/FK-filter details, crouton add/init/db-pullpackages/crouton-cli/CLAUDE.md (owns them; §9 lists its known-stale spots)

Vocabulary (crouton terms, defined once)

  • Collection — one CRUD entity (e.g. products): a generated, self-contained nested Nuxt layer with form, list, composable, team-scoped API, Drizzle schema. Always team-scoped (every row has teamId).
  • Layer — here: the domain folder layers/<layer>/ grouping collections (e.g. shop). (Distinct from Nuxt-layer-as-package; see crouton-architecture-contract.)
  • fieldsFile — the JSON file defining a collection's fields (§1). The input to everything.
  • crouton.config.js — unified config at the app root: collections + targets + dialect for the CLI, features flags for the @fyit/crouton module. Full key reference: packages/crouton-cli/CLAUDE.md "Config File Format".
  • Manifest (crouton.manifest.ts) — per-package declaration of field types, reserved names, detection patterns. The source of truth for field types (§2).
  • The CLI — packages/crouton-cli, bins crouton (= crouton-generate) and crouton-seed (verified package.json bin map). In an app with @fyit/crouton-cli as devDep: pnpm exec crouton <cmd>.

1. fieldsFile JSON format

Shape (each top-level key is a field name):

{
  "id":         { "type": "string",  "meta": { "primaryKey": true } },
  "name":       { "type": "string",  "meta": { "required": true, "maxLength": 255, "translatable": true } },
  "price":      { "type": "decimal", "meta": { "precision": 10, "scale": 2 } },
  "categoryId": { "type": "string",  "refTarget": "categories" },
  "authorId":   { "type": "string",  "refTarget": "users", "refScope": "adapter" }
}

Per-field keys: type (§2), meta (below), refTarget (name of the referenced collection — generates a CroutonFormReferenceSelect in the form, an FK query-param filter on the list endpoint, and cache auto-refresh), refScope ('adapter'/'external' for refs outside the generated layers, e.g. users; handled in lib/generators/{form-component,list-component,database-queries}.ts).

meta keys are owned by packages/crouton-cli/CLAUDE.md "Field Meta Properties" — read the full catalog there. What that doc doesn't say (verified behaviour):

meta keyNon-obvious verified behaviour
nullable.nullish() instead of .optional() in Zod; json and date types get .nullish() automatically (generate-collection.ts)
translatablevalue lives in the collection's translations JSON column; root column is a cache/fallback — see trap below
componentbesides overriding the form control, it triggers that package's generator contribution via manifest detects, even without a feature flag

Trap — translatable fields must be required: false. The real value lives in translations.{locale}.field; a NOT NULL root column fails inserts that only populate translations. (crouton-cli/CLAUDE.md "Why this matters".)

Three ways a field becomes translatable (merged, in this priority — verified generate-collection.ts:678-735): field-level meta.translatable: true → collection-level translatable: true in config (auto-detects common names: name, title, description, label, content, … on string/text fields) → config-level translations.collections.{plural}: [fields].

Never declare (auto-generated on every collection): id, teamId, owner, createdAt, updatedAt, createdBy, updatedBy; hierarchy adds parentId, path, depth, order. Reserved field names additionally include optimisticId, optimisticAction (verified packages/crouton-core/crouton.manifest.ts:27-37). Reserved collection names: api, server, app, pages, components, composables, layouts, middleware, plugins, assets, public, node_modules (same file, :39-43).

2. Field-type catalog

Source of truth is per-package manifests, not any doc table. getTypeMapping() in packages/crouton-cli/lib/utils/manifest-loader.ts (~:297) builds the map from every crouton.manifest.ts; core's types live in packages/crouton-core/crouton.manifest.ts:12-25. The tables in crouton-cli/CLAUDE.md and crouton-mcp/CLAUDE.md are copies (the MCP one is explicitly a fallback used only when manifest loading fails — packages/crouton-mcp/src/utils/field-types.ts).

Verified from the core manifest + the SQLite branch of lib/generators/database-schema.ts:89-100:

TypeSQLite column (actual)ZodTSDefaultForm componentAliases
stringtext()z.string()string''UInput
texttext()z.string()string''UTextarea
numberinteger()z.number()number0UInputNumberinteger
decimalreal()z.number()number0UInputNumber
booleaninteger({ mode: 'boolean' })z.boolean()booleanfalseUCheckbox
dateinteger({ mode: 'timestamp' })z.date()Date | nullnullCroutonCalendardatetime
jsonjsonColumn()z.record(z.string(), z.any())Record<string, any>{}UTextarea
repeaterjsonColumn()z.array(z.any()) (typed when meta.properties)any[][]CroutonFormRepeater
arraytext()z.array(z.string())string[][]UTextarea
referencetext()z.string()string''CroutonFormReferenceSelect
imagetext()z.string()string''CroutonImageUpload → assets picker¹
filetext()z.string()string''CroutonImageUpload → assets picker¹

¹ crouton-assets' manifest declares detects: { fieldTypes: ['image','file'], refTargetPatterns: ['asset','file','image','media'] } (verified packages/crouton-assets/crouton.manifest.ts), so its generator contribution swaps in CroutonAssetsPicker (crop for image) whenever those fields appear — no feature flag needed.

Notes:

  • reference exists as a first-class type, but in practice relationships are written as type: "string" + refTarget — the user-facing table in the crouton skill omits reference for that reason.
  • Alias resolution (#285): loadFields resolves aliases to their canonical type before any generator runs (each mapping entry carries canonical — manifest-loader.ts:303-318). History: datetime once leaked through unresolved → a raw <UInput> + a text column. Rules of thumb: number = integer column; decimal = float/real; a string-encoded enum ('0'/'1'/'2') is string, not number.
  • Adding a field type = a manifest change (plus generator branches) — see crouton-cli/CLAUDE.md "Add a new field type".

3. Dialect defaults — split by entry point

Code truth (the docs were corrected to match in the #1073 reshape):

Entry pointDialect defaultWhere
crouton <layer> <collection> (direct generate)sqlitebin/crouton-generate.js
crouton init <name>sqlitebin/crouton-generate.js
crouton configthe config file's dialect; if the config omits it → 'pg'lib/generate-collection.ts (the config subcommand has no --dialect flag at all)

Rule: always write dialect: 'sqlite' explicitly in crouton.config.js (every in-repo app targets D1/SQLite) — the silent pg fallback on the config path is the trap.

4. Naming contract

Everything derives from toCase() (lib/utils/helpers.ts — real English pluralization via the pluralize npm package + scule casing; categories↔category works, naive +s does not apply). Given collection products in layer shop:

ArtifactNameDerivation
Directorylayers/shop/collections/products/layer + lowercase plural
API base/api/teams/[id]/shop-products/{layer}-{plural}
Patch/delete route files[productId].patch.ts, [productId].delete.ts[{singularCamel}Id] — NOT [id] (docs say [id]; code is generate-collection.ts:932-937, fixture confirms [itemId].patch.ts)
ComponentsShopProductsForm, ShopProductsListthe collection's own nuxt.config.ts registers app/components with prefix: 'ShopProducts', global: true
ComposableuseShopProducts (file useShopProducts.ts)use{LayerPascal}{PluralPascal}
Registry key in croutonCollectionsshopProducts (+ import shopProductsConfig){layerCamel}{PluralPascal} (generate-collection.ts:1121-1122; mirrored by compose-layout.ts registryKeyFor())
Drizzle schema exportshopProductssame
DB tableshop_productstoSnakeCase(\${layer}_${plural}`) (database-schema.ts:171; confirmed by a real seed.json's "table": "bookings_locations"`)
Test filesShopProducts.test.ts, ShopProducts.api.test.ts{LayerPascal}{PluralPascal}

System-collection exception: a layer named crouton-* gets API path crouton-<collection-kebab> instead of {layer}-{plural} (generate-collection.ts:882-888) — e.g. layer crouton-events + collectionEvents → /api/teams/[id]/crouton-collection-events/. Its table is toSnakeCase('crouton' + Collection) (database-schema.ts:168).

5. Exact artifact list of one generate run

Verified against writeScaffold (lib/generate-collection.ts:880-1155) and on-disk generated collections (fixtures/minimal/layers/main/collections/items/, pocs/booking-demo/layers/bookings/collections/*/).

Per collection, under layers/{layer}/collections/{plural}/:

app/components/_Form.vue            # NOTE THE UNDERSCORE — see below. Skipped when
                                    #   formComponent is set (config or auto-detected)
app/components/List.vue
app/components/{FieldPascal}/{Input,Select,CardMini}.vue   # one dir per repeater field
app/composables/use{Layer}{Plurals}.ts   # Zod schema + columns + collection config
server/api/teams/[id]/{layer}-{plural}/
    index.get.ts  index.post.ts  [{singular}Id].patch.ts  [{singular}Id].delete.ts
    [{singular}Id]/move.patch.ts + reorder.patch.ts   # hierarchy only
    reorder.patch.ts                                  # sortable (non-hierarchy) only
server/database/schema.ts           # Drizzle (+ translations JSON column when translatable)
server/database/queries.ts          # getAll* with FK-filter + opt-in pagination overloads
server/database/seed.ts             # only with seed flag (drizzle-seed + Faker)
seed.json                           # always, except hierarchy collections (#298) — editable sample rows
{Layer}{Plurals}.test.ts            # Zod schema-smoke (#785) — skipped by --no-tests / tests:false
{Layer}{Plurals}.api.test.ts        # mocked route-handler test (#791), carries // @ts-nocheck — same gate
types.ts   nuxt.config.ts   README.md

The _Form.vue underscore: the actual filename is _Form.vue (generate-collection.ts:912) even though the dry-run output prints Form.vue (:825) and both the crouton skill and crouton-cli/CLAUDE.md draw Form.vue. It still registers as {Layer}{Plurals}Form — the composable's componentName field carries the name (verified fixtures/minimal/.../useMainItems.ts:44: componentName: 'MainItemsForm').

Side effects beyond the collection dir (config-mode run, same file :1091-1152 + runPostGeneration :1165-1293):

SurfaceWhat happens
layers/{layer}/nuxt.config.tscreated/updated to extend the collection
root nuxt.config.ts./layers/{layer} added to extends; enabled feature packages synced in
app/app.config.tscollection upserted into croutonCollections (import + entry)
i18n locale JSONcreated when the collection has translatable fields
server/database/schema/index.tsnamed schema export added per collection (config mode automates the "manual export" step the crouton skill lists)
migrationdrizzle-kit runs directly on the resolved schema graph — no Nuxt build (#1445 WS2). ~2s. On a cold scaffold it soft-defers (↻ Migration deferred … re-run: pnpm db:generate, exit 0) rather than producing it in the same run — #1457. The old npx nuxt db generate 30s-timeout/silent-zero-migrations failure (#523) is retired by design on resolver apps; still possible on an external legacy .nuxt-bundle scaffold (no app in this repo since #1456) → db-migrations skill
CSSTailwind @source directive ensured
.nuxt-adjacent registriestype registry + server/utils/crouton-query-registry.ts (lazy per-collection query lookup)
crouton.layout.json (app root)deterministic default layout (§6)
devtoolsgeneration recorded for the DevTools Generators tab

Real-world caveat: apps generated before #298/#709 (e.g. apps/velo, fixtures/*) lack seed.json-era artifacts at root (crouton.layout.json, query registry) — absence there is history, not a bug. pocs/booking-demo is a current-pipeline example with all of them.

6. Seed + default-layout pipeline (generate → booted app)

Mechanics of crouton-seed (discovery/topo-sort/wrangler transport) are owned by packages/crouton-cli/CLAUDE.md "App Seeding" — current and accurate. What this reference adds, verified from code:

  1. Layout pass (#709) — runPostGeneration → lib/compose-layout.ts writeDefaultLayout() calls composeDefaultLayout from @fyit/crouton-layout/app/utils/layout-compose (a stale comment at the top of compose-layout.ts still says "from crouton-core"; the import at :16 is truth — it moved in #751) and writes crouton.layout.json: { id: 'default', renderer, pattern, viable, tree }. Patterns: calendar-primary | master-detail | form-centric | stacked | empty (verified layout-compose.ts:54). Theory → sibling crouton-layout-reference.
    • Drift hazard (declared in code, compose-layout.ts:22-26): the CLI has no live app.config at generate time, so it hardcodes mirror copies of the block sizing contracts (CORE_BLOCKS/BOOKINGS_BLOCKS). Changing a minWidth/defaultSize in crouton-layout/crouton-bookings app.config must be mirrored here — the hazard and the current values are owned by sibling crouton-layout-reference §6.
  2. Package seed providers — crouton-seed --db <name> [--remote|--dry-run] collects each package's <pkg>/seed provider into idempotent upsert SQL, executed via wrangler d1 execute.
  3. Collection fixtures — each layers/*/collections/*/seed.json ({ table, key, rows } — verified shape in pocs/booking-demo) is upserted with injected system columns + stable seedId(layer, collection, key) ids (lib/seed-app.ts:180-193).
  4. Layout row — collectDefaultLayoutSql (seed-app.ts:213-242) upserts the tree into layout_configs row id default — the row the team layout page loads. NB (code comment): layout_configs.id is a global PK, so this seeds one default layout for the single seeded team only.

Result: a fresh POC boots laid out, not blank. The layout is data (editable in CroutonLayout), never generated .vue.

7. Deterministic vs AI-assisted

Deterministic (no LLM anywhere)AI-assisted (the agent is the intelligence)
All template generation (the 16 generators in lib/generators/ are string templates keyed off the schema)Schema design — the AI writes the fieldsFile; MCP design_schema/init_schema only feed it reference material
Type/alias resolution; Zod/TS/Drizzle mapping (manifest-driven)The human schema-review gate (#314) on top of machine validation
MCP validate_schema (pure structural check), dry_run, rollbackOptional runtime AI features (crouton-ai translate, alt-text) — not part of generation
The default-layout pass — "No LLM" is stated in compose-layout.ts's own header; the LLM /layout pass (#711) is gated and out of scopeLayout iteration via the agent⇄human ticket loop (sanitizer keeps ingest deterministic)
Seeding (SQL assembly, stable ids, topo-sort; Faker field-name heuristics are heuristic, not AI)
Generated tests (samples derived from each field's Zod; no Date.now()/Math.random())

Practical consequence: generation output is reproducible and diff-reviewable; the only judgment calls are the schema itself and any post-hoc layout edits — which is exactly where the sign-off gates sit.

8. Rollback & regeneration semantics

Rollback (crouton rollback <layer> <collection> [--dry-run] [--keep-files] [--force]) — verified lib/rollback-collection.ts:252-300, five steps:

  1. delete layers/{layer}/collections/{plural}/ (skipped by --keep-files)
  2. remove the schema export from server/database/schema/index.ts
  3. remove the croutonCollections entry + import from app.config.ts
  4. remove the collection from the layer root nuxt.config.ts
  5. remove ./layers/{layer} from the root nuxt.config.ts only if no other collections remain in the layer

Also: crouton rollback-bulk --layer=<layer> / --config=<path> (whole layer / everything in a config) and crouton rollback-interactive (selection UI). The MCP rollback tool defaults dryRun: true (verified crouton-mcp/src/tools/rollback.ts:7); the CLI's does not — pass --dry-run yourself first.

Rollback does NOT touch the database: no migration is reverted, no table dropped, no rows deleted. Clean those up separately (a follow-up migration, or accept the orphan table on throwaway POCs).

Regeneration: re-running crouton config / crouton <layer> <collection> overwrites every generated file unconditionally — writeScaffold has no file-existence guard (fsp.writeFile loop at generate-collection.ts:1074-1078; code-derived, not reproduced end-to-end). Two consequences:

  • The generated file headers saying "regeneration requires --force flag" are stale; --force actually means (a) proceed despite missing package dependencies (:747-754) and (b) override schema-index export conflicts (:373-384).
  • Hand edits inside generated files are lost on regeneration — including the "editable" seed.json (it is in the unconditional write list, :1042-1049). Edit seed.json only if you won't regenerate, or re-apply edits after. If you customize a Form, prefer formComponent: (skips _Form.vue generation entirely) over editing the generated one.

9. Doc drift in this domain

The 2026-07-02 sweep's corrections (docs paths, docs-MCP tool names, dead nuxt-crouton-* package paths, the --dialect default, _Form.vue/[{singular}Id].patch.ts filenames, the sync-script extension, the manifest-vs-fallback field-type source) were applied to the canonical docs in the #1073 reshape — .claude/skills/crouton.md, packages/crouton-cli/CLAUDE.md, packages/crouton-mcp/CLAUDE.md now match the code. Don't trust this skill over them; if they disagree again, code wins (trust order: sibling crouton-docs-trust-map §1) and the fix goes to the canonical doc via the sync-docs workflow, not to a table here.

One known drift remains in code, not docs: generated file headers still claim "regeneration requires --force" while regeneration actually overwrites unconditionally (§8) — that's a template fix in packages/crouton-cli/lib/generators/, not a doc edit.

Provenance and maintenance

verified: 2026-07-02

Facts verified against: packages/crouton-cli/{bin/crouton-generate.js, lib/generate-collection.ts, lib/compose-layout.ts, lib/seed-app.ts, lib/rollback-collection.ts, lib/utils/{helpers.ts,manifest-loader.ts}, lib/generators/database-schema.ts, package.json}, packages/crouton-core/crouton.manifest.ts, packages/crouton-assets/crouton.manifest.ts, packages/crouton-layout/app/utils/layout-compose.ts, packages/crouton-mcp/src/{index.ts,tools/rollback.ts}, and on-disk generated output in fixtures/minimal/ + pocs/booking-demo/. Line numbers are anchors from that date and will drift — trust the symbol names over the :NNN. Issue numbers (#285, #298, #523, #558, #709, #711, #751, #785, #791) are cited from code comments and discovery-report summaries; check the issue if load-bearing.

Re-verification one-liners:

# dialect defaults (expect sqlite in bin, || 'pg' in runConfig)
grep -n "dialect" packages/crouton-cli/bin/crouton-generate.js | head -5
grep -n "config.dialect ||" packages/crouton-cli/lib/generate-collection.ts
# field-type catalog + aliases (the source of truth)
sed -n '12,25p' packages/crouton-core/crouton.manifest.ts
# artifact list / filenames (underscore Form, [xId] routes)
grep -n "_Form.vue\|Id].patch" packages/crouton-cli/lib/generate-collection.ts | head -5
# naming (registry key, table name)
grep -n "registryKeyFor\|snakeCaseTableName" packages/crouton-cli/lib/{compose-layout.ts,generators/database-schema.ts}
# layout payload + seed row id
grep -n "id: 'default'\|layout_configs" packages/crouton-cli/lib/{compose-layout.ts,seed-app.ts}
# CLI/manifest/skill field-type sync check
node scripts/validate-field-types-sync.mjs

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

a11y

無料

Accessibility review for Vue surfaces — the code-cleaning analog of /code-review and /simplify, pointed at WCAG/ARIA. Reviews just your diff (or a package/file), rates findings by severity, and either comments inline on the PR (--comment) or applies the safe fixes for you (--fix). Steers the depth-aware `a11y` subagent. Use when asked to "check accessibility", "a11y this", "audit ARIA/keyboard", or run /a11y.

日本語の概要は準備中です。原文の説明を表示しています。

FriendlyInternet/nuxt-crouton102026年10月6日 更新

ask-human

無料

Emit a blocking question the owner can read in ~10 seconds and answer in one reply — the scannable, recommendation-first handoff every agent posts when it hits a fork it can't own. Leads with the one decision + a recommendation, carries the 🤖 provenance header, doubles as the

日本語の概要は準備中です。原文の説明を表示しています。

FriendlyInternet/nuxt-crouton102026年10月6日 更新

audit

無料

Audit packages for documentation completeness, detect drift between code and docs, and maintain documentation quality across the monorepo. Use when checking package docs, running audits, or reviewing documentation health.

日本語の概要は準備中です。原文の説明を表示しています。

FriendlyInternet/nuxt-crouton102026年10月6日 更新

Author a placeable layout block that looks right at ANY pane size. The one hard rule — size to the PANE with container queries (@container), never the viewport — plus list/form playbooks and the sizing contract (minWidth etc.) the viability metric reads. Use when adding/converting a croutonLayoutBlocks block, or when a block overflows/breaks in a narrow pane.

日本語の概要は準備中です。原文の説明を表示しています。

FriendlyInternet/nuxt-crouton102026年10月6日 更新

When a bug or regression is reported, the FIRST step — before fixing — is to research how and when it was introduced (git archaeology), then record that finding on the tracking issue/PR. Use the moment a bug, error, broken build, or "this used to work" is reported, before writing a fix. Produces a first-bad-commit (or "not a code regression") note you paste onto the issue.

日本語の概要は準備中です。原文の説明を表示しています。

FriendlyInternet/nuxt-crouton102026年10月6日 更新

commit

無料

Smart, granular git commits following monorepo conventions. Analyzes changes, filters to session-relevant files, groups by intent, and uses conventional commit format. Use when committing code changes.

日本語の概要は準備中です。原文の説明を表示しています。

FriendlyInternet/nuxt-crouton102026年10月6日 更新

FriendlyInternet のスキルをすべて見る

このスキルの問題を報告する