@squadbase/vantage 0.0.1 → 0.1.0

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 (167) hide show
  1. package/README.md +21 -4
  2. package/dist/chunk-A2UUGASH.js +12 -0
  3. package/dist/chunk-A2UUGASH.js.map +1 -0
  4. package/dist/{chunk-ZGDU5YLH.js → chunk-PRFBSQA4.js} +9 -5
  5. package/dist/chunk-PRFBSQA4.js.map +1 -0
  6. package/dist/chunk-WQZYXXQW.js +2249 -0
  7. package/dist/chunk-WQZYXXQW.js.map +1 -0
  8. package/dist/{chunk-73J5ZD4C.js → chunk-YLAB6UQS.js} +17 -3
  9. package/dist/chunk-YLAB6UQS.js.map +1 -0
  10. package/dist/cli.js +607 -36
  11. package/dist/cli.js.map +1 -1
  12. package/dist/components/index.d.ts +554 -0
  13. package/dist/components/index.js +1983 -0
  14. package/dist/components/index.js.map +1 -0
  15. package/dist/markdown/index.d.ts +9 -0
  16. package/dist/markdown/index.js +26 -0
  17. package/dist/markdown/index.js.map +1 -0
  18. package/dist/query/index.d.ts +27 -1
  19. package/dist/query/index.js +18 -0
  20. package/dist/query/index.js.map +1 -1
  21. package/dist/server/node.js +6 -1
  22. package/dist/server/node.js.map +1 -1
  23. package/dist/ui/index.d.ts +316 -200
  24. package/dist/ui/index.js +566 -511
  25. package/dist/ui/index.js.map +1 -1
  26. package/dist/vite/index.js +2 -2
  27. package/docs/en/agent-skills.md +89 -0
  28. package/docs/en/api-and-server.md +84 -0
  29. package/docs/en/build-and-deploy.md +280 -0
  30. package/docs/en/cli-reference.md +311 -0
  31. package/docs/en/components.md +233 -0
  32. package/docs/en/data-fetching.md +78 -0
  33. package/docs/en/environment-variables.md +69 -0
  34. package/docs/en/getting-started.md +95 -0
  35. package/docs/en/index.md +65 -0
  36. package/docs/en/markdown/markdown-renderer.md +44 -0
  37. package/docs/en/pages-and-metadata.md +56 -0
  38. package/docs/en/parts/app-shell.md +54 -0
  39. package/docs/en/parts/dashboard-card.md +64 -0
  40. package/docs/en/parts/data-table.md +86 -0
  41. package/docs/en/parts/date-range-picker.md +41 -0
  42. package/docs/en/parts/echart.md +53 -0
  43. package/docs/en/parts/filter-bar.md +66 -0
  44. package/docs/en/parts/funnel-steps.md +33 -0
  45. package/docs/en/parts/metric-value.md +23 -0
  46. package/docs/en/parts/multi-select.md +27 -0
  47. package/docs/en/parts/page-shell.md +45 -0
  48. package/docs/en/parts/searchable-select.md +47 -0
  49. package/docs/en/parts/section-header.md +20 -0
  50. package/docs/en/parts/segmented-control.md +25 -0
  51. package/docs/en/parts/status-badge.md +44 -0
  52. package/docs/en/parts/trend-indicator.md +26 -0
  53. package/docs/en/routing.md +95 -0
  54. package/docs/en/ui/accordion.md +36 -0
  55. package/docs/en/ui/alert.md +31 -0
  56. package/docs/en/ui/badge.md +23 -0
  57. package/docs/en/ui/breadcrumb.md +38 -0
  58. package/docs/en/ui/button.md +39 -0
  59. package/docs/en/ui/calendar.md +28 -0
  60. package/docs/en/ui/card.md +35 -0
  61. package/docs/en/ui/checkbox.md +34 -0
  62. package/docs/en/ui/cn.md +34 -0
  63. package/docs/en/ui/collapsible.md +21 -0
  64. package/docs/en/ui/command.md +37 -0
  65. package/docs/en/ui/dialog.md +52 -0
  66. package/docs/en/ui/dropdown-menu.md +50 -0
  67. package/docs/en/ui/empty.md +22 -0
  68. package/docs/en/ui/error-state.md +50 -0
  69. package/docs/en/ui/input-group.md +30 -0
  70. package/docs/en/ui/input.md +28 -0
  71. package/docs/en/ui/label.md +19 -0
  72. package/docs/en/ui/loading.md +19 -0
  73. package/docs/en/ui/popover.md +34 -0
  74. package/docs/en/ui/progress.md +28 -0
  75. package/docs/en/ui/scroll-area.md +23 -0
  76. package/docs/en/ui/select.md +63 -0
  77. package/docs/en/ui/separator.md +15 -0
  78. package/docs/en/ui/sheet.md +28 -0
  79. package/docs/en/ui/sidebar.md +92 -0
  80. package/docs/en/ui/skeleton.md +16 -0
  81. package/docs/en/ui/slider.md +21 -0
  82. package/docs/en/ui/spinner.md +14 -0
  83. package/docs/en/ui/switch.md +19 -0
  84. package/docs/en/ui/table.md +24 -0
  85. package/docs/en/ui/tabs.md +23 -0
  86. package/docs/en/ui/textarea.md +15 -0
  87. package/docs/en/ui/toggle-group.md +26 -0
  88. package/docs/en/ui/toggle.md +19 -0
  89. package/docs/en/ui/tooltip.md +22 -0
  90. package/docs/en/ui/use-is-mobile.md +18 -0
  91. package/docs/en/ui-and-theming.md +95 -0
  92. package/docs/index.json +1306 -0
  93. package/docs/ja/agent-skills.md +87 -0
  94. package/docs/ja/api-and-server.md +84 -0
  95. package/docs/ja/build-and-deploy.md +279 -0
  96. package/docs/ja/cli-reference.md +305 -0
  97. package/docs/ja/components.md +229 -0
  98. package/docs/ja/data-fetching.md +78 -0
  99. package/docs/ja/environment-variables.md +68 -0
  100. package/docs/ja/getting-started.md +95 -0
  101. package/docs/ja/index.md +65 -0
  102. package/docs/ja/markdown/markdown-renderer.md +43 -0
  103. package/docs/ja/pages-and-metadata.md +56 -0
  104. package/docs/ja/parts/app-shell.md +54 -0
  105. package/docs/ja/parts/dashboard-card.md +64 -0
  106. package/docs/ja/parts/data-table.md +85 -0
  107. package/docs/ja/parts/date-range-picker.md +41 -0
  108. package/docs/ja/parts/echart.md +52 -0
  109. package/docs/ja/parts/filter-bar.md +64 -0
  110. package/docs/ja/parts/funnel-steps.md +33 -0
  111. package/docs/ja/parts/metric-value.md +25 -0
  112. package/docs/ja/parts/multi-select.md +27 -0
  113. package/docs/ja/parts/page-shell.md +45 -0
  114. package/docs/ja/parts/searchable-select.md +47 -0
  115. package/docs/ja/parts/section-header.md +20 -0
  116. package/docs/ja/parts/segmented-control.md +26 -0
  117. package/docs/ja/parts/status-badge.md +44 -0
  118. package/docs/ja/parts/trend-indicator.md +26 -0
  119. package/docs/ja/routing.md +95 -0
  120. package/docs/ja/ui/accordion.md +37 -0
  121. package/docs/ja/ui/alert.md +31 -0
  122. package/docs/ja/ui/badge.md +23 -0
  123. package/docs/ja/ui/breadcrumb.md +38 -0
  124. package/docs/ja/ui/button.md +39 -0
  125. package/docs/ja/ui/calendar.md +28 -0
  126. package/docs/ja/ui/card.md +35 -0
  127. package/docs/ja/ui/checkbox.md +34 -0
  128. package/docs/ja/ui/cn.md +34 -0
  129. package/docs/ja/ui/collapsible.md +21 -0
  130. package/docs/ja/ui/command.md +36 -0
  131. package/docs/ja/ui/dialog.md +51 -0
  132. package/docs/ja/ui/dropdown-menu.md +50 -0
  133. package/docs/ja/ui/empty.md +22 -0
  134. package/docs/ja/ui/error-state.md +50 -0
  135. package/docs/ja/ui/input-group.md +30 -0
  136. package/docs/ja/ui/input.md +28 -0
  137. package/docs/ja/ui/label.md +19 -0
  138. package/docs/ja/ui/loading.md +19 -0
  139. package/docs/ja/ui/popover.md +34 -0
  140. package/docs/ja/ui/progress.md +28 -0
  141. package/docs/ja/ui/scroll-area.md +24 -0
  142. package/docs/ja/ui/select.md +64 -0
  143. package/docs/ja/ui/separator.md +15 -0
  144. package/docs/ja/ui/sheet.md +28 -0
  145. package/docs/ja/ui/sidebar.md +92 -0
  146. package/docs/ja/ui/skeleton.md +16 -0
  147. package/docs/ja/ui/slider.md +21 -0
  148. package/docs/ja/ui/spinner.md +14 -0
  149. package/docs/ja/ui/switch.md +19 -0
  150. package/docs/ja/ui/table.md +24 -0
  151. package/docs/ja/ui/tabs.md +24 -0
  152. package/docs/ja/ui/textarea.md +15 -0
  153. package/docs/ja/ui/toggle-group.md +27 -0
  154. package/docs/ja/ui/toggle.md +19 -0
  155. package/docs/ja/ui/tooltip.md +22 -0
  156. package/docs/ja/ui/use-is-mobile.md +18 -0
  157. package/docs/ja/ui-and-theming.md +95 -0
  158. package/package.json +29 -4
  159. package/registry/blocks/sales-overview.tsx +43 -19
  160. package/registry/ui/data-table.tsx +702 -102
  161. package/skills/vantage-add-feature/SKILL.md +150 -0
  162. package/skills/vantage-app/SKILL.md +258 -0
  163. package/skills/vantage-pitfalls/SKILL.md +115 -0
  164. package/templates/AGENTS.md +268 -0
  165. package/theme.css +178 -40
  166. package/dist/chunk-73J5ZD4C.js.map +0 -1
  167. package/dist/chunk-ZGDU5YLH.js.map +0 -1
@@ -0,0 +1,233 @@
1
+ # Components
2
+
3
+ > Reference for the bundled shadcn/ui (Base UI) kit and the composite dashboard components.
4
+
5
+ Vantage ships **shadcn/ui** as-is. Nothing to install, nothing to copy — just import. There are three
6
+ public entry points, and **the sidebar is sectioned by those three**.
7
+
8
+ | Subpath | What's in it | Count |
9
+ | --- | --- | --- |
10
+ | [`@squadbase/vantage/ui`](ui/button) | The shadcn/ui primitives (Base UI build) plus utilities like `cn()` | 37 |
11
+ | [`@squadbase/vantage/components`](parts/page-shell) | Dashboard parts composed from them | 15 |
12
+ | [`@squadbase/vantage/markdown`](markdown/markdown-renderer) | Markdown rendering alone (kept apart — it's heavy) | 1 |
13
+
14
+ ```tsx
15
+ import { Button, Card, Badge } from "@squadbase/vantage/ui";
16
+ import { PageShell, DashboardCardPreset, EChart } from "@squadbase/vantage/components";
17
+ import { MarkdownRenderer } from "@squadbase/vantage/markdown";
18
+ ```
19
+
20
+ > [!NOTE]
21
+ > The UI kit is meant to be **imported from the package**, not copied. Pull an editable source with
22
+ > [`vantage add`](cli-reference) only when you need to change a component's internals.
23
+
24
+ ## It's the Base UI build
25
+
26
+ What ships is the **Base UI variant** of shadcn/ui. In July 2026 shadcn/ui switched its default
27
+ primitives from Radix UI to [Base UI](https://base-ui.com), and Vantage follows the new one. Coming
28
+ from the Radix build, four differences matter.
29
+
30
+ - **There is no `asChild`.** Pass an element to the `render` prop instead.
31
+
32
+ ```tsx
33
+ // Radix build
34
+ <PopoverTrigger asChild><Button>Open</Button></PopoverTrigger>
35
+
36
+ // Base UI build (Vantage)
37
+ <PopoverTrigger render={<Button />}>Open</PopoverTrigger>
38
+ ```
39
+
40
+ - **[`Checkbox`](ui/checkbox)'s `checked` is strictly a boolean.** The mixed state is
41
+ the separate `indeterminate` prop.
42
+ - **[`ToggleGroup`](ui/toggle-group)'s `value` is an array.** For single choice, use
43
+ [`SegmentedControl`](parts/segmented-control).
44
+ - **[`Select`](ui/select)'s `onValueChange` gives `string | null`.** You need a
45
+ `null` guard. And `SelectValue` shows the raw value by default — pass the value-to-label map as
46
+ `items` to get labels.
47
+
48
+ State is expressed as `data-open` / `data-checked` rather than `data-state="open"`. Vantage's
49
+ `theme.css` declares custom variants that accept both spellings, so classes like
50
+ `data-open:animate-in` work either way.
51
+
52
+ ## `@squadbase/vantage/ui`
53
+
54
+ The shadcn/ui primitives. The names and props are shadcn/ui's own, so
55
+ [their docs](https://ui.shadcn.com/docs/components) apply directly. The sidebar is alphabetical;
56
+ here they're grouped by what they're for.
57
+
58
+ ### Forms and input
59
+
60
+ [`Button`](ui/button) ·
61
+ [`Input`](ui/input) ·
62
+ [`InputGroup`](ui/input-group) ·
63
+ [`Textarea`](ui/textarea) ·
64
+ [`Label`](ui/label) ·
65
+ [`Select`](ui/select) ·
66
+ [`Checkbox`](ui/checkbox) ·
67
+ [`Switch`](ui/switch) ·
68
+ [`Slider`](ui/slider) ·
69
+ [`Toggle`](ui/toggle) ·
70
+ [`ToggleGroup`](ui/toggle-group) ·
71
+ [`Calendar`](ui/calendar) ·
72
+ [`Command`](ui/command)
73
+
74
+ ### Layout and navigation
75
+
76
+ [`Card`](ui/card) ·
77
+ [`Tabs`](ui/tabs) ·
78
+ [`Separator`](ui/separator) ·
79
+ [`ScrollArea`](ui/scroll-area) ·
80
+ [`Sidebar`](ui/sidebar) ·
81
+ [`Breadcrumb`](ui/breadcrumb) ·
82
+ [`Accordion`](ui/accordion) ·
83
+ [`Collapsible`](ui/collapsible)
84
+
85
+ ### Data display
86
+
87
+ [`Table`](ui/table) ·
88
+ [`Badge`](ui/badge) ·
89
+ [`Progress`](ui/progress)
90
+
91
+ ### Overlays
92
+
93
+ [`Dialog`](ui/dialog) ·
94
+ [`Sheet`](ui/sheet) ·
95
+ [`Popover`](ui/popover) ·
96
+ [`Tooltip`](ui/tooltip) ·
97
+ [`DropdownMenu`](ui/dropdown-menu)
98
+
99
+ ### States
100
+
101
+ [`Alert`](ui/alert) ·
102
+ [`Skeleton`](ui/skeleton) ·
103
+ [`Spinner`](ui/spinner) ·
104
+ [`Loading`](ui/loading) ·
105
+ [`Empty`](ui/empty) ·
106
+ [`ErrorState`](ui/error-state)
107
+
108
+ `Loading` / `Empty` / `ErrorState` are the only three that aren't shadcn/ui — Vantage adds them.
109
+
110
+ ### Utilities
111
+
112
+ [`cn()`](ui/cn) · [`useIsMobile()`](ui/use-is-mobile)
113
+
114
+ ## `@squadbase/vantage/components`
115
+
116
+ Dashboard parts composed from `ui/`.
117
+
118
+ | Component | What it is |
119
+ | --- | --- |
120
+ | [`PageShell`](parts/page-shell) | The page frame: header band, summary, content |
121
+ | [`AppShell`](parts/app-shell) | The app frame — hand it your nav |
122
+ | [`SectionHeader`](parts/section-header) | A section heading with actions |
123
+ | [`DashboardCard`](parts/dashboard-card) | The dashboard tile, with preset and skeleton |
124
+ | [`DataTable`](parts/data-table) | Sorting, search, pagination, selection |
125
+ | [`EChart`](parts/echart) | The Apache ECharts wrapper |
126
+ | [`FunnelSteps`](parts/funnel-steps) | A funnel drawn as bars |
127
+ | [`FilterBar`](parts/filter-bar) | A row of filters driven by one value |
128
+ | [`DateRangePicker`](parts/date-range-picker) | Date range with presets |
129
+ | [`SegmentedControl`](parts/segmented-control) | Single-choice segments |
130
+ | [`SearchableSelect`](parts/searchable-select) | Single choice with search |
131
+ | [`MultiSelect`](parts/multi-select) | Multiple choice with search |
132
+ | [`MetricValue`](parts/metric-value) | A KPI's number and unit |
133
+ | [`TrendIndicator`](parts/trend-indicator) | An arrow and a percentage |
134
+ | [`StatusBadge`](parts/status-badge) | A dot-and-label status badge |
135
+
136
+ ## `@squadbase/vantage/markdown`
137
+
138
+ A subpath holding only [`MarkdownRenderer`](markdown/markdown-renderer). Markdown
139
+ rendering carries Shiki with every language grammar; mixed into the `components` barrel it would add
140
+ over 10 MB to every build, so it is deliberately kept apart.
141
+
142
+ ## Putting it together
143
+
144
+ ```tsx
145
+ import { Button } from "@squadbase/vantage/ui";
146
+ import {
147
+ PageShell,
148
+ PageShellHeader,
149
+ PageShellHeading,
150
+ PageShellTitle,
151
+ PageShellDescription,
152
+ PageShellHeaderEnd,
153
+ PageShellActions,
154
+ PageShellContent,
155
+ DashboardCardPreset,
156
+ MetricValue,
157
+ TrendIndicator,
158
+ EChart,
159
+ type EChartsOption,
160
+ } from "@squadbase/vantage/components";
161
+
162
+ const option: EChartsOption = {
163
+ xAxis: { type: "category", data: monthly.map((m) => m.month) },
164
+ yAxis: { type: "value" },
165
+ series: [{ type: "bar", data: monthly.map((m) => m.revenue) }],
166
+ };
167
+
168
+ export default function Overview() {
169
+ return (
170
+ <PageShell>
171
+ <PageShellHeader>
172
+ <PageShellHeading>
173
+ <PageShellTitle>Sales dashboard</PageShellTitle>
174
+ <PageShellDescription>The last six months</PageShellDescription>
175
+ </PageShellHeading>
176
+ <PageShellHeaderEnd>
177
+ <PageShellActions>
178
+ <Button variant="outline">Export</Button>
179
+ </PageShellActions>
180
+ </PageShellHeaderEnd>
181
+ </PageShellHeader>
182
+
183
+ <PageShellContent>
184
+ <div className="grid gap-4 md:grid-cols-3">
185
+ <DashboardCardPreset title="Revenue">
186
+ <MetricValue className="my-0">$12,400</MetricValue>
187
+ <TrendIndicator value={12.4} direction="up" />
188
+ </DashboardCardPreset>
189
+ <DashboardCardPreset title="New customers">
190
+ <MetricValue className="my-0">128</MetricValue>
191
+ <TrendIndicator value={3.1} direction="down" />
192
+ </DashboardCardPreset>
193
+ <DashboardCardPreset title="Churn">
194
+ <MetricValue className="my-0">2.1%</MetricValue>
195
+ </DashboardCardPreset>
196
+ </div>
197
+
198
+ <DashboardCardPreset title="Monthly revenue" className="mt-4">
199
+ <EChart option={option} height={320} />
200
+ </DashboardCardPreset>
201
+ </PageShellContent>
202
+ </PageShell>
203
+ );
204
+ }
205
+ ```
206
+
207
+ ## Theming
208
+
209
+ The look is decided by CSS variables (design tokens). To change colours or radii, override just the
210
+ variables in a `styles.css` at the project root — see [UI & theming](ui-and-theming).
211
+
212
+ ## When you want to edit the source
213
+
214
+ To change a component's internals, pull an editable copy.
215
+
216
+ ```bash
217
+ vantage add ui data-table # an editable DataTable into components/
218
+ vantage add block sales-overview
219
+ ```
220
+
221
+ > [!NOTE]
222
+ > In the current prototype, `vantage add` can copy only `data-table` (ui) and `sales-overview` (block).
223
+ > Everything else is import-only.
224
+
225
+ ## How to read these pages
226
+
227
+ Every component page pairs a **live preview** with its **source**, in tabs. The
228
+ `export const client = "only";` at the top of each source is this documentation site's own directive
229
+ — your app doesn't need it.
230
+
231
+ > [!NOTE]
232
+ > The previews are shared between both locales, and their sample data is written in Japanese (the
233
+ > site's default locale). The component APIs are the same either way.
@@ -0,0 +1,78 @@
1
+ # Data fetching
2
+
3
+ > Handle server state with a managed TanStack Query (useQuery).
4
+
5
+ Vantage ships a **managed TanStack Query** for server state. There is no `QueryClient` to set up —
6
+ just import `useQuery` and friends from `@squadbase/vantage/query`.
7
+
8
+ ```tsx
9
+ import { useQuery } from "@squadbase/vantage/query";
10
+
11
+ export default function Customers() {
12
+ const { data, isLoading, error } = useQuery({
13
+ queryKey: ["customers"],
14
+ queryFn: async () => {
15
+ const res = await fetch("/api/customers");
16
+ if (!res.ok) throw new Error("failed to load");
17
+ return res.json();
18
+ },
19
+ });
20
+
21
+ if (isLoading) return <p>Loading…</p>;
22
+ if (error) return <p>Something went wrong</p>;
23
+ return (
24
+ <ul>
25
+ {data.map((c: { id: string; name: string }) => (
26
+ <li key={c.id}>{c.name}</li>
27
+ ))}
28
+ </ul>
29
+ );
30
+ }
31
+ ```
32
+
33
+ ## A single managed QueryClient
34
+
35
+ Vantage provides exactly one `QueryClient` with these defaults:
36
+
37
+ | Option | Value |
38
+ |---|---|
39
+ | `staleTime` | 30 seconds |
40
+ | `retry` | 1 |
41
+ | `refetchOnWindowFocus` | `false` |
42
+
43
+ Customize by **overriding per query**. Swapping the whole `QueryClient` is intentionally not exposed,
44
+ to keep the stack managed.
45
+
46
+ ```tsx
47
+ // Change behavior for this query only
48
+ useQuery({
49
+ queryKey: ["metrics"],
50
+ queryFn: fetchMetrics,
51
+ staleTime: 5 * 60 * 1000, // 5 minutes
52
+ retry: 3,
53
+ });
54
+ ```
55
+
56
+ > [!NOTE]
57
+ > Do not import `@tanstack/react-query` directly. Using the curated re-exports from
58
+ > `@squadbase/vantage/query` lets Vantage evolve the underlying library safely.
59
+
60
+ ## Pairing with the API
61
+
62
+ Calling `/api/*` inside `queryFn` connects naturally to the [optional server](api-and-server).
63
+ Even a client-only app without `server/` can `fetch` an external API the same way.
64
+
65
+ > [!TIP]
66
+ > When calling the built-in `/api`, use `apiFetch` from `@squadbase/vantage/query` so the base URL can
67
+ > be switched via env (for deploying the client and server on different origins). See
68
+ > [Build & deploy](build-and-deploy) for details.
69
+ >
70
+ > ```tsx
71
+ > import { apiFetch } from "@squadbase/vantage/query";
72
+ >
73
+ > queryFn: () => apiFetch("/api/customers").then((r) => r.json());
74
+ > ```
75
+
76
+ ## What to read next
77
+
78
+ - [API & server](api-and-server) — write a backend
@@ -0,0 +1,69 @@
1
+ # Environment variables
2
+
3
+ > Only PUBLIC_-prefixed env reaches the client. Read secrets from the server's env.
4
+
5
+ Vantage's default is to **never leak** environment variables to the client. The boundary is the prefix.
6
+
7
+ ## Only `PUBLIC_` reaches the client
8
+
9
+ Only variables beginning with `PUBLIC_` are included in the client bundle and readable via
10
+ `import.meta.env`.
11
+
12
+ ```tsx
13
+ // client code
14
+ const analyticsId = import.meta.env.PUBLIC_ANALYTICS_ID;
15
+ ```
16
+
17
+ The client can only see:
18
+
19
+ - `PUBLIC_*` (the public values you define)
20
+ - `MODE` / `DEV` / `PROD` / `SSR` / `BASE_URL` (Vite standard)
21
+
22
+ > [!WARNING]
23
+ > Reading an env variable **without** the `PUBLIC_` prefix on the client triggers a `PUBLIC_ENV_MISUSE`
24
+ > warning from `vantage check`. There is no user-facing `VITE_` API.
25
+
26
+ ## Secrets come from the server's `env`
27
+
28
+ Read secrets like API keys and tokens from the server's `ApiContext.env` — **never expose them to
29
+ the client**. These carry no prefix.
30
+
31
+ ```ts
32
+ // server/api/report.ts
33
+ import type { ApiContext } from "@squadbase/vantage/server";
34
+
35
+ export async function GET({ env }: ApiContext) {
36
+ const apiKey = env.SECRET_API_KEY; // never reaches the client
37
+ // …call an external service
38
+ return Response.json({ ok: true });
39
+ }
40
+ ```
41
+
42
+ ## An `.env` example
43
+
44
+ ```bash
45
+ # .env
46
+ PUBLIC_ANALYTICS_ID=UA-XXXX # reaches the client
47
+ SECRET_API_KEY=sk_live_xxx # server only (ApiContext.env)
48
+ ```
49
+
50
+ > [!NOTE]
51
+ > The dev server re-reads env on every request. The production Node server snapshots `process.env` once
52
+ > at startup.
53
+
54
+ ## Env used at deploy time
55
+
56
+ When you deploy the client and server on different origins, these env vars come into play.
57
+
58
+ | Variable | Side | Role |
59
+ |---|---|---|
60
+ | `PUBLIC_API_BASE_URL` | Client (public) | Base URL the client uses to call `/api`. Also overridable via `--api-base-url` |
61
+ | `CORS_ORIGIN` | Server | Origin(s) allowed for `/api`. Unset means CORS is off |
62
+ | `CORS_CREDENTIALS` | Server | `true` to allow credentials (cookies, etc.) |
63
+
64
+ See [Build & deploy](build-and-deploy) for how to use them.
65
+
66
+ ## What to read next
67
+
68
+ - [Build & deploy](build-and-deploy) — production env and split origins
69
+ - [UI & theming](ui-and-theming) — shape the look
@@ -0,0 +1,95 @@
1
+ # Getting started
2
+
3
+ > From install to running your first Vantage app.
4
+
5
+ ## Prerequisites
6
+
7
+ - **Node.js 20 or newer**
8
+ - A package manager (pnpm, npm, or yarn)
9
+
10
+ ## Create the smallest app
11
+
12
+ ### Add Vantage
13
+
14
+ Add `@squadbase/vantage` to your project.
15
+
16
+ ```bash
17
+ pnpm add @squadbase/vantage
18
+ ```
19
+
20
+ ### Write index.tsx
21
+
22
+ Put a single `index.tsx` at the project root. The **default-exported component** becomes the
23
+ route `/`.
24
+
25
+ ```tsx
26
+ // index.tsx
27
+ export default function Dashboard() {
28
+ return (
29
+ <main className="p-6">
30
+ <h1 className="text-2xl font-semibold">Dashboard</h1>
31
+ </main>
32
+ );
33
+ }
34
+ ```
35
+
36
+ ### Start the dev server
37
+
38
+ ```bash
39
+ pnpm exec vantage dev
40
+ ```
41
+
42
+ This starts `http://localhost:5173` with HMR. Editing a page applies via React Fast Refresh
43
+ in place.
44
+
45
+ > [!TIP]
46
+ > Right after a plain `pnpm add`, the `vantage` binary isn't on your `PATH`, so run it via
47
+ > `pnpm exec vantage` (or `npx vantage`). Add `"dev": "vantage dev"` to your `package.json`
48
+ > `scripts` and you can use `pnpm dev` instead.
49
+
50
+ ## The development loop
51
+
52
+ | Command | Role |
53
+ |---|---|
54
+ | `vantage dev` | Dev server (HMR + optional API). Default `:5173` |
55
+ | `vantage build` | Production build → `dist/` (client + optional server) |
56
+ | `vantage preview` | Run the production build locally |
57
+ | `vantage check` | Static checks (routes, boundaries, forbidden files). Exit 1 on error |
58
+ | `vantage routes` | Print the page + API URL map |
59
+
60
+ > [!TIP]
61
+ > While `vantage dev` runs, the browser's `console.*` and uncaught errors are forwarded to the dev
62
+ > terminal as `[browser:…]`. Most issues can be diagnosed without opening the browser.
63
+
64
+ ## Quick mode (pass a path directly)
65
+
66
+ Instead of `cd`-ing into a project, you can pass its **path directly** to start the dev server.
67
+ Point at a folder or an entry file and `dev` boots on it.
68
+
69
+ ```bash
70
+ vantage ./demo # folder → run dev inside it
71
+ vantage ./demo/index.tsx # page file → use its parent folder as the root
72
+ ```
73
+
74
+ When the first argument isn't a known command but points at a path, Vantage runs `dev` with that
75
+ path as the root (printing `quick dev → <path>`). See the
76
+ [CLI reference](cli-reference) for the full resolution rules.
77
+
78
+ ## You never write config files
79
+
80
+ Vantage takes "convention over configuration" literally. These files are a **hard error**
81
+ (`vantage check` fails) if present in your project:
82
+
83
+ - `vite.config.*`
84
+ - `tailwind.config.*`
85
+ - `postcss.config.*`
86
+ - `components.json`
87
+ - `vantage.config.*`
88
+
89
+ Everything they used to configure is owned by Vantage. When you need to customize, use the
90
+ explicit escape hatches described throughout this guide.
91
+
92
+ ## What to read next
93
+
94
+ - [File-based routing](routing) — add more pages
95
+ - [Pages & definePage](pages-and-metadata) — the page contract and metadata
@@ -0,0 +1,65 @@
1
+ # What is Vantage
2
+
3
+ > A config-free React dashboard framework. You only write index.tsx.
4
+
5
+ A **vantage** point is a place with a clear, commanding view — and that's the idea behind the name:
6
+ give you a dashboard that sees all of your data at a glance, with the least possible effort.
7
+
8
+ **Vantage** is a config-free React dashboard framework for
9
+ [Squadbase Editor](https://squadbase.dev), built on Vite 8. As an app author you write a
10
+ **single `index.tsx`** — routing, React setup, TanStack Query, Tailwind CSS, the UI kit, the dev
11
+ server, an optional API server, and the build are all **owned by Vantage**.
12
+
13
+ ```tsx
14
+ // index.tsx → route "/"
15
+ export default function Dashboard() {
16
+ return (
17
+ <main className="p-6">
18
+ <h1 className="text-2xl font-semibold">Dashboard</h1>
19
+ </main>
20
+ );
21
+ }
22
+ ```
23
+
24
+ Those seven lines are a working dashboard app. You never write `vite.config`, `tailwind.config`,
25
+ `postcss.config`, `components.json`, or `vantage.config`.
26
+
27
+ > [!NOTE]
28
+ > This site is a guide for **app authors** — people building dashboards *with* Vantage. For the
29
+ > framework's own internals, see the repository's `README.md` and design document.
30
+
31
+ ## Highlights
32
+
33
+ ### One-file first
34
+
35
+ A single `index.tsx` is a complete app. Add a `.tsx` file when you want another page.
36
+
37
+ ### Convention over configuration
38
+
39
+ Config files aren't just unnecessary — they're forbidden. File and directory conventions drive everything.
40
+
41
+ ### Managed stack
42
+
43
+ React, Vite, TanStack Router/Query, Tailwind, and the UI kit are pinned by Vantage.
44
+
45
+ ### Server is optional
46
+
47
+ Add `server/` to enable an API. Without it, your app is a client-only SPA.
48
+
49
+ ## Next steps
50
+
51
+ ### Getting started
52
+
53
+ From install to running your first app.
54
+
55
+ ### File-based routing
56
+
57
+ How dropping a file creates a route.
58
+
59
+ ### Data fetching
60
+
61
+ Handle server state with a managed TanStack Query.
62
+
63
+ ### API & server
64
+
65
+ Write a backend under `server/api`.
@@ -0,0 +1,44 @@
1
+ # MarkdownRenderer
2
+
3
+ > Renders markdown, syntax highlighting included.
4
+
5
+ Renders a markdown string — tables, code blocks with syntax highlighting, and maths included. Good
6
+ for LLM output, or for prose that lives in your database.
7
+
8
+ ```tsx
9
+ import { MarkdownRenderer } from "@squadbase/vantage/markdown";
10
+ ```
11
+
12
+ | Prop | Type | Description |
13
+ | --- | --- | --- |
14
+ | `content` | `string` | The markdown to render. |
15
+ | `className` | `string` | Classes to add. |
16
+
17
+ ## Why it's on its own subpath
18
+
19
+ It is **deliberately not re-exported** from `@squadbase/vantage/components`. Markdown rendering
20
+ carries Shiki with every language grammar, and the import edge alone is something bundlers cannot
21
+ drop. Sitting in the shared barrel, it would add roughly 11 MB and 300 files to the build output of
22
+ apps that never render markdown.
23
+
24
+ Behind its own entry, **only the apps that import it** pay for it.
25
+
26
+ ```tsx
27
+ // This one is heavy — and that's fine
28
+ import { MarkdownRenderer } from "@squadbase/vantage/markdown";
29
+
30
+ // This one stays light
31
+ import { DashboardCardPreset } from "@squadbase/vantage/components";
32
+ ```
33
+
34
+ ## Streaming LLM output
35
+
36
+ Since only `content` changes, you can hand it a partially-streamed string. Incomplete markdown — an
37
+ unclosed code fence, say — still renders without breaking.
38
+
39
+ ```tsx
40
+ const [text, setText] = useState("");
41
+ // …setText((prev) => prev + chunk) as chunks arrive
42
+
43
+ <MarkdownRenderer content={text} />;
44
+ ```
@@ -0,0 +1,56 @@
1
+ # Pages & definePage
2
+
3
+ > A page's only requirement is a default export. Use definePage to attach a static title and description.
4
+
5
+ ## The only requirement is a default export
6
+
7
+ A Vantage page needs just one thing: a **default-exported React component**.
8
+
9
+ ```tsx
10
+ export default function MonthlyAnalysis() {
11
+ return <h1>Monthly analysis</h1>;
12
+ }
13
+ ```
14
+
15
+ A page without a default export is flagged by `vantage check` with a `MISSING_DEFAULT_EXPORT` error.
16
+
17
+ ## Attach metadata with definePage
18
+
19
+ To add a title or description, use `definePage`. It is optional.
20
+
21
+ ```tsx
22
+ import { definePage } from "@squadbase/vantage";
23
+
24
+ export const page = definePage({
25
+ title: "Monthly analysis",
26
+ description: "A monthly summary of revenue and key metrics",
27
+ });
28
+
29
+ export default function MonthlyAnalysis() {
30
+ return <h1>Monthly analysis</h1>;
31
+ }
32
+ ```
33
+
34
+ - `title` drives `document.title` (the deepest route match's title wins; otherwise it falls back to
35
+ the document's initial `<title>`).
36
+ - `title`/`description` are **read statically at generation time**. Vantage parses the source rather
37
+ than executing your page, so keep the values **literal**.
38
+
39
+ > [!WARNING]
40
+ > The **export name must be `page`** in `export const page = definePage({...})`. A different name means
41
+ > the metadata is not read.
42
+
43
+ ## Relationship to Fast Refresh
44
+
45
+ Even with a non-component export like `page`, Vantage handles it internally so React Fast Refresh
46
+ survives. Editing a page body updates in place while preserving state.
47
+
48
+ ## Prototype limitations
49
+
50
+ `definePage` also accepts `pendingComponent` / `errorComponent` / `validateSearch` as types, but in
51
+ the current prototype they are **not yet wired into lazy routes**. Per-page pending/error overrides
52
+ are unimplemented — the framework's shared defaults render instead.
53
+
54
+ ## What to read next
55
+
56
+ - [Data fetching](data-fetching) — handle server state
@@ -0,0 +1,54 @@
1
+ # AppShell
2
+
3
+ > The application frame — hand it your nav and you're done.
4
+
5
+ The frame around the whole app. Hand `groups` an array of nav entries and you get a collapsible
6
+ sidebar — or a header, for narrow screens. Use it instead of assembling
7
+ [`Sidebar`](ui/sidebar) yourself.
8
+
9
+ ```tsx
10
+ import { AppShell } from "@squadbase/vantage/components";
11
+ import type { NavGroup, NavItem } from "@squadbase/vantage/components";
12
+ ```
13
+
14
+ | Prop | Type | Default | Description |
15
+ | --- | --- | --- | --- |
16
+ | `groups` | `NavGroup[]` | | The navigation: an array of `{ label?, items: NavItem[] }`. |
17
+ | `variant` | `"sidebar" \| "header"` | `"sidebar"` | A sidebar frame, or a header with a select. |
18
+ | `actions` | `ReactNode` | | Rendered at the top right. |
19
+ | `header` | `ReactNode` | | Replaces the default header wholesale. |
20
+ | `defaultOpen` | `boolean` | `true` | With `variant="sidebar"`, whether it starts open. |
21
+ | `linkComponent` | `ElementType` | | The link component used to render items. |
22
+ | `onNavigate` | `(href: string) => void` | | Fired when an item is chosen; defaults to `location.assign`. |
23
+
24
+ ## NavItem
25
+
26
+ ```ts
27
+ interface NavItem {
28
+ label: string;
29
+ href: string;
30
+ icon?: ComponentType<{ className?: string }>;
31
+ isActive?: boolean;
32
+ disabled?: boolean;
33
+ badge?: string;
34
+ children?: NavItem[]; // collapsible sub-items
35
+ }
36
+ ```
37
+
38
+ An item with `children` becomes a disclosure.
39
+
40
+ ## Wiring it to the router
41
+
42
+ Pass `onNavigate` for client-side navigation.
43
+
44
+ ```tsx
45
+ import { useNavigate } from "@squadbase/vantage/router";
46
+
47
+ const navigate = useNavigate();
48
+
49
+ <AppShell groups={groups} onNavigate={(href) => navigate({ to: href })}>
50
+ {children}
51
+ </AppShell>;
52
+ ```
53
+
54
+ Highlighting is explicit: set `isActive` by comparing the current route's path with each `href`.