Development Standards and Tools¶
本プロジェクトにおける技術標準、コーディング規約、開発ツール、およびワークフローの定義です。
技術標準とツール¶
- モノレポ構成: Nx + pnpm によるワークスペース管理
- バックエンド: Vendure (Node.js/TypeScript)
- フロントエンド: Vite + React (TypeScript/Tailwind CSS v4)
- 共通パッケージ:
@ritsubi/domain,@ritsubi/utils - デプロイ: Cloudflare Workers (Storefront), Cloudflare Workers (Dashboard), Fly.io (Vendure)
- バージョン管理:
miseによる Node.js, pnpm 等のツール管理 - 品質管理:
oxlint(高速な広域リンター),ESLint(型依存/React Hooks ルール),knip(未使用依存関係チェック),Semgrep(CI 向け SAST),ShellCheck(shell script lint),vitest(テスト),tsc-files(高速型チェック)
UI テーマ方針¶
- Storefront の UI テーマは light theme 固定 とし、ダークテーマは要件外とする。
prefers-color-schemeやテーマ切替 provider を使って、Storefront 全体の配色を dark に切り替えない。- shared UI 基盤に dark 用スタイル定義が存在しても、Storefront では light 前提の受け入れ・検証を行う。
主要コマンド¶
just dev-full: 開発サーバー起動(一括, CLI / Portless)just build: ビルド(一括)just lint: oxlint と ESLint を順番に実行just lint-fix: oxlint 自動修正just knip: Knip v6 の全体分析(未使用ファイル/依存関係/exports を調査)just knip-gate: Knip の手動 gate(unlisted/unresolved)just scan-semgrep-changed origin/develop HEAD: changed JS/TS/PHP(.mjs/.cjs/.mts/.cts含む)向け Semgrep SASTjust scan-shellcheck-changed origin/develop HEAD: changed.sh向けShellCheckjust scan-trivy-fs: Trivy による repo 全体の misconfig / secret scanjust scan-trivy-image-vendure: Trivy による Vendure Fly image scan(pre-push とTrivy Vendure Imageworkflow の共通入口)just env-status <staging|production>: Storefront / Vendure / Fly / Cloudflare の 実行状況を 1 窓口で確認するコマンド。--format jsonで AI エージェント向けの structured output を返す。just env-status-all: staging / production をまとめて確認し、version / build metadata / health の差分まで出す。just ai-rg <pattern>:tmp/node_modules/ build artifact を除外した AI 向け全文検索。just ai-find-agents: repo 管理下のAGENTS.mdだけを列挙する。just typecheck: TypeScript 型チェック (全体)just vendure-migrate: データベースマイグレーション
重複 helper の正本¶
- HTTP
Set-Cookie抽出は@ritsubi/utilsのextractSetCookies/splitCombinedSetCookieHeaderを使う。Fetch runtime ごとのgetSetCookie()差分と combined header split を各 app / test / ops script で再実装しない。 - Node scripts の変更ファイル解決は
scripts/lib/git-change-scope.mjsを使う。--changed-only/--staged/ GitHub / Nx の diff range fallback を各 lint guard に複製しない。 - Vendure service を使う seed / repair / one-shot script は
apps/vendure-server/scripts/lib/run-vendure-script.tsを使う。production guard、port: 0、app.close()は wrapper の責務。 - traceparent の文字列化は
@ritsubi/utilsのformatTraceparentを使う。 Playwright / browser logger / Worker などの surface ごとに00-...を手書きしない。 - 通貨・日時 helper は
@ritsubi/utilsのformatCurrencyValue/formatVendurePriceValue/formatDateTimeMediumを使う。React Dashboard のutils/common.tsは互換 import の薄い re-export とし、formatter 実装を増やさない。 - JSON の安定比較は
@ritsubi/utilsのsortJsonValue/stableJsonStringifyを使う。dirty 判定・drift hash・snapshot 比較で object key sort を再実装しない。Node.mjsops script ではscripts/lib/stable-json.mjsを使う。 - Storefront で TanStack Router の
location.searchobject をURLSearchParamsに変換する場合はapps/storefront/src/lib/router-search.tsを使う。 - Playwright E2E の navigation timing 取得は
apps/storefront/tests/e2e/helpers/performance-metrics.tsを使う。 - React Dashboard form の
beforeunloadguard はpackages/plugins/src/standard-extensions/admin-extensions/dashboard/utils/use-dirty-form-state.tsを使う。route blocker 付きの dirty guard は同ファイルのuseDirtyNavigationGuardを使う。 - 再発防止は
pnpm run lint:duplicated-helper-implementationsで検査する。root のlint:static-checksにも含まれる。
Nx と キャッシュ戦略¶
本プロジェクトでは、モノレポの依存関係管理とタスク実行の最適化に Nx
を使用しています。Nx
Cloud(リモートキャッシュ)は使用せず、ローカル環境および GitHub
Actions のネイティブキャッシュ(actions/cache)を利用して .nx/cache
をプロジェクト間で共有・復元する戦略をとっています。
- CI でのキャッシュ:
ci-pr-develop.ymlなどでactions/cacheを使用するが、pnpm store/.nx/cacheは lockfile 共有だけでなく PR / branch ごとの trust boundary でも key を分離する。PR/fork と base branch / deploy 系 workflow で同じ cache key を共有しない。 Playwright browser bundle は公式 CI 手順に合わせて cache せず、install-playwright-chromiumからplaywright install --with-deps chromiumを実行する。 - キャッシュの復元方針: broad な
restore-keysfallback は原則禁止。exact-match key のみを復元し、closed PR の cache はCleanup PR Cachesworkflow で削除する。 - CI モード: CI 環境では
NX_NO_CLOUD=trueを設定し、リモートへの接続試行を無効化しています。 - Storefront Cloudflare target の正本:
dev*/build/cloudflare:build/cloudflare:types*/cloudflare:preview/cloudflare:deploy*はapps/storefront/project.jsonの Nx target を正本とし、 local / CI / deploy の全経路でpnpm exec nx run ritsubi-storefront:<target>を通します。 - Storefront guard の障害方針: 認証ガードは fail-closed を基本にしつつ、予期しない例外は login redirect へ degrade して Worker exception 化を避けます。メンテナンスガードは fail-open を基本にし、意図した redirect 以外の障害は観測して継続します。
- Cloudflare 設定変更時の認証:
local で Cloudflare の設定値やリソースを直接変更する
wrangler操作は、共有 token 注入よりwranglerのユーザー認証を正とします。deploy 系 script が利用するCLOUDFLARE_API_TOKENは自動化用途として扱い、手元の設定変更作業とは分離します。
Nx affected の基準¶
nx affected
を使用し、「変更されたファイルに影響を受けるプロジェクトのみ」を対象に Lint、型チェック、テスト、ビルドを実行します。
- PR:
NX_BASE=origin/<base>,NX_HEAD=${{ github.sha }} developpush(integration gate):NX_BASE=${{ github.event.before }}main/hotfix/*push:NX_BASE=${{ github.event.before }}
主要コマンド例¶
# 影響を受けるプロジェクトのみ型チェック
pnpm exec nx affected --target=typecheck --base="$NX_BASE" --head="$NX_HEAD"
# 影響を受けるプロジェクトのみテスト(並列実行)
pnpm exec nx affected --target=test --base="$NX_BASE" --head="$NX_HEAD" --parallel=3
# プロジェクトの依存関係を可視化(ブラウザで開く)
pnpm exec nx graph
CI(GitHub Actions)とローカルフックの責務¶
GitHub Actions Runner(Blacksmith)¶
本リポジトリの GitHub Actions は GitHub-hosted runner ではなく Blacksmith runner を利用します。
- 基本タグ:
blacksmith-2vcpu-ubuntu-2404(軽いジョブ) - 重いジョブ:
blacksmith-8vcpu-ubuntu-2404(Nx の並列実行を活用するためリソースを多めに割り当て) - キャッシュ:
actions/cacheを使う場合でも、.nx/cache/pnpm storeは workflow context ごとに scope を分離する。PR / fork 由来 cache を trusted branch / deploy job に再利用させない。Playwright browser bundle は cache 対象にせず、公式 CLI の install path を使う。
CI dependency / cache hardening¶
setup-pnpm-workspace/setup-pnpm-minimal/install-playwright-chromium/restore-nx-cacheを、GitHub Actions cache の正本とする。workflow ごとにactions/cacheを直書きして trust boundary をばらけさせない。pnpm installは、scripts 実行が不要な workflow では--ignore-scriptsを既定とする。特に workflow validation や軽量 PR guard は install-time 実行面を増やさない。- lifecycle script を許可する workflow は、build / codegen / DB dry-run
など実行理由を説明できるものに限定する。必要性が曖昧なまま
ignore-scripts: "false"を追加しない。 pull_request_targetで untrusted code を checkout して install / build / cache restore しない。pull_request_targetは bot metadata 処理など、PR 本文や review 操作に閉じた用途へ限定する。
CI の実行判定 (Nx への委譲)¶
手動のパスフィルター(dorny/paths-filterなど)は使用せず、どのプロジェクトをテスト・ビルドすべきかの判定はすべて Nx
(nx affected) に委ねています。これにより、新しいパッケージを追加した際にも CI の設定ファイルをメンテナンスする必要がありません。
GitHub Actions / custom action の検証手順¶
.github/workflows/** や .github/actions/** を変更した場合は、Nx 管理外の
custom GitHub Actions も含めて次の順で確認します。
pnpm run typecheck:gha-actions
pnpm run lint:actions
pnpm run build:gha-actions
typecheck:gha-actionsは.github/actions/*/src/index.tsの正本検査です。pnpm exec tsc .github/actions/.../src/index.tsのように files を直接渡すと、 roottsconfig.jsonの扱いと衝突してTS5112などの手順由来エラーを起こしやすいため使用しません。- workflow YAML / action YAML の構文確認や
actionlint、custom action dist の再生成確認は.github/actions/validate-workflowsを通す CI の共通経路に揃えます。PR 向け workflow へ同じ処理を直書きしません。 .github/actions/validate-workflowsはignore-scripts: trueで install する。workflow lint / typecheck / build に不要な package lifecycle script は実行しない。pnpm run build:gha-actions後に.github/actions/**/distが更新された場合は、 source と dist の drift を解消するため、意図した変更として差分を確認します。
ブランチ役割別ゲート(SSOT)¶
| トリガー | Workflow / Queue | 重さ | 役割 |
|---|---|---|---|
| PR: feature/* → develop | CI (PR -> develop) |
軽 | smoke gate(lint / typecheck / unit / coverage / worker) |
| merge_group(Mergify queue train) | CI (PR -> develop) (merge_group event) |
重 | full gate(integration / CT / Cloudflare build を追加) |
| push: develop(直push/マージ後) | CI (push develop) |
中 | post-merge build / typecheck |
| PR: develop → main(+ hotfix/* → main) | CI (PR -> main) + Mergify queue (任意) |
重 | 出荷判定ゲート。promotion PR は Mergify queue を利用できる |
| push: main | deploy/release workflows | 最小 | 配布・運用 |
GitHub Merge Queue は使わず、Mergify Merge Queue を採用する。branch
protection は ci/required-develop / ci/required-main
を正本とし、Mergify はその required checks を満たした PR だけを queue 経由でマージする。
PR smoke / merge queue full の 2 段ゲート設計:
- PR (
pull_requestevent): lint・typecheck・unit・coverage・dashboard-worker・storefront-smoke のみ必須。 高速(目標 < 12 min)でフィードバックを返す。 - Merge queue (
merge_groupevent): 上記に加えて integration shards × 2・provider-contract・dashboard-smoke・dashboard-pages-smoke・ storefront-ct × 2・storefront-cloudflare-build を必須化。evaluate-required-gateがrequire-heavy-gate: trueで両グループを集約する。
CI (PR -> develop) は Nx affected ベースの incremental gate を基本にする。
Promote Main は Staging Smoke Storefront 成功後にのみ動く。staging
deploy 完了だけでは main への昇格は進めず、smoke を通った変更だけを promotion
candidate とする。
Lighthouse CI
は nightly と手動実行を基本にし、通常の push では常時実行しない。
Mergify Queue / Stacks¶
developが default branch のため、Mergify 設定はdevelop上の.mergify.ymlを正本とする。develop向け PR はautoラベルで Mergify queue に投入する。手動投入したい場合は PR へ@mergifyio queueコメントを使ってよい。main向け promotion PR はpromotion+autoラベルのときだけ Mergify queue に投入する。- Stacked PR は GitHub の head branch 自動削除を前提に、
mergify-cliを使って運用する。
python3 -m pip install --user mergify-cli
mergify stack --setup
# feature branch 上で stack を作成 / 更新
mergify stack
「ローカルで落とす」「CIで保証する」¶
| 種類 | lefthook(ローカル) | GitHub Actions(CI) |
|---|---|---|
| format | ✅(staged のみ) | ❌ |
| lint | ✅(staged/affected) | ✅(affected) |
| typecheck | ✅(affected) | ✅(affected) |
| unit test | ✅(affected/push前) | ✅(affected) |
| integration/e2e | ❌ | ✅ |
| build | ✅(affected/push前) | ✅(affected) |
| security SAST | ❌ | ✅(CI (PR -> develop) / changed JS/TS/PHP) |
| shell script lint | ❌ | ✅(CI (PR -> develop) / changed .sh) |
| dependency audit | ❌ | ✅(audit.yml / schedule + workflow_dispatch) |
| Trivy FS / image | 任意実行 | ✅(独立 workflow / schedule + PR + push + 手動) |
ポイント:
- lefthook は「即時・機械的・軽量」。pre-commit では staged files が属する
projectを優先して即時フィードバックを返し、transitive な影響確認は pre-push / CI のnx affectedに委譲します。 - CI は「非同期・網羅的」。ここでも Nx の並列実行を活用し、待ち時間を最小化します。
- アプリコード向け SAST は
CI (PR -> develop)でbash scripts/ci/run-semgrep-changed.sh "$NX_BASE" "$NX_HEAD"を実行し、changed JS/TS/PHP(.mjs/.cjs/.mts/.cts含む)files のみを Semgrep CE で検査します。explicit target では.semgrepignoreに頼れないため、test/generated/build 系は runner 側でも除外します。初期導入ではERRORのみ blocker とし、workflow 向けp/ciルールは別フェーズとします。 - shell script lint は
CI (PR -> develop)でbash scripts/ci/run-shellcheck-changed.sh "$NX_BASE" "$NX_HEAD"を実行し、changed.shのみを ShellCheck で検査します。設定の正本は.shellcheckrcとし、初期導入ではstyleを除外するためseverity=infoで実行します。
開発ワークフローと Git Hooks¶
本プロジェクトでは lefthook
を使用して、コミットおよびプッシュ時に自動チェックを行っています。Nx と統合することで、高速かつ漏れのない検証を実現しています。
コミット前チェック (pre-commit)¶
コミットを高速化するため、変更されたファイルとその影響範囲のみを対象にチェックを行います。
- codegen-smart: Nx の依存関係グラフを利用し、必要なプロジェクトのみ GraphQL Codegen を実行。
- oxlint /
oxfmt: 変更された JS/TS と Markdown/YAML の静的解析とフォーマット。
docs 系は
scripts/lefthook/docs-staged.shでoxfmt→markdownlint-cli2 --fix→ Mermaid lint の順に直列実行し、parallel hook が同じ Markdown を同時に書き換えないようにします。 - typecheck (touched projects): staged の TS/TSX が属する project だけ
nx run-many --target=typecheck --projects=<touched-projects>で型チェックします。対象は Nx 管理下のapps/packages/tools/に絞り、依存先への波及確認は pre-push のnx affectedに委譲。 - vendure-data-guards:
scripts/hooks/pre-commit-vendure-data-guards.shにより、エンティティやマイグレーションの staged 変更がある場合のみ静的安全チェックを実行。 対象 path はscripts/ci/vendure-data-guard-paths.txtを正本にし、migration timestamp guard はLEFTHOOK_FAST=1でも skip しません。 - vendure-dist-guard:
scripts/ci/vendure-dist-guard-paths.txtを正本に、Vendure の privatedistimport が staged 差分へ混入していないかを確認します。
プッシュ前チェック (pre-push)¶
プッシュ前に、影響を受けるプロジェクト全体の整合性を最終確認します。
- Nx を正本にする gate:
verify-affectedのように project graph で安全に絞れるチェックだけをnx affectedに載せます。 -
Nx を正本にしない gate:
vendure-db-dry-run、vendure-image-trivyは workspace 横断入力や Docker build 入力が正本のため、差分 path / build input ベースで判定します。 -
verify-affected:
nx affected --target=typecheck --base=<push-base> --head=HEADを実行し、今から push するコミット範囲で影響を受けるプロジェクトだけを型チェックします。重いテストは CI に委譲します。docs/**や*.md/*.csvなど文書系差分しかない push では、Nx 起動自体を skip します。 - vendure-db-dry-run:
scripts/ci/vendure-db-dry-run-paths.txtを正本に、Vendure の data-model に影響する path 変更がある場合のみ、使い捨て DB を用いてシード・マイグレーションの安全性をテストします。 対象差分がある場合、migration timestamp guard とvendure-data-guardsは DB 接続設定の有無に関係なく必ず実行します。その後のdb:reset:dry-runはDATABASE_URL未設定時にローカルの使い捨て PostgreSQL (postgres://vendure:vendure_dev_password@localhost:5433/vendure_dev) を使います。 明示的な接続先を使う場合はVENDURE_DRY_RUN_DATABASE_URLまたはDATABASE_URLを設定します。 dry-run 本体はデフォルトでlocalhost/127.0.0.1/::1以外を拒否します。 dry-run を明示的に迂回する場合だけSKIP_VENDURE_DB_DRY_RUN=1を使います。 - knip:
Knip は OOM しやすいため pre-push gate から外し、手動の
just knip-gate/just knipで実行します。just knip-gateはscripts/ci/knip-workspaces.txtを正本に対象 workspace を逐次実行し、単一 Node process に monorepo 全体の graph を載せないようにします。 必要な場合はRITSUBI_KNIP_NODE_MAX_OLD_SPACE_SIZE_MBで Knip 専用の heap 上限を調整できます。 - vendure-image-trivy:
scripts/hooks/pre-push-trivy-vendure-image.shにより、Vendure image の構成要素 (apps/vendure-server/src/**,apps/vendure-server/scripts/**,apps/vendure-server/static/**,apps/vendure-server/tsconfig*.json,apps/vendure-server/tests/vendure-test-utils/**,packages/config/**,packages/contract/**,packages/domain/**,packages/plugins/**,packages/utils/**,.dockerignore,.npmrc*,patches/**, lockfile,trivy.yamlなど)に変更がある push だけjust scan-trivy-image-vendure相当の image scan を実行します。差分判定の path list はscripts/ci/vendure-image-paths.txtを正本とし、local hook はこの manifest を読み、 CI はscripts/ci/validate-trivy-vendure-image-paths.mjsで workflow のon.pull_request.paths/on.push.pathsとの一致を検証します。通常の push で毎回 image build は走らせず、出荷 artifact に直結する差分だけを gate します。 - dashboard-i18n-catalog:
scripts/ci/dashboard-i18n-catalog-paths.txtを正本に、Dashboard i18n の source / catalog / compile 出力 / checker が変わった push だけpnpm run lint:dashboard-i18n-catalogを実行します。無関係な push では skip 理由を出して終了します。 - docs-strict / changeset-check:
scripts/hooks/pre-push-common.shのresolve_pre_push_rangeを使い、他の pre-push gate と同じPRE_PUSH_BASE..HEADを比較対象にします。
FAST モード¶
緊急時などで重い処理をスキップしたい場合は LEFTHOOK_FAST=1 を使用できます。
LEFTHOOK_FAST=1 git push
この場合、以下のジョブがスキップされます。
vendure-db-dry-runvendure-image-trivy
Vendure image Trivy gate だけを明示的に外したい場合は
SKIP_TRIVY_VENDURE_IMAGE=1 git push を使用します。通常運用では常用せず、
既知の triage 中や CI 側で結果を確認する意図が明確な場合に限ります。
アーキテクチャ層の定義と責務¶
プロジェクトの長期的なメンテナンス性と AI による理解しやすさを維持するため、以下の層を明確に分離します。
1. 純粋ドメイン層 (packages/domain)¶
- 役割: ビジネスの「意味」と「不変条件(Invariants)」を保持する。
- 制約: 依存関係ゼロ。Node.js, Web, DB, Framework, および Zod などのバリデーションライブラリにも依存しない。
- 内容: エンティティ(POJO)、値オブジェクト、ドメインサービス。
2. 契約層 (packages/contract)¶
- 役割: システム間や境界での「合意(契約)」を定義する。
- 制約: Zod を中心としたスキーマ定義。I/O の形式を定義し、人間・機械・AI が共通して参照できる「正本」となる。
- 内容:
Zod スキーマ、推論された TypeScript 型、API リクエスト/レスポンス定義。環境変数の共通バリデーション関数・共通型定義もここに集約する(apps 側は薄い
env.schema.ts)。 - generated artifact ルール:
packages/contract/generated/*.tsは codegen の tracked 正本として扱う。src/配下の*.js/*.d.ts/*.mapは build artifact とみなし、tracked 正本にしない。- 検査は
pnpm run lint:tracked-src-artifacts、掃除はpnpm run clean:src-artifactsを使う。
3. shared config / spec 層 (packages/config)¶
- 役割: app 横断で共有する設定まわりの正本を保持する。
- 内容:
src/env.schema.ts: shared env fragmentsrc/defaults.ts: runtime fallback / build defaultssrc/spec.ts: cross-app shared immutable technical constants- 制約:
- 業務不変条件は置かない(→
packages/domain) - 境界契約の正本となるスキーマは置かない(→
packages/contract) - 新規利用では bare import の
@ritsubi/configではなく subpath import を優先する
4. utility 層 (packages/utils)¶
- 役割: low-level helper / runtime helper を提供する。
- 内容: URL helper、Sentry helper、runtime helper、process/build step 判定など。
- 制約: shared な defaults / spec / 業務定数の正本を持たない。
5. 実装・インフラ層 (packages/plugins, apps/*)¶
- 役割: ドメイン知識と契約を使用して、具体的な機能を実装する。
- 内容: Vendure プラグイン、TypeORM エンティティ、NestJS コントローラー、Storefront の route / page コンポーネント。
- バリデーション: 境界(API 入力時など)で
packages/contractの Zod スキーマを使用して実行時検証を行う。
コーディング規約¶
Git コミットルール (Conventional Commits + 日本語)¶
すべてのコミットメッセージは以下の形式で記載してください。
type: 日本語での説明
主要タイプ:
feat: 新機能追加fix: バグ修正docs: ドキュメント更新style: コードスタイル修正refactor: リファクタリングtest: テスト追加・修正chore: ビルド・補助ツール関連
例: feat: 顧客別価格設定プラグインを追加
開発ワークフロー¶
- ブランチ戦略: Gitフロー(シンプル版)。詳細は
docs/04-project-management/branch-strategy.md参照。 - デプロイ: GitHub Actions による自動デプロイ(
develop -> staging,main -> production)。 - Issue 管理: GitHub Issue を使用。完了条件 (DoD) を明確に定義すること。
-
gh issue の本文はファイル/ヒアドキュメントで渡す(バッククォート等のシェル展開を避ける)
cat <<'EOF' > /tmp/issue.md ## 概要 ここに本文を書く(バッククォートも安全) EOF gh issue create --title "..." --body-file /tmp/issue.md -
既存Issueの更新も同様に
--body-fileを使用する
コード品質とテスト¶
- oxlint: 共通設定
.oxlintrc.jsonを使用。 - コンポーネントテスト:
- Storefront: UI 検証の正本は Playwright CT + fixture とする。見た目、interaction、状態差分は E2E mock より先に CT へ寄せる。
- Storefront screenshot: コンポーネント単体で判断できる見た目は page 全体ではなく locator の
toHaveScreenshot()で固定する。ユーザーへ提示する PNG は canonical snapshot path を直接使わず、同じ locator にcaptureFreshCtScreenshot()を呼び、pnpm -C apps/storefront run test:ct:fresh -- <ct spec> --grep "<test name>" --screenshot <name>で actual browser capture を timestamp 付き fresh 出力にする。actual capture が無い場合は失敗扱いにし、snapshot コピーの fallback は使わない。 - Vitest + React Testing Library は、純粋関数・hook・小さな UI ロジック・jsdom で閉じる補助検証に使う。
- Plugins (UI): 管理画面拡張などの UI コンポーネントは引き続き
jsdom環境でテスト可能。 - インポート規則:
CRITICAL: テストの安定性を高め、
Element type is invalidエラーを撲滅するため、shadcnコンポーネントは一括インポートを禁止し、個別インポート(例:@/components/shadcn/button)を必須とする。 - モック手法: Storefront では
vi.mockによる query hook 直接モックを第一選択にしない。まず fixture / CT support / preview 専用 provider で状態を再現し、直接モックは小さな単体検証に限定する。 - E2E テスト: Playwright を使用。
- Storefront:
apps/storefront/tests/e2e/ - Dashboard:
apps/vendure-server/tests/dashboard-e2e/ - data-testid: E2E 安定化のため、主要要素には必ず
data-testidを付与すること。文言依存のセレクタは禁止。
UI 開発と shadcn/ui ガイドライン¶
本プロジェクトのフロントエンド開発では、最新の shadcn/ui と Tailwind CSS v4 を基盤としています。
shadcn/ui 活用の原則¶
- 車輪の再発明を避ける:
- Radix UI ベースのコンポーネント(Dialog, Popover, Sheet, Collapsible 等)は、アクセシビリティ(フォーカストラップ、スクロールロック、キーボード操作)を標準で備えています。
- これらを
useEffectで手動実装(例:overflow: hiddenの制御)することは禁止です。 - Tailwind CSS v4 への準拠:
- スタイルは CSS 変数(
--color-primary等)とdata-slot属性を用いて管理します。 - アニメーションは
index.css内の最新の@theme inline定義を使用してください。 - グローバル・プロバイダーの管理:
Toasterはapps/storefront/src/layout/root-layout.tsx、TooltipProviderはapps/storefront/src/providers.tsxに配置します。- 新しいグローバル機能を追加した際は、必ずルートレイアウト・プロバイダーへの配置状況を確認してください。
- モノレポ構成の維持:
- コンポーネントのソース(primitive)は
packages/uiに置き、各アプリ(apps/storefront等)のcomponents/ui/で export または必要に応じた wrapper を作成する構成を遵守してください。
ディレクトリ・ファイル管理¶
ディレクトリ管理ルール¶
- ルートディレクトリ直下に一時ファイルやログを直接作成しない。
- HMR / watch / build / Docker 転送の入力ではない生成物を app/package root 配下へ出さない。
- 見返す成果物(Playwright / Vitest / Cosmos / coverage / screenshot /
report / SMILE export など)は repo root の
output/を使用する。 - 再生成可能な cache / state / pid / log / auth storage は repo root の
tmp/を使用する。 apps/*/tmp、apps/*/test-results、apps/*/coverage、apps/*/.wrangler、packages/*/tmp、packages/*/coverage、playwright-ct/.cache、static/email/test-emails、exports/smileなどを新しい生成先にしない。境界検査はpnpm run lint:generated-boundariesを使う。
命名安定化ルール¶
- repo 管理対象の 文書・補助資料・補助スクリプト は、原則 ASCII の lowercase kebab-case に統一する。
README.md,AGENTS.md,SKILL.md,CHANGELOG.md,Dockerfile*,justfile,Makefileなどの ecosystem 標準ファイル名は例外として維持する。- ソースコードは universal に kebab-case へ寄せず、各ディレクトリの
AGENTS.mdと framework / runtime 慣例を優先する。たとえば React Dashboard の PascalCase コンポーネント、TypeORM migration の timestamp+snake_case、GitHub Actions の*.ymlはローカル規約として扱う。 - TypeORM migration の timestamp は 13 桁 epoch-ms (
Date.now()) を正本とする。 TypeORM/Vendure CLI の公式形式に揃え、pnpm migrate:generateで生成すれば 自動的にこの形式になる。手書きで作る場合もnode -e 'console.log(Date.now())'を使い、<13桁>_<snake_case>.ts(Ritsubi 慣行) または<13桁>-<PascalCase>.ts(TypeORM CLI 既定) のどちらかにする。 class 名は<PascalCase><13桁>の形で末尾を timestamp で締める (nameプロパティは class 名と完全一致させる)。 既存の 14 桁YYYYMMDDhhmmss形式は legacy で、prod DB のmigrationsテーブルに記録済みのため rename はしない。scripts/ci/vendure-data-guards.mjsは HEAD に既に存在する 14 桁 file だけを grandfather し、HEAD に存在しない新規 14 桁 migration は fail させる。 新規での 14 桁採用は禁止。軽量検査はpnpm run lint:vendure-migration-timestampsで実行でき、pre-commit / pre-push でも migration 変更時に同じ検査が走る。 __screenshots__/のような snapshot fixture 名、外部識別子(host 名・module 名・font 名・受領 asset 名)を写したファイル名も例外として扱う。.playwright-cli//.playwright-mcp//.wrangler/は tool state なので repo root / app root の正本にはしない。docs/直下の新規トップレベルディレクトリ追加は既存 taxonomy を優先し、必要な場合でもdocs/documentation-rules.md/docs/index.md/.mkdocs/dev.ymlを同時更新する。
ACF スキーマ管理 (WordPress)¶
- 正本は
apps/wordpress-cms/plugins/ritsubi-ec-plugin/acf-json/配下の JSON。 - 管理画面で直接編集せず、コードベースで更新する。
特定ツールの運用ルール¶
UI プレビュー運用ルール¶
- ルールの正本:
/docs/07-frontend/ui-preview-guidelines.mdを参照。
VSCode Tasks & Launch¶
- ルートのオーケストレーションは
justfileを正とし、.vscode/tasks.jsonはjust経由で呼ぶ。 - VSCode タスク定義はルート
.vscode/tasks.jsonに集約し、アプリ配下には配置しない。 - アプリ固有コマンドが必要な場合も、ルートタスクから
justまたはpnpmを呼び出す。
Vitest¶
- Vitest には Jest の
--runInBandを渡さない。単一ファイルを確認する場合はpnpm --dir <app> exec vitest run <test-file>を使う。
依存関係管理 (pnpm catalogs)¶
- 可能な限りルートの
catalog:に共通化する。 catalogs.frontend/catalogs.backendはバージョン競合が発生するツールのみに使用。wranglerは root catalog を正本とし、app ごとの個別 pin を増やさない。wranglerの更新では npm の absolute latest をそのまま追わず、minimumReleaseAge: 3 daysを満たす「採用可能な最新成熟版」を選ぶ。必要性が明確でない限りminimumReleaseAgeExcludeに追加しない。overridesは原則使用禁止。
パフォーマンスとメモリ管理 (Storefront & Cloudflare)¶
Cloudflare Workers (Edge Runtime) のメモリ制限(通常 128MB)および、長時間セッションでのブラウザメモリ肥大化を防止するため、以下の最適化を適用しています。
1. Vite アセット配信 (Client-side)¶
ブラウザ側では Vite build のハッシュ付き /assets/* を長期キャッシュ前提で配信し、
Cloudflare Workers 側は ASSETS binding と SPA fallback に責務を限定します。
apps/storefront/vite.config.tsapps/storefront/worker.jsapps/storefront/wrangler.toml
2. TanStack Query キャッシュ制御 (Client-side)¶
GraphQL 取得結果は queryKey ごとに管理し、古い値は gcTime と invalidateQueries
で制御します。
packages/sdk/shop/src/query-client.tsstaleTime: 30_000gcTime: 5 * 60_000
3. Sentry サンプリングレート (Server/Client/Edge)¶
パフォーマンス監視のオーバーヘッドとバッファリングを最小限に抑えます。
tracesSampleRate:- Production: 0.1 (10%)
- Development: 1.0 (100%)
4. ルート loader / バルクデータ取得の制限¶
route loader や Worker request 中に大量のデータをメモリへ読み込む処理は、Worker のメモリ制限超過 (500 Error) を招くため厳禁です。
- WordPress 取得: 全件取得(バルク取得)を避け、可能な限り個別のクエリまたはページネーションを使用する。
- MSW: 本番環境ではサーバーサイド MSW が絶対に起動しないようガードを徹底する。