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

crouton-run-and-operate

Day-to-day operation runbook for nuxt-crouton apps — boot any app/POC locally with auth working, seed and inspect the local database (including the miniflare-vs-.data split that makes seeded data "disappear"), turn on the review overlay / eruda, observe deployed staging (tail, smoke, row counts), and capture screenshots. Use when asked to "run the app", "boot velo/fanfare/a poc locally", "why can't I log in locally", "seed the database", "the seed data doesn't show up", "look at the local db", "check what's on staging", "screenshot the app", or "where do the artifacts land".

インストール方法を見る

含まれるファイル(1)

  • SKILL.md15.9 KB

SKILL.md(原文)

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

crouton-run-and-operate

Operate a running crouton app — locally or on deployed staging — from cold boot to evidence capture. ("crouton" = this monorepo's schema-driven CRUD framework: @fyit/crouton-* packages that generated Nuxt apps extend as layers.)

When to use / when NOT to use

You want to…Use
Boot, log in, seed, inspect, observe, screenshot a running appthis skill
Recreate the environment (install/build traps, typecheck story, versions)crouton-build-and-env
Deploy to staging / wire CI / first-time Cloudflare setupdeploy (apps), poc-deploy (pocs); prod only via deploy-production
Generate/apply Drizzle migrations, schema.mjs gotcha, infra tablesdb-migrations
Mirror one D1 env into another (refresh staging from prod)db-clone
Run the Playwright fixture smoke (boot+auth+CRUD proof)e2e-smoke
Deploy a preview for UI sign-off (the gate workflow)ui-proposal
Symptom → root-cause lookupsibling crouton-diagnostics-index
Measure the harness itself (context budget, traces)loop-station / sibling crouton-harness-observability

1. Boot any app locally from cold, with auth working

Prerequisites (one line — full story in crouton-build-and-env): pnpm install && pnpm build:packages. Apps consume @fyit/* packages from dist/; skipping build:packages = dev-server error on missing crouton-core/dist.

export BETTER_AUTH_SECRET=$(openssl rand -hex 32)   # required (crouton-auth throws if unset); better-auth only WARNS below 32 chars
pnpm --filter velo dev                              # or: cd apps/velo && pnpm dev
  • There is no root dev script (verified: root package.json scripts). Root CLAUDE.md's "Development Commands" listing pnpm dev only works inside an app dir — a known doc contradiction; the app package.json is ground truth here.
  • On Claude-web sessions the SessionStart hook (.claude/hooks/session-start.sh) already did install + build:packages and exported a cached dev BETTER_AUTH_SECRET (from ~/.crouton-dev-auth-secret) — check echo $BETTER_AUTH_SECRET before generating your own.
  • Apps ship .env.example (copy to .env). Trap: it hardcodes BETTER_AUTH_URL=http://localhost:3000 but each app runs on its own pinned port (table below) — set it to the app's real port or cookies misbehave.
  • E2e fixtures (fixtures/*) commit a dummy .env on purpose (BETTER_AUTH_SECRET=dev-fixture-secret-do-not-use-in-production) — they boot with zero env setup.
  • No manual DB step: hub: { db: 'sqlite' } in each app's nuxt.config.ts (root CLAUDE.md gotcha — never hub: { database: true }) auto-applies all layers' migrations at dev boot; locally it's a sqlite file, at runtime it maps to Cloudflare D1/KV/R2.

Fixed dev ports — pinned in each app's/POC's nuxt.config.ts devServer.port. Snapshot 2026-07-02 — regenerate with the re-verify block before relying on numbers.

AppPortPOCPort
apps/triage3005pocs/alexdeforce3001
apps/velo3006pocs/sintlukas3003
apps/kassa3007pocs/crouton-builder-demo3010
e2e fixtures3000pocs/crouton-builder and pocs/kvr3011 — collision; run one with --port
pocs/loop-station3021

Pocs that set no port (blog, thinkgraph*, three-demo, booking-demo at the snapshot) default to 3000/auto-bump.

First login (auth = better-auth via @fyit/crouton-auth; facts from e2e/CLAUDE.md):

  • Login/register is a RouteModal overlay, not a page — /auth/login redirects to / and opens the modal (useAuthModal). Register a fresh account in the modal on a fresh DB.
  • Signup creates no team. Programmatically, create one via the better-auth org API: POST /api/auth/organization/create then /set-active — both require an Origin header (CSRF). See ensureTeam() in e2e/helpers.ts for the exact calls. Or seed staff accounts instead (§2).
  • Generated collections render at /admin/{teamSlug}/crouton/{collectionKey}.
  • Session check: GET /api/auth/get-session returns the authenticated user (what smoke-deployed.mjs uses as login proof).

Do NOT verify with nuxt preview: crouton collection pages currently 500 under production-preset SSR — an internal data-fetch loses the auth cookie (e2e/CLAUDE.md, open problem). Operate against nuxt dev.

1.5 Reproduce a runtime bug locally — MOBILE-FIRST (never push a fix blind)

The method rule is in AGENTS.md (Bug work → reproduce against the running system): for a runtime bug (reload loop, 500, broken interaction), reproduce + verify the fix locally before pushing. Here's the crouton how-to. This stack is phone-first (#722, atelier-plan) — drive at a phone viewport (390×844) by default; only check desktop when a surface is explicitly wide.

Write a throwaway driver inside the repo tree (playwright resolves from repo node_modules; a /tmp script can't import it) — repro.local.mjs at the repo root; don't commit it.

import { chromium } from 'playwright'
const CHROME = '/opt/pw-browsers/chromium-1194/chrome-linux/chrome' // glob newest if the build bumped
const browser = await chromium.launch({ executablePath: CHROME, headless: true, args: ['--no-sandbox'] })
const ctx = await browser.newContext({ viewport: { width: 390, height: 844 }, deviceScaleFactor: 3 }) // MOBILE
const page = await ctx.newPage()
page.on('console', m => console.log('console', m.type(), m.text()))
page.on('load', () => console.log('PAGE LOAD', page.url()))         // count loads → reload vs re-render
page.on('framenavigated', f => f === page.mainFrame() && console.log('nav', f.url()))
page.on('pageerror', e => console.log('PAGEERROR', e.message))

Auth/team bootstrap for a team-scoped page (better-auth's org calls need an origin header, else MISSING_OR_NULL_ORIGIN). Do it via ctx.request so cookies are shared: POST /api/auth/sign-up/email {email,password,name} → POST /api/auth/organization/create {name,slug} (headers {origin, referer}) → POST /api/auth/organization/set-active {organizationId} → seed rows via the collection API POST /api/teams/<orgId>/<collection> → page.goto('/…').

Instrument, then observe — don't theorise. A full-page reload in Nuxt is often chunk-error auto-reload; counting load events tells a reload from a re-render. (#988 board reload: three blind pushes vs one local repro that found it — autosave→refetch→reload — in minutes.)

2. Seeding

Package demo data — every app has db:seed scripts (verified in the apps' package.json):

pnpm --filter velo db:seed          # = crouton-seed --db velo-db --with-staff (local)
pnpm --filter velo db:seed:staging  # = crouton-seed --db velo-staging-db --remote --with-staff

crouton-seed (bin: packages/crouton-cli/bin/crouton-seed.mjs) discovers SeedProviders from every extended @fyit/crouton-* package, emits idempotent upsert SQL, and executes it via npx wrangler d1 execute <db> --local|--remote. Flags (verified): --db (required) --remote --dir --team (default test1) --locale (default nl) --with-staff --dry-run. It also seeds the app's default layout: crouton.layout.json → a layout_configs row with id default (#709; lib/seed-app.ts).

⚠️ THE seed-visibility trap (code-derived, not reproduced end-to-end): a local crouton-seed writes via wrangler d1 execute --local into <app>/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite (miniflare = wrangler's local Cloudflare simulator), but nuxt dev with hub: { db: 'sqlite' } reads <app>/.data/db/sqlite.db. seed-app.ts has no copy step into .data/ (verified: it only shells out to wrangler d1 execute — re-check with the seed grep in the re-verify block). So locally-seeded data may never appear in the dev app. crouton db-pull handles the split explicitly — lib/db-pull.ts copies the imported DB to .data/db/sqlite.db and marks _hub_migrations applied. If seeded data "doesn't show up", this split is why; workaround is copying the sqlite file into .data/db/sqlite.db by hand (stop dev first).

App-specific content seeds (seedData/ convention): velo keeps CSVs/markdown under apps/velo/seedData/{school-velotek,velosolidaire}/, consumed by HTTP endpoints POST /api/seed and POST /api/seed/velosolidaire (apps/velo/server/api/seed/*.post.ts — additive, dedupes users by email, hashes passwords properly). This is the "per-collection seeding" the db-clone skill contrasts itself with.

Pull real remote data local:

cd apps/velo && npx crouton db-pull --env staging --dry-run   # then drop --dry-run

Flags (verified in bin/crouton-generate.js dbPullCmd): --env, --config, --keep-sql, --dry-run. Flow: export remote D1 → wipe local wrangler D1 → import → copy to .data/db/sqlite.db.

3. Inspecting the local DB

  • File: <app>/.data/db/sqlite.db — exists only after dev has run once. Inspect with plain sqlite3:
    sqlite3 apps/velo/.data/db/sqlite.db '.tables'
    
  • No Drizzle Studio wiring exists in the repo (verified: zero db:studio/drizzle-kit studio hits) — but none is needed on a normal dev machine: NuxtHub core itself launches Drizzle Studio as the "Database" tab in Nuxt DevTools during nuxt dev whenever hub.db is set (@nuxthub/core launchDrizzleStudio() → startStudioSQLiteServer, iframe at local.drizzle.studio — verified in the dist, not exercised live). It needs a browser + egress to that host, so it's unusable in the headless sandbox — there, raw sqlite3 is the reality.
  • Remote row counts (read-only, safest remote check):
    node scripts/db-counts.mjs --app velo --env staging   # or: pnpm db:counts -- --app velo --env staging
    
    Discovers the DB name from the app's wrangler.jsonc; a real run needs CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN, --dry-run needs neither. (These CF creds are typically absent in the interactive sandbox — remote inspection then goes through CI.)
  • Ad-hoc remote SQL: npx wrangler d1 execute <db-name> [--env staging] --remote --command "SELECT …".

4. Review overlay and eruda

  • Review overlay — NUXT_PUBLIC_CROUTON_REVIEW=true at build time (read in packages/crouton-devtools/src/module.ts) makes @fyit/crouton-devtools install @fyit/crouton-feedback (epic #960) with the GitHub sink defaulted: a glasses launcher with Console (eruda), Annotate (pin a comment on an element → resolves the source file → lands as a 🎯 Preview feedback PR comment), and Changelog. Generated cf:staging scripts bake the flag in; zero prod footprint. The sign-off workflow around it belongs to the ui-proposal skill.
  • Eruda mobile devtools layer — opt-in per app: extends: ['@fyit/crouton-devtools/eruda'], active in local dev or when NUXT_PUBLIC_CROUTON_ERUDA=true at build (verified in packages/crouton-devtools/eruda/nuxt.config.ts; default off, chunk never fetched in prod). Set the flag in cf:staging only, never cf:deploy.

5. Observing deployed staging

Deploy/migrate mechanics live in the deploy skill — this is the watching side.

NeedCommandCaveat
Live Worker logspnpm --filter triage logs / --filter fanfare logs (= npx wrangler tail triage|fanfare)Only some apps have a logs script (grep for it — re-verify block), and those tail the production worker. No staging tail script exists anywhere (verified at the snapshot); hand-run npx wrangler tail <app>-staging (unverified against a live worker — needs CF creds). No log persistence: an error nobody was tailing is gone.
Prove a deployed preview worksnode scripts/smoke-deployed.mjs --url https://<app>.pmcp.dev --email <e> --password <pw> [--app <n>] [--manifest <app>/deploy.config.json]Login proof via /api/auth/get-session → optional CRUD round-trip (from deploy.config.json smoke.crud) → screenshot screenshots/<app>-smoke.png. CI runs it per deploy, report-only unless smoke.required: true.
Seed a loginable review account on a deploynode scripts/seed-review-login.mjs --url <deployedUrl> --email <e> --password <pw>Uses the app's own HTTP auth routes (real password hashing); best-effort. --seed-team <slug> attaches it to the seeded demo org — with --db <d1> (remote, the deploy path) or --sqlite <path> (the local .data/db/sqlite.db, #1777).
Look at a change locally, in one commandpnpm preview <app>Boot + seed + disposable review login + a prefilled one-click URL (scripts/app-preview.mjs, #1777). Use this instead of hand-rolling boot→seed→login; it's the only preview a packages-only change gets, since PR deploy previews match only apps/<app>/** by design. --no-seed / --no-login for faster re-runs; landing page comes from reviewLogin.landing in the app's deploy.config.json.
What's in the staging DBnode scripts/db-counts.mjs --app <app> --env staging§3.

At last verification, no runtime analytics was wired in any deployed app: packages/crouton-analytics exists but no app/poc/fixture depends on it (unverified beyond a grep of package.jsons — re-run that grep before relying on it; from the #1073 discovery sweep, adapters were in-flight, #947).

6. Screenshots

node scripts/app-shots.mjs <baseUrl> <path[:name]> [more paths...] [--out <dir>] [--desktop|--viewport WxH]
# e.g. node scripts/app-shots.mjs http://localhost:3006 /:home /auth/login:login   # MOBILE (default)

Shots are MOBILE (390×844) by default — this stack is phone-first (#722); verify the phone layout first and only add --desktop (1280×900) for surfaces that are explicitly wide. (Also pnpm app:shots.) Writes screenshots/<name>.png; exits 1 on any failure. It auto-resolves the pre-installed chromium under /opt/pw-browsers/ (globs the newest build; override with PLAYWRIGHT_CHROMIUM_PATH) — a failing npx playwright install does NOT mean "no browser"; doctrine: crouton-harness-observability §5. All screenshots go in screenshots/ at repo root (HARD GATE, root CLAUDE.md).

7. Where artifacts land

ArtifactLocationCommitted?
Local dev DB (NuxtHub)<app>/.data/db/sqlite.db (+ applied-migration copies in .data/db/migrations/sqlite/)No (.data gitignored — verified git check-ignore)
Wrangler-local D1 (miniflare)<app>/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqliteNo
Build output<app>/.output/No
Screenshotsscreenshots/<name>.pngNo (*.png gitignored)
Drizzle migrations (source of truth)<app>/server/db/migrations/sqlite/Yes
e2e outputse2e/.auth/, playwright-report/, test-results/No

Provenance and maintenance

verified: 2026-07-02

grep -rn devServer apps/*/nuxt.config.ts pocs/*/nuxt.config.ts         # ports table
grep -n '"dev"\|"logs"\|db:seed' apps/*/package.json                   # scripts / tail gap
grep -n 'wrangler\|\.data' packages/crouton-cli/lib/seed-app.ts        # seed write target (has a .data copy step appeared?)
grep -rln crouton-analytics apps pocs fixtures --include=package.json  # analytics still unconsumed?
head -20 scripts/app-shots.mjs scripts/smoke-deployed.mjs              # usage lines
grep -n CROUTON_REVIEW packages/crouton-devtools/src/module.ts         # review-overlay gate

レビュー

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

同じリポジトリのスキル

概要と使いどころ

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月13日 更新

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月13日 更新

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月13日 更新

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月13日 更新

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月13日 更新

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月13日 更新

FriendlyInternet のスキルをすべて見る

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