@squadbase/vantage-template 0.1.1-dev1.ac4fa22 → 0.1.1-dev1.bb2f95a

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 (34) hide show
  1. package/README.md +12 -2
  2. package/base-template/.squadbase/skills/vantage-add-feature/SKILL.md +14 -7
  3. package/base-template/.squadbase/skills/vantage-app/SKILL.md +10 -6
  4. package/base-template/.squadbase/skills/vantage-design/SKILL.md +60 -52
  5. package/base-template/.squadbase/skills/vantage-design/references/extract.md +26 -27
  6. package/base-template/.squadbase/skills/vantage-design/references/format.md +12 -172
  7. package/base-template/.squadbase/skills/vantage-design/references/presets.md +50 -110
  8. package/base-template/.squadbase/skills/vantage-pitfalls/SKILL.md +50 -1
  9. package/base-template/.squadbase/skills/vantage-slide/SKILL.md +299 -0
  10. package/base-template/.squadbase/skills/vantage-slide/references/morph.md +102 -0
  11. package/base-template/.squadbase/skills/vantage-slide/references/steps.md +57 -0
  12. package/base-template/.squadbase/skills/vantage-slide/references/tokens.md +87 -0
  13. package/base-template/.squadbase/skills/vantage-slide/references/transitions.md +196 -0
  14. package/base-template/AGENTS.md +121 -21
  15. package/base-template/agents/api.md +7 -0
  16. package/base-template/agents/csv.md +2 -1
  17. package/base-template/agents/doc.md +52 -3
  18. package/base-template/agents/page.md +91 -10
  19. package/base-template/agents/slide.md +77 -3
  20. package/base-template/agents/xlsx.md +2 -1
  21. package/base-template/bun.lock +79 -69
  22. package/base-template/bunfig.toml +5 -0
  23. package/base-template/package.json +6 -6
  24. package/base-template/src/_layout.tsx +13 -6
  25. package/base-template/src/components/build-recovery.tsx +37 -1
  26. package/base-template/src/components/user-card.tsx +11 -11
  27. package/base-template/src/index.tsx +1 -1
  28. package/base-template/src/styles.css +105 -18
  29. package/dist/index.js +956 -0
  30. package/package.json +20 -17
  31. package/ui-templates/CLAUDE.md +2 -0
  32. package/ui-templates/kpi-chart-simple/pages/index.tsx +47 -47
  33. package/ui-templates/kpi-chart-simple-ja/pages/index.tsx +47 -47
  34. package/base-template/DESIGN.md +0 -108
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squadbase/vantage-template",
3
- "version": "0.1.1-dev1.ac4fa22",
3
+ "version": "0.1.1-dev1.bb2f95a",
4
4
  "description": "CLI tool for initializing and customizing Squadbase Vantage projects.",
5
5
  "keywords": [
6
6
  "squadbase",
@@ -36,29 +36,32 @@
36
36
  "access": "public",
37
37
  "registry": "https://registry.npmjs.org"
38
38
  },
39
- "scripts": {
40
- "sync-base": "rsync -a --delete --exclude='node_modules' --exclude='dist' --exclude='.vantage' --exclude='*.tsbuildinfo' --exclude='*.log' template/ base-template/ && mv base-template/.gitignore base-template/_gitignore",
41
- "build": "npm run sync-base && tsup",
42
- "type-check": "tsc",
43
- "agents": "node scripts/build-agents.cjs",
44
- "agents:check": "node scripts/build-agents.cjs --check",
45
- "template:install": "bun install --cwd template --frozen-lockfile",
46
- "template:build": "npm --prefix template run build",
47
- "prepublishOnly": "npm run agents:check && npm run build",
48
- "release": "npm publish --@squadbase:registry=https://registry.npmjs.org",
49
- "dev": "node scripts/dev.mjs",
50
- "screenshot": "node scripts/screenshot.mjs"
51
- },
52
39
  "devDependencies": {
53
40
  "@types/node": "^22.15.0",
54
41
  "playwright": "^1.49.0",
55
42
  "tsup": "^8.4.0",
56
- "typescript": "~5.7.0"
43
+ "typescript": "~5.7.0",
44
+ "vitest": "^5.0.5",
45
+ "@squadbase/squadkit": "0.0.0"
57
46
  },
58
47
  "optionalDependencies": {
59
48
  "@ai-sdk/anthropic": "^2.0.0",
60
49
  "@ai-sdk/google": "^2.0.0",
61
- "@ai-sdk/openai": "^2.0.0",
50
+ "@ai-sdk/openai": "2.0.122",
62
51
  "ai": "^5.0.52"
52
+ },
53
+ "gitHead": "bb2f95a39a1a3f6b111cea5f59b677f4f92b9037",
54
+ "scripts": {
55
+ "sync-base": "rsync -a --delete --exclude='node_modules' --exclude='dist' --exclude='.vantage' --exclude='*.tsbuildinfo' --exclude='*.log' template/ base-template/ && mv base-template/.gitignore base-template/_gitignore",
56
+ "build": "pnpm run sync-base && tsup",
57
+ "type-check": "tsc",
58
+ "test": "vitest run",
59
+ "agents": "node scripts/build-agents.cjs",
60
+ "agents:check": "node scripts/build-agents.cjs --check",
61
+ "template:install": "bun install --cwd template --frozen-lockfile",
62
+ "template:build": "bun run --cwd template build",
63
+ "release": "pnpm publish --@squadbase:registry=https://registry.npmjs.org",
64
+ "dev": "node scripts/dev.mjs",
65
+ "screenshot": "node scripts/screenshot.mjs"
63
66
  }
64
- }
67
+ }
@@ -96,6 +96,8 @@ server/api/<endpoint>.ts # ★ サンプルデータ + GET ハ
96
96
  | --- | --- |
97
97
  | `PageShell*` / `DashboardCard*` / `EChart` / `EChartsOption` / `DataTable*` / `ColumnDef` / `DateRangePicker` / `FilterBar*` / `FunnelSteps` / `MetricValue` / `TrendIndicator` / `StatusBadge` / `SegmentedControl` / `MultiSelect` / `SearchableSelect` / `SectionHeader` / `AppShell` / `Placeholder` / `Sparkline` | `@squadbase/vantage/components` |
98
98
  | `Button` / `Input` / `Badge` / `Tabs*` / `ToggleGroup*` / `Table*` / `Select*` / `Dialog*` / `cn` ほか shadcn プリミティブ | `@squadbase/vantage/ui` |
99
+
100
+ 型付きチャート(`LineChart` / `AreaChart` / `BarChart` / `DonutChart` / `BarList` / `CategoryBar` / `ProgressCircle` / `Tracker`、`@squadbase/vantage/components`)と `Avatar` / `Pagination` / `RadioGroup` / `AlertDialog` / `Drawer` / `Toaster` / `Field` / `Combobox` / `HoverCard` / `Kbd`(`@squadbase/vantage/ui`)は 0.6.3 で入った。雛形の依存が `^0.5.3` の間は使わない(上の EChart の書き方のまま)。
99
101
  | `definePage` | `@squadbase/vantage` |
100
102
  | `Link` / `Outlet` / `useParams` / `useSearch` / `useNavigate` / `useRoutes` / `useCurrentRoute` / `useSearchParam` / `useSearchState` | `@squadbase/vantage/router` |
101
103
  | `useApiQuery` / `useApiMutation` / `useQuery` / `useMutation` / `apiFetch` | `@squadbase/vantage/query` |
@@ -104,6 +104,53 @@ const RANGE_OPTIONS: SegmentOption[] = [
104
104
  { label: "90 days", value: "90d" },
105
105
  ]
106
106
 
107
+ export default function HomePage() {
108
+ // Filter state belongs in the URL rather than `useState`: it survives a
109
+ // reload, and a pasted link reproduces exactly what you were looking at.
110
+ const [range, setRange] = useSearchParam("range", "30d")
111
+
112
+ // `search` goes into the query string *and* the cache key, so changing the
113
+ // range refetches instead of serving the previous window.
114
+ const summary = useApiQuery<KpiSummary>("/api/kpi-summary", { search: { range } })
115
+
116
+ return (
117
+ <PageShell>
118
+ <PageShellHeader>
119
+ <PageShellHeading>
120
+ <PageShellTitle>[Template] Performance overview</PageShellTitle>
121
+ <PageShellDescription>
122
+ Key metrics and trends for the selected period.
123
+ </PageShellDescription>
124
+ </PageShellHeading>
125
+ <PageShellHeaderEnd>
126
+ <SegmentedControl
127
+ options={RANGE_OPTIONS}
128
+ value={range}
129
+ onChange={setRange}
130
+ ariaLabel="Period"
131
+ />
132
+ </PageShellHeaderEnd>
133
+ </PageShellHeader>
134
+
135
+ <PageShellContent className="space-y-6">
136
+ {summary.isPending ? (
137
+ <Loading />
138
+ ) : summary.isError ? (
139
+ // `summary.error` is an `ApiError`: `message` is the text the handler
140
+ // passed to `HttpError`, so there is no cast and no generic wording.
141
+ <ErrorState
142
+ title="Could not load the dashboard"
143
+ message={summary.error.message}
144
+ action={<Button onClick={() => void summary.refetch()}>Retry</Button>}
145
+ />
146
+ ) : (
147
+ <DashboardBody data={summary.data} />
148
+ )}
149
+ </PageShellContent>
150
+ </PageShell>
151
+ )
152
+ }
153
+
107
154
  function DashboardBody({ data }: { data: KpiSummary }) {
108
155
  return (
109
156
  <>
@@ -151,50 +198,3 @@ function DashboardBody({ data }: { data: KpiSummary }) {
151
198
  </>
152
199
  )
153
200
  }
154
-
155
- export default function HomePage() {
156
- // Filter state belongs in the URL rather than `useState`: it survives a
157
- // reload, and a pasted link reproduces exactly what you were looking at.
158
- const [range, setRange] = useSearchParam("range", "30d")
159
-
160
- // `search` goes into the query string *and* the cache key, so changing the
161
- // range refetches instead of serving the previous window.
162
- const summary = useApiQuery<KpiSummary>("/api/kpi-summary", { search: { range } })
163
-
164
- return (
165
- <PageShell>
166
- <PageShellHeader>
167
- <PageShellHeading>
168
- <PageShellTitle>[Template] Performance overview</PageShellTitle>
169
- <PageShellDescription>
170
- Key metrics and trends for the selected period.
171
- </PageShellDescription>
172
- </PageShellHeading>
173
- <PageShellHeaderEnd>
174
- <SegmentedControl
175
- options={RANGE_OPTIONS}
176
- value={range}
177
- onChange={setRange}
178
- ariaLabel="Period"
179
- />
180
- </PageShellHeaderEnd>
181
- </PageShellHeader>
182
-
183
- <PageShellContent className="space-y-6">
184
- {summary.isPending ? (
185
- <Loading />
186
- ) : summary.isError ? (
187
- // `summary.error` is an `ApiError`: `message` is the text the handler
188
- // passed to `HttpError`, so there is no cast and no generic wording.
189
- <ErrorState
190
- title="Could not load the dashboard"
191
- message={summary.error.message}
192
- action={<Button onClick={() => void summary.refetch()}>Retry</Button>}
193
- />
194
- ) : (
195
- <DashboardBody data={summary.data} />
196
- )}
197
- </PageShellContent>
198
- </PageShell>
199
- )
200
- }
@@ -104,6 +104,53 @@ const RANGE_OPTIONS: SegmentOption[] = [
104
104
  { label: "90日", value: "90d" },
105
105
  ]
106
106
 
107
+ export default function HomePage() {
108
+ // 絞り込み状態は useState ではなく URL に置く。リロードで消えず、URL を
109
+ // そのまま共有すれば相手も同じ画面を見られる。
110
+ const [range, setRange] = useSearchParam("range", "30d")
111
+
112
+ // search はクエリ文字列とキャッシュキーの両方に入るので、期間を変えると
113
+ // 前の期間のデータを返さずに再取得される。
114
+ const summary = useApiQuery<KpiSummary>("/api/kpi-summary", { search: { range } })
115
+
116
+ return (
117
+ <PageShell>
118
+ <PageShellHeader>
119
+ <PageShellHeading>
120
+ <PageShellTitle>[テンプレート] パフォーマンス概要</PageShellTitle>
121
+ <PageShellDescription>
122
+ 選択期間の主要指標とトレンド。
123
+ </PageShellDescription>
124
+ </PageShellHeading>
125
+ <PageShellHeaderEnd>
126
+ <SegmentedControl
127
+ options={RANGE_OPTIONS}
128
+ value={range}
129
+ onChange={setRange}
130
+ ariaLabel="期間"
131
+ />
132
+ </PageShellHeaderEnd>
133
+ </PageShellHeader>
134
+
135
+ <PageShellContent className="space-y-6">
136
+ {summary.isPending ? (
137
+ <Loading />
138
+ ) : summary.isError ? (
139
+ // summary.error は ApiError。message にはハンドラが HttpError に
140
+ // 渡した文言がそのまま入るので、キャストも汎用文言も要らない。
141
+ <ErrorState
142
+ title="ダッシュボードを読み込めませんでした"
143
+ message={summary.error.message}
144
+ action={<Button onClick={() => void summary.refetch()}>再試行</Button>}
145
+ />
146
+ ) : (
147
+ <DashboardBody data={summary.data} />
148
+ )}
149
+ </PageShellContent>
150
+ </PageShell>
151
+ )
152
+ }
153
+
107
154
  function DashboardBody({ data }: { data: KpiSummary }) {
108
155
  return (
109
156
  <>
@@ -151,50 +198,3 @@ function DashboardBody({ data }: { data: KpiSummary }) {
151
198
  </>
152
199
  )
153
200
  }
154
-
155
- export default function HomePage() {
156
- // 絞り込み状態は useState ではなく URL に置く。リロードで消えず、URL を
157
- // そのまま共有すれば相手も同じ画面を見られる。
158
- const [range, setRange] = useSearchParam("range", "30d")
159
-
160
- // search はクエリ文字列とキャッシュキーの両方に入るので、期間を変えると
161
- // 前の期間のデータを返さずに再取得される。
162
- const summary = useApiQuery<KpiSummary>("/api/kpi-summary", { search: { range } })
163
-
164
- return (
165
- <PageShell>
166
- <PageShellHeader>
167
- <PageShellHeading>
168
- <PageShellTitle>[テンプレート] パフォーマンス概要</PageShellTitle>
169
- <PageShellDescription>
170
- 選択期間の主要指標とトレンド。
171
- </PageShellDescription>
172
- </PageShellHeading>
173
- <PageShellHeaderEnd>
174
- <SegmentedControl
175
- options={RANGE_OPTIONS}
176
- value={range}
177
- onChange={setRange}
178
- ariaLabel="期間"
179
- />
180
- </PageShellHeaderEnd>
181
- </PageShellHeader>
182
-
183
- <PageShellContent className="space-y-6">
184
- {summary.isPending ? (
185
- <Loading />
186
- ) : summary.isError ? (
187
- // summary.error は ApiError。message にはハンドラが HttpError に
188
- // 渡した文言がそのまま入るので、キャストも汎用文言も要らない。
189
- <ErrorState
190
- title="ダッシュボードを読み込めませんでした"
191
- message={summary.error.message}
192
- action={<Button onClick={() => void summary.refetch()}>再試行</Button>}
193
- />
194
- ) : (
195
- <DashboardBody data={summary.data} />
196
- )}
197
- </PageShellContent>
198
- </PageShell>
199
- )
200
- }
@@ -1,108 +0,0 @@
1
- <!--
2
- DESIGN.md — このアプリの「見た目の意図」を書くファイルです。
3
-
4
- - 実際の色・角丸・書体の値は src/styles.css にあります。ここにはトークン名(--primary など)と
5
- 使い分けのルールだけを書き、色コードは書きません。
6
- - エージェントはページ・スライド・コンポーネントを書く前にこのファイルを読みます。
7
- 会話の中での指示はこのファイルより優先されます。
8
- - 「このサイトに合わせて」「色を落ち着いた感じに」と頼めば、このファイルと styles.css を
9
- まとめて更新します。
10
- - このファイルはあなたのものです。`vantage upgrade` が書き換えることはありません。
11
- -->
12
-
13
- # デザイン
14
-
15
- ## 全体のトーン (Overview)
16
-
17
- - 落ち着いた無彩色のベースに、データだけが色を持つ業務ダッシュボード。
18
- - 装飾より読みやすさを優先する。影・グラデーション・アニメーションは最小限。
19
- - 数字が主役。1 画面で伝えたいことを 1 つに絞り、補足は小さく添える。
20
- - ブランド素材: なし(ロゴを使う場合は `public/brand/logo.svg` のように `public/` 配下のパスで書く)
21
-
22
- ## 色 (Colors)
23
-
24
- 色は必ずトークン(Tailwind のセマンティッククラス)で指定する。素のパレット(`bg-blue-600` など)や
25
- 色コードを直接書かない。
26
-
27
- | 役割 | トークン | 使う場所 |
28
- | --- | --- | --- |
29
- | 主色 (Primary) | `--primary` / `--primary-foreground` | 主要ボタン、選択中の状態。既定は無彩色 |
30
- | 強調 (Accent) | `--chart-1` | 1 つだけ目立たせたい数値・系列・リンク的な強調 |
31
- | 良い (Positive) | `--chart-2` | 前期比のプラスなど、良い変化の小さな印 |
32
- | 悪い (Negative) | `--destructive` | 前期比のマイナス、エラー、削除操作 |
33
- | 注意 (Warning) | 専用トークンなし | 文言とアイコンで示し、色は `--muted-foreground` |
34
- | 背景の段階 | `--background` → `--card` → `--muted` | ページ → カード → カード内の区画・ホバー |
35
- | 境界 | `--border` / `--input` / `--ring` | 罫線、入力欄、フォーカス |
36
- | 文字 | `--foreground` / `--muted-foreground` | 本文 / 補足・ラベル・単位 |
37
-
38
- - `--muted`・`--accent`・`--secondary`・`--border` は背景・境界用。文字色に使わない。
39
- - 増減(▲▼・前期比)は向きで色を分ける: 増加・プラスは `--chart-2`(または `--primary`)、
40
- 減少・マイナスは `--destructive`。下向きの矢印やマイナスを `--primary` で塗らない。
41
- - ライトとダークの両方がトークンで決まるので `dark:` を並べない。
42
-
43
- ## チャート (Charts)
44
-
45
- - 系列の順番は `--chart-1` → `--chart-2` → `--chart-3` → `--chart-4` → `--chart-5`
46
- (現在はプリセット `blue`: 青 → ティール → フクシア → バイオレット → グレー)。
47
- - 1 系列だけを目立たせるときは、その系列を `--chart-1`、残りをすべて `--chart-5`(グレー)にする。
48
- - 良い / 悪いを色で塗り分けるときは `--chart-2` / `--destructive`。色だけに頼らず ▲▼ や符号も添える。
49
- - 系列は 5 つまで。それ以上はグループ化するか「その他」にまとめる。
50
- - 禁止: 同じチャートで `--destructive` を普通の系列色として使う(悪い値に見える)。
51
- - 禁止: 隣り合う系列に `--chart-3` と `--chart-4` を並べて細い線で描く(見分けにくい)。
52
- - 配色を丸ごと変えるときは `npx @squadbase/vantage-template chart <preset>` を使う
53
- (`blue` / `ocean` / `sunset` / `forest` / `berry` / `mono`)。
54
-
55
- ## 書体 (Typography)
56
-
57
- | 用途 | 指定 | 備考 |
58
- | --- | --- | --- |
59
- | 見出し・本文 | 日本語を含むシステムフォント(`body` の `font-family`) | Web フォントは使わない |
60
- | 数字 | 同上 + `tabular-nums` | 桁がそろうように必ず付ける |
61
- | スライドの見出し | `--slide-font-display` | 既定は日本語を含むシステムフォント |
62
- | スライドの本文 | `--slide-font-body` | 既定は見出しと同じ |
63
-
64
- サイズの段階(ダッシュボード):
65
-
66
- - ページ見出し: `text-2xl font-bold`
67
- - カード見出し・ラベル: `text-sm font-medium text-muted-foreground`
68
- - KPI の数値: `text-3xl font-semibold tabular-nums`
69
- - 本文・表: `text-sm`
70
- - 注釈・出典: `text-xs text-muted-foreground`
71
-
72
- スライドのサイズは `--slide-size-hero`(表紙・大きな数字)と `--slide-size-body`(本文)を基準にする。
73
-
74
- ## レイアウトと密度 (Layout)
75
-
76
- - 情報はカード(`bg-card` + `border-border`)で区切る。角丸は `--radius` に従う(個別に変えない)。
77
- - グリッドの間隔は `gap-4`。セクション間は `gap-6` 程度。
78
- - KPI は 1 行に 2〜4 枚。その下にチャート、最後に明細の表。
79
- - 密度は「中」。余白を削って詰め込むより、ページを分ける。
80
-
81
- ## 成果物の種類ごとの規則 (Per-artifact)
82
-
83
- ### ダッシュボード
84
-
85
- - 先頭に KPI カード、次にトレンドのチャート、最後に明細の表。
86
- - 各 KPI には比較対象(前月比・目標比など)を 1 つ添える。
87
- - チャートのタイトルは結論を書く(「売上推移」より「売上は 3 か月連続で増加」)。
88
-
89
- ### スライド
90
-
91
- - 1 枚に 1 メッセージ。見出しに結論を書く。
92
- - 色は `--slide-bg` / `--slide-fg` / `--slide-accent` / `--slide-muted` を使う
93
- (既定では `--background` / `--foreground` / `--primary` / `--muted-foreground` に連動)。
94
- - 強調色は 1 枚につき 1 か所まで。
95
-
96
- ## Do / Don't
97
-
98
- Do:
99
-
100
- - トークンと Tailwind のセマンティッククラスで色を指定する。
101
- - 数値には単位と比較対象を付ける。
102
- - 色の意味(良い / 悪い / 強調)をアプリ全体でそろえる。
103
-
104
- Don't:
105
-
106
- - 色コードや素のパレットクラスを直接書く。
107
- - 1 画面で強調色を何か所にも使う。
108
- - 3D チャート・円グラフの多用・装飾目的のグラデーション。