cmx-sdk 0.2.9 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/add-studio-YUDYE2OH.js +0 -0
  2. package/dist/chunk-7TDMLYBI.js +0 -0
  3. package/dist/chunk-EDXXR5BE.js +0 -0
  4. package/dist/chunk-FPQYL5GE.js +0 -0
  5. package/dist/chunk-IIQLQIDP.js +0 -0
  6. package/dist/chunk-NZQ6SBFS.js +0 -0
  7. package/dist/{chunk-EZMBZWH7.js → chunk-Y3S3K6M3.js} +73 -28
  8. package/dist/cli.js +2 -2
  9. package/dist/init-FLRQXJX4.js +0 -0
  10. package/dist/{interactive-menu-FYVOQSTL.js → interactive-menu-5PRQIESI.js} +1 -1
  11. package/dist/studio-HAS6DYLO.js +0 -0
  12. package/dist/{update-sdk-KJZ6VB4M.js → update-sdk-ZXMWQF3I.js} +2 -1
  13. package/dist/update-studio-TWCYSYIS.js +0 -0
  14. package/package.json +14 -16
  15. package/templates/AGENTS.md +0 -173
  16. package/templates/CLAUDE.md +0 -28
  17. package/templates/claude/commands/check.md +0 -64
  18. package/templates/claude/commands/next-action.md +0 -66
  19. package/templates/claude/skills/cmx-cache/SKILL.md +0 -50
  20. package/templates/claude/skills/cmx-cache/references/cache-patterns.md +0 -153
  21. package/templates/claude/skills/cmx-component/SKILL.md +0 -108
  22. package/templates/claude/skills/cmx-component/references/component-schema.md +0 -123
  23. package/templates/claude/skills/cmx-content/SKILL.md +0 -158
  24. package/templates/claude/skills/cmx-content/references/migration-patterns.md +0 -120
  25. package/templates/claude/skills/cmx-content/references/seed-patterns.md +0 -146
  26. package/templates/claude/skills/cmx-dev/SKILL.md +0 -266
  27. package/templates/claude/skills/cmx-dev/references/api-patterns.md +0 -220
  28. package/templates/claude/skills/cmx-dev/references/cli-reference.md +0 -54
  29. package/templates/claude/skills/cmx-form/SKILL.md +0 -103
  30. package/templates/claude/skills/cmx-form/references/form-template.md +0 -152
  31. package/templates/claude/skills/cmx-migrate/SKILL.md +0 -501
  32. package/templates/claude/skills/cmx-migrate/references/analysis-guide.md +0 -127
  33. package/templates/claude/skills/cmx-migrate/references/html-to-mdx.md +0 -99
  34. package/templates/claude/skills/cmx-migrate/references/intermediate-format.md +0 -196
  35. package/templates/claude/skills/cmx-migrate/references/tool-setup.md +0 -150
  36. package/templates/claude/skills/cmx-schema/SKILL.md +0 -159
  37. package/templates/claude/skills/cmx-schema/references/field-types.md +0 -164
  38. package/templates/claude/skills/cmx-schema/references/migration-scenarios.md +0 -44
  39. package/templates/claude/skills/cmx-seo/SKILL.md +0 -54
  40. package/templates/claude/skills/cmx-seo/references/seo-patterns.md +0 -216
  41. package/templates/claude/skills/cmx-style/SKILL.md +0 -48
  42. package/templates/claude/skills/cmx-style/references/style-patterns.md +0 -114
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -6,15 +6,17 @@ import {
6
6
  getAddDependencyCommand,
7
7
  readSdkVersion
8
8
  } from "./chunk-EDXXR5BE.js";
9
+ import {
10
+ cleanupTempFile,
11
+ downloadTarball
12
+ } from "./chunk-IIQLQIDP.js";
9
13
 
10
14
  // src/commands/update-sdk.ts
11
15
  import { execSync } from "child_process";
12
- import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
16
+ import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
17
+ import { tmpdir } from "os";
13
18
  import { dirname, join } from "path";
14
- import { fileURLToPath } from "url";
15
- var __filename = fileURLToPath(import.meta.url);
16
- var __dirname = dirname(__filename);
17
- var SDK_ROOT = join(__dirname, "..", "..");
19
+ import { extract } from "tar";
18
20
  function resolveRequestedVersion(version) {
19
21
  if (version === void 0) return "latest";
20
22
  const normalized = version.trim();
@@ -23,27 +25,25 @@ function resolveRequestedVersion(version) {
23
25
  }
24
26
  return normalized;
25
27
  }
26
- function syncClaudeCommands(projectRoot) {
27
- const templatesDir = join(SDK_ROOT, "templates", "claude", "commands");
28
- if (!existsSync(templatesDir)) return;
29
- const destDir = join(projectRoot, ".claude", "commands");
30
- mkdirSync(destDir, { recursive: true });
31
- cpSync(templatesDir, destDir, { recursive: true, force: true });
32
- console.log(" \u2705 .claude/commands \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F");
33
- }
34
- function syncClaudeSkills(projectRoot) {
35
- const templatesDir = join(SDK_ROOT, "templates", "claude", "skills");
36
- if (!existsSync(templatesDir)) return;
37
- const destDir = join(projectRoot, ".claude", "skills");
38
- mkdirSync(destDir, { recursive: true });
39
- cpSync(templatesDir, destDir, { recursive: true, force: true });
40
- console.log(" \u2705 .claude/skills \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F");
28
+ function readProjectCmxConfig(projectRoot) {
29
+ const envFiles = [".env.local", ".env"];
30
+ for (const envFile of envFiles) {
31
+ const envPath = join(projectRoot, envFile);
32
+ if (!existsSync(envPath)) continue;
33
+ try {
34
+ const content = readFileSync(envPath, "utf-8");
35
+ const apiUrl = content.match(/^CMX_API_URL=(.+)$/m)?.[1]?.trim();
36
+ const apiKey = content.match(/^CMX_API_KEY=(.+)$/m)?.[1]?.trim();
37
+ if (apiUrl && apiKey) {
38
+ return { apiUrl, apiKey };
39
+ }
40
+ } catch {
41
+ }
42
+ }
43
+ return null;
41
44
  }
42
- function syncManagedFile(projectRoot, relativePath) {
43
- const templatePath = join(SDK_ROOT, "templates", relativePath);
44
- if (!existsSync(templatePath)) return;
45
+ function syncManagedFileFromContent(projectRoot, relativePath, templateContent) {
45
46
  const destPath = join(projectRoot, relativePath);
46
- const templateContent = readFileSync(templatePath, "utf-8");
47
47
  if (!existsSync(destPath)) {
48
48
  mkdirSync(dirname(destPath), { recursive: true });
49
49
  writeFileSync(destPath, templateContent);
@@ -69,6 +69,40 @@ function syncManagedFile(projectRoot, relativePath) {
69
69
  console.log(` \u2705 ${relativePath} \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F\uFF08${updatedBlocks} \u30D6\u30ED\u30C3\u30AF\uFF09`);
70
70
  }
71
71
  }
72
+ async function syncFromApi(projectRoot, apiUrl, apiKey) {
73
+ const tmpFile = join(tmpdir(), `.tmp-starter-kit-${Date.now()}.tar.gz`);
74
+ const tmpExtractDir = join(tmpdir(), `.tmp-starter-kit-extract-${Date.now()}`);
75
+ try {
76
+ await downloadTarball(`${apiUrl}/api/v1/sdk/download/starter-kit`, tmpFile, {
77
+ headers: { Authorization: `Bearer ${apiKey}` }
78
+ });
79
+ mkdirSync(tmpExtractDir, { recursive: true });
80
+ await extract({
81
+ file: tmpFile,
82
+ cwd: tmpExtractDir,
83
+ strip: 1,
84
+ filter: (entryPath) => entryPath.includes("/.claude/") || entryPath.endsWith("/AGENTS.md") || entryPath.endsWith("/CLAUDE.md")
85
+ });
86
+ const extractedClaude = join(tmpExtractDir, ".claude");
87
+ if (existsSync(extractedClaude)) {
88
+ mkdirSync(join(projectRoot, ".claude"), { recursive: true });
89
+ cpSync(extractedClaude, join(projectRoot, ".claude"), { recursive: true, force: true });
90
+ console.log(" \u2705 .claude/ \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F");
91
+ }
92
+ for (const filename of ["AGENTS.md", "CLAUDE.md"]) {
93
+ const extractedFile = join(tmpExtractDir, filename);
94
+ if (existsSync(extractedFile)) {
95
+ syncManagedFileFromContent(projectRoot, filename, readFileSync(extractedFile, "utf-8"));
96
+ }
97
+ }
98
+ } finally {
99
+ cleanupTempFile(tmpFile);
100
+ try {
101
+ rmSync(tmpExtractDir, { recursive: true, force: true });
102
+ } catch {
103
+ }
104
+ }
105
+ }
72
106
  async function updateSdk(options = {}) {
73
107
  console.log("\n cmx-sdk \u306E\u4F9D\u5B58\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u66F4\u65B0\u3057\u307E\u3059...\n");
74
108
  const projectRoot = findProjectRoot();
@@ -103,10 +137,21 @@ async function updateSdk(options = {}) {
103
137
  console.log("\n \u2705 cmx-sdk \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F\uFF01");
104
138
  console.log(` \u66F4\u65B0\u5F8C\u30D0\u30FC\u30B8\u30E7\u30F3: ${updatedVersion ?? "\u4E0D\u660E"}`);
105
139
  console.log("\n \u23F3 Claude Code \u30D5\u30A1\u30A4\u30EB\u3092\u66F4\u65B0\u4E2D...");
106
- syncClaudeCommands(projectRoot);
107
- syncClaudeSkills(projectRoot);
108
- syncManagedFile(projectRoot, "AGENTS.md");
109
- syncManagedFile(projectRoot, "CLAUDE.md");
140
+ const cmxConfig = readProjectCmxConfig(projectRoot);
141
+ if (!cmxConfig) {
142
+ console.warn(" \u26A0\uFE0F CMX_API_URL / CMX_API_KEY \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093");
143
+ console.warn(" .env.local \u306B\u8A2D\u5B9A\u3059\u308B\u3068 .claude/ / AGENTS.md / CLAUDE.md \u3082\u81EA\u52D5\u66F4\u65B0\u3055\u308C\u307E\u3059\n");
144
+ } else {
145
+ try {
146
+ console.log(" \u23F3 \u30B9\u30BF\u30FC\u30BF\u30FC\u30AD\u30C3\u30C8\u304B\u3089\u6700\u65B0\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u5F97\u4E2D...");
147
+ await syncFromApi(projectRoot, cmxConfig.apiUrl, cmxConfig.apiKey);
148
+ } catch (error) {
149
+ console.error(
150
+ ` \u274C Claude Code \u30D5\u30A1\u30A4\u30EB\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${error instanceof Error ? error.message : "\u4E0D\u660E\u306A\u30A8\u30E9\u30FC"}
151
+ `
152
+ );
153
+ }
154
+ }
110
155
  console.log("\n \u6B21\u306E\u30B9\u30C6\u30C3\u30D7:");
111
156
  console.log(" 1. \u578B\u751F\u6210\u3092\u518D\u5B9F\u884C");
112
157
  console.log(" npx cmx-sdk codegen types");
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-FPQYL5GE.js";
8
8
  import {
9
9
  updateSdk
10
- } from "./chunk-EZMBZWH7.js";
10
+ } from "./chunk-Y3S3K6M3.js";
11
11
  import "./chunk-NZQ6SBFS.js";
12
12
  import "./chunk-EDXXR5BE.js";
13
13
  import "./chunk-IIQLQIDP.js";
@@ -4204,7 +4204,7 @@ function requireApiCredentials() {
4204
4204
  return { apiUrl, apiKey };
4205
4205
  }
4206
4206
  program.action(async () => {
4207
- const { interactiveMenu } = await import("./interactive-menu-FYVOQSTL.js");
4207
+ const { interactiveMenu } = await import("./interactive-menu-5PRQIESI.js");
4208
4208
  await interactiveMenu();
4209
4209
  });
4210
4210
  program.command("init [project-name]").description("\u65B0\u3057\u3044 CMX \u30B5\u30A4\u30C8\u3092\u4F5C\u6210").option("--no-studio", "CMX Studio \u3092\u30B9\u30AD\u30C3\u30D7").option("--pm <manager>", "\u30D1\u30C3\u30B1\u30FC\u30B8\u30DE\u30CD\u30FC\u30B8\u30E3\u30FC (npm, pnpm, yarn)").option("--key <key>", "CMX API \u30AD\u30FC\uFF08\u5FC5\u9808\u3002\u672A\u6307\u5B9A\u6642\u306F\u30D7\u30ED\u30F3\u30D7\u30C8\u8868\u793A\uFF09").option("--api-url <url>", "CMX API \u30B5\u30FC\u30D0\u30FC\u306E URL").action(async (projectName, options) => {
File without changes
@@ -31,7 +31,7 @@ async function interactiveMenu() {
31
31
  return updateStudio({});
32
32
  }
33
33
  case "update-sdk": {
34
- const { updateSdk } = await import("./update-sdk-KJZ6VB4M.js");
34
+ const { updateSdk } = await import("./update-sdk-ZXMWQF3I.js");
35
35
  return updateSdk({});
36
36
  }
37
37
  case "studio": {
File without changes
@@ -2,8 +2,9 @@
2
2
  import {
3
3
  resolveRequestedVersion,
4
4
  updateSdk
5
- } from "./chunk-EZMBZWH7.js";
5
+ } from "./chunk-Y3S3K6M3.js";
6
6
  import "./chunk-EDXXR5BE.js";
7
+ import "./chunk-IIQLQIDP.js";
7
8
  export {
8
9
  resolveRequestedVersion,
9
10
  updateSdk
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cmx-sdk",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "CMX SDK - Official SDK for building content-driven websites with CMX",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,7 +26,6 @@
26
26
  ],
27
27
  "files": [
28
28
  "dist",
29
- "templates",
30
29
  "README.md"
31
30
  ],
32
31
  "exports": {
@@ -35,19 +34,6 @@
35
34
  "import": "./dist/index.js"
36
35
  }
37
36
  },
38
- "scripts": {
39
- "prebuild": "node scripts/copy-api-client.js",
40
- "sync:starter-kit-docs": "pnpm --filter @cmx/api-server generate:openapi && node scripts/sync-starter-kit-docs.mjs --write",
41
- "sync:starter-kit-docs:check": "pnpm --filter @cmx/api-server generate:openapi && node scripts/sync-starter-kit-docs.mjs --check",
42
- "check:sdk-command-api-usage": "node scripts/check-sdk-command-api-usage.mjs",
43
- "check:generated-sync": "node scripts/check-generated-sync.mjs",
44
- "test:contracts": "tsx scripts/check-cli-contracts.ts",
45
- "verify:release": "pnpm run check:sdk-command-api-usage && pnpm run check:generated-sync && pnpm run test:contracts",
46
- "build": "tsup",
47
- "dev": "tsup --watch",
48
- "typecheck": "tsc --noEmit",
49
- "prepublishOnly": "pnpm run verify:release && pnpm run sync:starter-kit-docs:check && pnpm run build"
50
- },
51
37
  "dependencies": {
52
38
  "@inquirer/prompts": "^8.2.1",
53
39
  "@mdx-js/mdx": "^3.1.1",
@@ -70,5 +56,17 @@
70
56
  "tsup": "^8.5.1",
71
57
  "tsx": "^4.21.0",
72
58
  "typescript": "^5.9.3"
59
+ },
60
+ "scripts": {
61
+ "prebuild": "node scripts/copy-api-client.js",
62
+ "sync:starter-kit-docs": "pnpm --filter @cmx/api-server generate:openapi && node scripts/sync-starter-kit-docs.mjs --write",
63
+ "sync:starter-kit-docs:check": "pnpm --filter @cmx/api-server generate:openapi && node scripts/sync-starter-kit-docs.mjs --check",
64
+ "check:sdk-command-api-usage": "node scripts/check-sdk-command-api-usage.mjs",
65
+ "check:generated-sync": "node scripts/check-generated-sync.mjs",
66
+ "test:contracts": "tsx scripts/check-cli-contracts.ts",
67
+ "verify:release": "pnpm run check:sdk-command-api-usage && pnpm run check:generated-sync && pnpm run test:contracts",
68
+ "build": "tsup",
69
+ "dev": "tsup --watch",
70
+ "typecheck": "tsc --noEmit"
73
71
  }
74
- }
72
+ }
@@ -1,173 +0,0 @@
1
- # CMX Starter Kit — AI Agent Instructions
2
-
3
- このファイルはAIコーディングエージェント(Claude Code, Cursor, GitHub Copilot, Google Jules 等)向けの共通指示書です。
4
-
5
- > **注意:** `<!-- cmx-sdk:start -->` ~ `<!-- cmx-sdk:end -->` の範囲は `npx cmx-sdk update-sdk` で自動更新されます。
6
- > その範囲外はカスタマイズ可能です。
7
-
8
- ## サイト設定
9
-
10
- サイト固有の設定は以下を参照:
11
-
12
- → cmx/site-config.md — 開発方針(種別・トーン・デザイン方針・禁止事項)
13
- → cmx-workflow/style-guide.md — 執筆ルール(文体・用語・記事構成、別配布)
14
-
15
- すべてのコード変更・提案は site-config.md の方針と矛盾しないことを確認すること。
16
- コンテンツ生成時は style-guide.md のトーン・フォーマットに従うこと。
17
-
18
- ---
19
-
20
- <!-- cmx-sdk:start id="architecture" -->
21
- ## アーキテクチャ
22
-
23
- CMX Starter Kit はヘッドレスCMSのフロントエンドテンプレートです。
24
-
25
- ```
26
- CMX Admin(サービス側) Starter Kit(このリポジトリ)
27
- ┌─────────────────────┐ ┌──────────────────────────┐
28
- │ コレクション / データタイプ │ Public │ Next.js 16 (App Router) │
29
- │ 投稿 / アセット / フォーム │ API │ cmx-sdk でデータ取得 │
30
- │ │◄─────────│ Cloudflare Workers デプロイ │
31
- │ APIキー ─────────────────────────│ .env の CMX_API_KEY で認証 │
32
- └─────────────────────┘ └──────────────────────────┘
33
- ```
34
-
35
- ### 厳守ルール
36
-
37
- - **すべてのデータ取得は `cmx-sdk` 経由。** DB直接アクセスは存在しない
38
- - **サーバーコンポーネントがデフォルト。** クライアントコンポーネントは必要最小限に
39
- - **CMXデータを取得するページには `export const dynamic = "force-dynamic"` を必ず付ける**
40
- - **MDXレンダリングは `src/lib/mdx/render.tsx` の `renderMdx` を使う。** 独自のMDX処理を書かない
41
- - **カスタムコンポーネントは `src/components/custom/index.ts` から export する。** export すれば MDX 内で自動的に使用可能になる
42
- - **`cmx/generated/` 配下のファイルは手動編集禁止。** `npx cmx-sdk codegen types` で再生成する
43
-
44
- ### 独自実装の禁止
45
-
46
- - **独自の API クライアントや fetch ラッパーを作成しない。** `cmx-sdk` と `@/lib/` 配下の既存関数のみ使用する
47
- - **`cmx-sdk` にない機能が必要な場合、独自実装せずユーザーに相談する**
48
-
49
- ### エラー時の行動規範
50
-
51
- 1. **1回リトライ**する
52
- 2. リトライでも解決しない場合、**代替手段を勝手に実装せず、ユーザーに報告して確認を取る**
53
- <!-- cmx-sdk:end -->
54
-
55
- ---
56
-
57
- <!-- cmx-sdk:start id="env-vars" -->
58
- ## 環境変数
59
-
60
- | 変数名 | 必須 | 説明 |
61
- |--------|------|------|
62
- | `CMX_API_KEY` | 必須 | CMX Admin で発行した API キー |
63
- | `CMX_API_URL` | 必須 | CMX Admin インスタンスの URL |
64
- | `CMX_WORKSPACE_ID` | 任意 | ワークスペースID(APIキーから自動判定) |
65
- | `NEXT_PUBLIC_SITE_URL` | 必須 | 公開サイトの URL |
66
- | `REVALIDATE_API_KEY` | 任意 | リバリデーション用の秘密鍵 |
67
- <!-- cmx-sdk:end -->
68
-
69
- ---
70
-
71
- <!-- cmx-sdk:start id="commands" -->
72
- ## コマンド
73
-
74
- ```bash
75
- pnpm dev # 開発サーバー起動(Turbopack, port 4000)
76
- pnpm build # Next.js ビルド
77
- pnpm build:cf # Cloudflare Workers 向けビルド
78
- pnpm deploy # Cloudflare Workers デプロイ
79
- pnpm typecheck # TypeScript 型チェック
80
- pnpm lint # ESLint
81
- npx cmx-sdk sync-components # カスタムコンポーネントを Admin に同期
82
- npx cmx-sdk components scaffold --name FeatureCard # コンポーネント雛形を生成
83
- npx cmx-sdk codegen types # スキーマから型付きコードを自動生成
84
- npx cmx-sdk codegen pages --template layered # ページ雛形(resolver/meta/view分離)を生成
85
- npx cmx-sdk codegen check # 生成コードと import/tsconfig の整合を検証
86
- npx cmx-sdk codegen all # types → pages → check を一括実行
87
- npx cmx-sdk mdx validate # MDX本文の構文/禁止構文/props を検証
88
- npx cmx-sdk mdx doctor # MDX定義JSONと実装/exportの整合を検証
89
- npx cmx-sdk create-collection --json '...' # コレクションを API 経由で作成
90
- npx cmx-sdk create-data-type --json '...' # データタイプを API 経由で作成
91
- npx cmx-sdk create-data-entry --type-slug {slug} --json '...' # データエントリを作成
92
- npx cmx-sdk list-collection-data-types --collection {slug} # コレクションの付属データタイプ一覧
93
- npx cmx-sdk list-collection-presets --type {type} # プリセット一覧(おすすめ/その他)
94
- npx cmx-sdk update-sdk # SDK・コマンド・スキルを最新版に更新
95
- ```
96
- <!-- cmx-sdk:end -->
97
-
98
- ---
99
-
100
- <!-- cmx-sdk:start id="setup-flow" -->
101
- ## 開発フロー
102
-
103
- ### 初期構築
104
-
105
- ```
106
- 1. サイトコンフィグ作成 cmx/site-config.md を作成
107
- 2. 環境セットアップ .env.local 設定 → pnpm install → pnpm dev
108
- 3. スキーマ設計 コレクション・データタイプの JSON 定義を作成
109
- → create-collection / create-data-type コマンドで登録
110
- 4. テストデータ投入 Admin 側でコンテンツを作成し「公開」にする
111
- 5. コード生成 npx cmx-sdk codegen types で型付き関数を生成
112
- 6. 雛形生成(任意) npx cmx-sdk codegen pages --template layered
113
- 7. ページ実装 一覧ページ・詳細ページ・静的ページを作成
114
- 8. コンポーネント作成 MDX 用カスタムコンポーネントを定義・実装・同期
115
- 9. デプロイ pnpm build:cf && pnpm deploy
116
- ```
117
- <!-- cmx-sdk:end -->
118
-
119
- ---
120
-
121
- <!-- cmx-sdk:start id="api-patterns" -->
122
- ## API パターン
123
-
124
- ### データ取得
125
-
126
- ```tsx
127
- // cmx-sdk 直接(汎用)
128
- import { getCollectionContents, getCollectionContentDetail, getDataEntries, getDataEntry } from "cmx-sdk"
129
-
130
- // re-export 経由(推奨)
131
- import { getCollectionContents, getCollectionContentDetail, getDataEntries } from "@/lib/api/admin-client"
132
-
133
- // エラー時 throw するラッパー(ページで使用)
134
- import { requireFetchContents, requireFetchContent, requireDataEntries } from "@/lib/utils/data-fetching"
135
-
136
- // 型付き自動生成関数(npx cmx-sdk codegen types 後)
137
- import { getBlogContents, getBlogContentDetail } from "@cmx/generated"
138
- import { getStaff, getStaffById } from "@cmx/generated"
139
- ```
140
-
141
- ### ページテンプレート: コレクション一覧
142
-
143
- ```tsx
144
- // src/app/{collection}/page.tsx
145
- import { COLLECTION_SLUGS } from "@/lib/constants/collections"
146
- import { requireFetchContents } from "@/lib/utils/data-fetching"
147
-
148
- export const dynamic = "force-dynamic"
149
-
150
- export default async function ListPage() {
151
- const { collection, contents } = await requireFetchContents(COLLECTION_SLUGS.xxx)
152
- return (/* 一覧 UI */)
153
- }
154
- ```
155
-
156
- ### ページテンプレート: コレクション詳細
157
-
158
- ```tsx
159
- // src/app/{collection}/[slug]/page.tsx
160
- import { COLLECTION_SLUGS } from "@/lib/constants/collections"
161
- import { requireFetchContent } from "@/lib/utils/data-fetching"
162
- import { renderMdx } from "@/lib/mdx/render"
163
-
164
- export const dynamic = "force-dynamic"
165
-
166
- export default async function DetailPage({ params }: { params: Promise<{ slug: string }> }) {
167
- const { slug } = await params
168
- const { content, references } = await requireFetchContent(COLLECTION_SLUGS.xxx, slug)
169
- const { content: rendered } = await renderMdx(content.mdx, references)
170
- return <article className="prose prose-lg max-w-none">{rendered}</article>
171
- }
172
- ```
173
- <!-- cmx-sdk:end -->
@@ -1,28 +0,0 @@
1
- # Claude Code 設定
2
-
3
- > **注意:** `<!-- cmx-sdk:start -->` ~ `<!-- cmx-sdk:end -->` の範囲は `npx cmx-sdk update-sdk` で自動更新されます。
4
- > その範囲外はカスタマイズ可能です。
5
-
6
- <!-- cmx-sdk:start id="project-rules" -->
7
- ## プロジェクトルール
8
-
9
- CMX Starter Kit のルール・アーキテクチャ・API パターンは `AGENTS.md` を参照。
10
-
11
- ### コミット前
12
-
13
- 変更を加えたらコミット前に必ずチェックを実行:
14
-
15
- ```bash
16
- pnpm typecheck # TypeScript 型チェック
17
- pnpm build # ビルド確認
18
- npx cmx-sdk codegen check # 生成コード整合チェック
19
- ```
20
-
21
- または Studio の「チェック」ボタンを使用。
22
- <!-- cmx-sdk:end -->
23
-
24
- ---
25
-
26
- ## プロジェクト固有の設定
27
-
28
- <!-- ここにプロジェクト固有のルールやメモを追記してください -->
@@ -1,64 +0,0 @@
1
- ---
2
- name: Check
3
- description: ビルド・型・整合性を一括チェック
4
- disable-model-invocation: true
5
- allowed-tools: Bash
6
- continuation-mode: auto
7
- ---
8
-
9
- # Check(ビルド・整合性チェック)
10
-
11
- ## 実行内容
12
-
13
- 以下をこの順番で実行する。エラーがあれば即座に報告して止まる。
14
-
15
- ### 1. TypeScript 型チェック
16
-
17
- ```bash
18
- pnpm typecheck
19
- ```
20
-
21
- ### 2. ビルド確認
22
-
23
- ```bash
24
- pnpm build
25
- ```
26
-
27
- ### 3. 生成コードと import/tsconfig の整合チェック
28
-
29
- ```bash
30
- npx cmx-sdk codegen check
31
- ```
32
-
33
- ## 出力フォーマット
34
-
35
- 成功時:
36
-
37
- ```
38
- ## チェック結果
39
-
40
- - [x] TypeScript: 型エラーなし
41
- - [x] ビルド: 成功
42
- - [x] 整合性: 問題なし
43
-
44
- ✅ すべてのチェックが通りました。
45
- ```
46
-
47
- エラー時:
48
-
49
- ```
50
- ## チェック結果
51
-
52
- - [x] TypeScript: 型エラーなし
53
- - [ ] ビルド: ❌ エラー {n} 件
54
- - [ ] 整合性: スキップ(ビルドエラーのため)
55
-
56
- 修正すべき箇所:
57
- 1. {ファイル名}:{行番号} - {エラー内容}
58
- ```
59
-
60
- ## ルール
61
-
62
- - エラーが出たステップで止め、以降のステップはスキップする
63
- - エラー内容は要約せず、そのまま出力する
64
- - 修正案がある場合は箇条書きで提示する
@@ -1,66 +0,0 @@
1
- ---
2
- name: Next Action
3
- description: 迷ったときに現在地を確認し、次にやるべきことを案内
4
- disable-model-invocation: true
5
- allowed-tools: Bash, Read, Glob, Grep
6
- continuation-mode: auto
7
- ---
8
-
9
- # Next Action
10
-
11
- ## チェック項目
12
-
13
- ### 環境
14
-
15
- - `.env.local` が存在するか
16
- - `CMX_API_KEY` が設定されているか
17
-
18
- ### サイトコンフィグ
19
-
20
- - `cmx/site-config.md` が記入済みか(「未設定」が残っていないか)
21
-
22
- ### スキーマ
23
-
24
- - `src/lib/constants/collections.ts` の登録スラッグ一覧
25
- - `cmx/generated/` の生成済みファイル一覧
26
- - 両者の不一致がないか
27
-
28
- ### ページ
29
-
30
- - `src/app/` 配下のページ一覧
31
- - 登録済みコレクションに対応するページが全て存在するか
32
- - データタイプに対応するページが存在するか
33
-
34
- ### コンポーネント
35
-
36
- - `cmx/components/` の JSON 定義一覧
37
- - `src/components/custom/index.ts` のエクスポート一覧
38
- - 定義と実装の不一致がないか
39
-
40
- ## 判定ルール
41
-
42
- - 未完了(✗ または △)の項目が1つでもある場合は、未完了優先で次アクションを案内する
43
- - すべて完了(✓)の場合は、保守・改善フェーズ向けの追加提案を出す
44
-
45
- ## 出力フォーマット
46
-
47
- ```
48
- ## Next Action(現在地)
49
-
50
- - [x] 環境: 設定済み
51
- - [ ] サイトコンフィグ: 一部未設定(未設定: {項目名...})
52
- - [x] スキーマ: 整合済み(コレクション {n} / データタイプ {n})
53
- - [ ] ページ: 未実装 {n} 件({slug...})
54
- - [x] コンポーネント: 整合済み(定義 {n} / 実装 {n})
55
-
56
- ### Next Action(最優先)
57
- - {1件だけ。具体的なコマンド付きで提示}
58
- 例: `/setup/05_pages` で未実装ページを作成する
59
-
60
- ### 追加提案
61
- - 未完了がある場合:
62
- - 未完了項目に直結する提案を最大2件
63
- - すべて完了している場合:
64
- - 保守・改善に進む提案を最大2件
65
- - 例: `/maintain/component`, `/maintain/style`, `/deploy`
66
- ```
@@ -1,50 +0,0 @@
1
- ---
2
- name: cmx-cache
3
- description: |
4
- CMX Starter Kit のキャッシュ戦略スキル。force-dynamic → ISR 切り替え、sdkFetchWithTags、CACHE_TAGS、リバリデーション設定、Cloudflare R2 キャッシュ。
5
- トリガー: 「キャッシュを設定」「ISRに切り替え」「リバリデーションを設定」
6
- 「force-dynamicを外す」「キャッシュタグを設定」「パフォーマンス改善」
7
- 「ページの表示速度を上げたい」「キャッシュ戦略」「R2キャッシュ」
8
- 「revalidateを設定」「オンデマンド再検証」など。
9
- ---
10
-
11
- # CMX キャッシュ戦略
12
-
13
- ## 現状の構成
14
-
15
- スターターキットの初期状態は全ページ `export const dynamic = "force-dynamic"`(毎リクエスト SSR)。ISR 基盤(R2 バケット、リバリデーション API)は構築済み。
16
-
17
- ## ISR 移行の判断基準
18
-
19
- | 条件 | 推奨 |
20
- |------|------|
21
- | コンテンツ更新頻度が低い | ISR(revalidate: 3600 等) |
22
- | リアルタイム性が必要 | force-dynamic のまま |
23
- | プレビューページ | 常に force-dynamic |
24
- | 静的ページ(about 等) | ISR(revalidate: 86400)または静的生成 |
25
-
26
- ## 移行手順
27
-
28
- 詳細は [references/cache-patterns.md](references/cache-patterns.md) を参照。
29
-
30
- ### 1. ページの revalidate 設定
31
-
32
- `export const dynamic = "force-dynamic"` を削除し `export const revalidate = 秒数` に変更。
33
-
34
- ### 2. タグ付き fetch に切り替え
35
-
36
- `sdkFetchWithTags` を使い、CACHE_TAGS でタグを付与。
37
-
38
- ### 3. リバリデーション API の確認
39
-
40
- `/api/revalidate` エンドポイントが動作することを確認。`REVALIDATE_API_KEY` 環境変数が必要。
41
-
42
- ### 4. Cloudflare R2 の確認
43
-
44
- `wrangler.jsonc` で R2 バケットバインディング `NEXT_INC_CACHE_R2_BUCKET` が設定済みか確認。
45
-
46
- ## 変更後
47
-
48
- 1. デプロイ後にページの `Cache-Control` ヘッダーを確認
49
- 2. コンテンツ更新後にリバリデーションが動作することを確認
50
- 3. プレビューページが常に最新データを返すことを確認