@nanisoft/prism-llms 0.4.0 → 0.5.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 (175) hide show
  1. package/README.md +88 -0
  2. package/THIRD-PARTY-NOTICES.md +48 -0
  3. package/dist/data.json +3996 -387
  4. package/dist/demo-graph.d.ts +21 -12
  5. package/dist/demo-graph.js +37 -21
  6. package/dist/extractor.d.ts +24 -17
  7. package/dist/extractor.js +269 -153
  8. package/dist/index.d.ts +12 -7
  9. package/dist/index.js +9 -7
  10. package/dist/llms-full.txt +7968 -2013
  11. package/dist/llms.txt +97 -93
  12. package/dist/markdown.d.ts +69 -23
  13. package/dist/markdown.js +131 -72
  14. package/dist/md/blocks/app-shell-01.md +135 -0
  15. package/dist/md/blocks/auth-form-01.md +135 -0
  16. package/dist/md/blocks/cta-01.md +88 -0
  17. package/dist/md/blocks/data-table-01.md +196 -0
  18. package/dist/md/blocks/feature-grid-01.md +92 -0
  19. package/dist/md/blocks/hero-01.md +90 -0
  20. package/dist/md/blocks/instrument-panel-01.md +109 -0
  21. package/dist/md/blocks/logo-strip-01.md +97 -0
  22. package/dist/md/blocks/note-grid-01.md +102 -0
  23. package/dist/md/blocks/page-header-01.md +97 -0
  24. package/dist/md/blocks/pricing-01.md +91 -0
  25. package/dist/md/blocks/process-rail-01.md +106 -0
  26. package/dist/md/blocks/product-grid-01.md +113 -0
  27. package/dist/md/blocks/settings-panel-01.md +148 -0
  28. package/dist/md/blocks/site-footer.md +103 -11
  29. package/dist/md/blocks/site-header.md +111 -11
  30. package/dist/md/blocks/stack-grid-01.md +108 -0
  31. package/dist/md/blocks/stats-01.md +89 -0
  32. package/dist/md/blocks/status-ledger-01.md +121 -0
  33. package/dist/md/changelogs/prism-llms.md +206 -0
  34. package/dist/md/changelogs/prism-mcp-server.md +88 -0
  35. package/dist/md/changelogs/prism-tokens.md +126 -0
  36. package/dist/md/changelogs/prism-ui.md +429 -0
  37. package/dist/md/components/accordion.md +108 -0
  38. package/dist/md/components/alert.md +90 -7
  39. package/dist/md/components/avatar.md +89 -7
  40. package/dist/md/components/badge.md +74 -7
  41. package/dist/md/components/breadcrumb.md +84 -7
  42. package/dist/md/components/button.md +90 -7
  43. package/dist/md/components/card.md +90 -7
  44. package/dist/md/components/checkbox.md +101 -7
  45. package/dist/md/components/cta-link.md +98 -0
  46. package/dist/md/components/diagram.md +124 -0
  47. package/dist/md/components/dialog.md +128 -0
  48. package/dist/md/components/dropdown-menu.md +125 -0
  49. package/dist/md/components/fact-list.md +85 -0
  50. package/dist/md/components/field.md +116 -0
  51. package/dist/md/components/input.md +86 -7
  52. package/dist/md/components/kbd.md +77 -0
  53. package/dist/md/components/pagination.md +95 -7
  54. package/dist/md/components/popover.md +95 -7
  55. package/dist/md/components/product-mark.md +123 -0
  56. package/dist/md/components/product-switcher.md +88 -0
  57. package/dist/md/components/progress.md +88 -7
  58. package/dist/md/components/prose.md +91 -0
  59. package/dist/md/components/radio-group.md +111 -0
  60. package/dist/md/components/section.md +91 -0
  61. package/dist/md/components/select.md +143 -7
  62. package/dist/md/components/separator.md +77 -0
  63. package/dist/md/components/skeleton.md +71 -7
  64. package/dist/md/components/slider.md +90 -7
  65. package/dist/md/components/switch.md +104 -7
  66. package/dist/md/components/table.md +104 -7
  67. package/dist/md/components/tabs.md +105 -7
  68. package/dist/md/components/textarea.md +101 -0
  69. package/dist/md/components/tooltip.md +95 -7
  70. package/dist/md/components/typography.md +82 -7
  71. package/dist/md/content/about-content.md +36 -0
  72. package/dist/md/content/audience.md +43 -0
  73. package/dist/md/content/glossary.md +69 -0
  74. package/dist/md/content/product-vocabulary.md +53 -0
  75. package/dist/md/content/voice.md +52 -0
  76. package/dist/md/content/writing-mechanics.md +58 -0
  77. package/dist/md/foundation/colors.md +10 -0
  78. package/dist/md/foundation/iconography.md +14 -0
  79. package/dist/md/foundation/motion.md +10 -0
  80. package/dist/md/foundation/radii.md +9 -0
  81. package/dist/md/foundation/shadows.md +9 -0
  82. package/dist/md/foundation/spacings.md +8 -0
  83. package/dist/md/foundation/typography.md +9 -0
  84. package/dist/md/foundation/variables.md +9 -0
  85. package/dist/md/overview/architecture.md +76 -0
  86. package/dist/md/overview/brand.md +41 -0
  87. package/dist/md/overview/composition.md +77 -0
  88. package/dist/md/overview/quickstart.md +97 -0
  89. package/dist/md/overview/theming.md +89 -0
  90. package/dist/md/overview/using-llms.md +83 -0
  91. package/dist/md/pages/auth-page.md +149 -0
  92. package/dist/md/pages/blog-post-page.md +136 -0
  93. package/dist/md/pages/dashboard-page.md +241 -0
  94. package/dist/md/pages/marketing-page.md +199 -0
  95. package/dist/md/pages/not-found-page.md +105 -0
  96. package/dist/md/pages/settings-page.md +206 -0
  97. package/dist/prism-skill.md +50 -0
  98. package/dist/store.d.ts +203 -0
  99. package/dist/store.js +317 -0
  100. package/package.json +29 -26
  101. package/dist/demo-graph.d.ts.map +0 -1
  102. package/dist/demo-graph.js.map +0 -1
  103. package/dist/extractor.d.ts.map +0 -1
  104. package/dist/extractor.js.map +0 -1
  105. package/dist/index.d.ts.map +0 -1
  106. package/dist/index.js.map +0 -1
  107. package/dist/markdown.d.ts.map +0 -1
  108. package/dist/markdown.js.map +0 -1
  109. package/dist/md/blocks/component-demo.md +0 -19
  110. package/dist/md/blocks/page-header.md +0 -19
  111. package/dist/md/components/affix.md +0 -14
  112. package/dist/md/components/anchor.md +0 -14
  113. package/dist/md/components/auto-complete.md +0 -14
  114. package/dist/md/components/back-top.md +0 -14
  115. package/dist/md/components/border-beam.md +0 -14
  116. package/dist/md/components/calendar.md +0 -14
  117. package/dist/md/components/carousel.md +0 -14
  118. package/dist/md/components/cascader.md +0 -14
  119. package/dist/md/components/col.md +0 -14
  120. package/dist/md/components/collapse.md +0 -14
  121. package/dist/md/components/color-picker.md +0 -14
  122. package/dist/md/components/date-picker.md +0 -14
  123. package/dist/md/components/descriptions.md +0 -14
  124. package/dist/md/components/display-title.md +0 -20
  125. package/dist/md/components/divider.md +0 -14
  126. package/dist/md/components/drawer.md +0 -14
  127. package/dist/md/components/dropdown.md +0 -14
  128. package/dist/md/components/empty.md +0 -14
  129. package/dist/md/components/flex.md +0 -14
  130. package/dist/md/components/float-button.md +0 -14
  131. package/dist/md/components/form.md +0 -14
  132. package/dist/md/components/grid.md +0 -14
  133. package/dist/md/components/image.md +0 -14
  134. package/dist/md/components/input-number.md +0 -14
  135. package/dist/md/components/layout.md +0 -14
  136. package/dist/md/components/list.md +0 -14
  137. package/dist/md/components/listy.md +0 -14
  138. package/dist/md/components/masonry.md +0 -14
  139. package/dist/md/components/mentions.md +0 -14
  140. package/dist/md/components/menu.md +0 -14
  141. package/dist/md/components/modal.md +0 -14
  142. package/dist/md/components/popconfirm.md +0 -14
  143. package/dist/md/components/qrcode.md +0 -14
  144. package/dist/md/components/radio.md +0 -14
  145. package/dist/md/components/rate.md +0 -14
  146. package/dist/md/components/result.md +0 -14
  147. package/dist/md/components/row.md +0 -14
  148. package/dist/md/components/segmented.md +0 -14
  149. package/dist/md/components/space.md +0 -14
  150. package/dist/md/components/spin.md +0 -14
  151. package/dist/md/components/splitter.md +0 -14
  152. package/dist/md/components/statistic.md +0 -14
  153. package/dist/md/components/steps.md +0 -14
  154. package/dist/md/components/tag.md +0 -14
  155. package/dist/md/components/time-picker.md +0 -14
  156. package/dist/md/components/timeline.md +0 -14
  157. package/dist/md/components/tour.md +0 -14
  158. package/dist/md/components/transfer.md +0 -14
  159. package/dist/md/components/tree-select.md +0 -14
  160. package/dist/md/components/tree.md +0 -14
  161. package/dist/md/components/upload.md +0 -14
  162. package/dist/md/components/watermark.md +0 -14
  163. package/dist/md/docs/brand.md +0 -41
  164. package/dist/md/pages/blog-layout.md +0 -19
  165. package/dist/md/pages/docs-shell.md +0 -23
  166. package/dist/md/theme/blue-dark.md +0 -127
  167. package/dist/md/theme/blue-light.md +0 -129
  168. package/dist/md/theme/green-dark.md +0 -127
  169. package/dist/md/theme/green-light.md +0 -129
  170. package/dist/md/theme/lavender-dark.md +0 -127
  171. package/dist/md/theme/lavender-light.md +0 -129
  172. package/dist/md/theme/peach-dark.md +0 -127
  173. package/dist/md/theme/peach-light.md +0 -129
  174. package/dist/md/theme/rose-dark.md +0 -127
  175. package/dist/md/theme/rose-light.md +0 -129
@@ -0,0 +1,105 @@
1
+ # NotFoundPage
2
+
3
+ A complete not-found screen: the status code as the heading of the page, one sentence about what happened, and the ways out.
4
+
5
+ ```tsx
6
+ import { NotFoundPage } from '@nanisoft/prism-ui/pages/not-found-page'
7
+ ```
8
+
9
+ ## Overview
10
+
11
+ NotFoundPage is a complete not-found screen: the code, what happened, and the ways
12
+ out.
13
+
14
+ All four NaniSoft sites compose one, each in its own not-found route, and three of
15
+ them are the same six lines with a different product name on it: a display title
16
+ carrying the code, one muted sentence, and two or three links. The fourth wrote
17
+ the same thing in its own markup. Four hand-written screens for one shape.
18
+
19
+ It is a Page rather than a Block because it is a whole screen: it owns the
20
+ document's `h1`, it is what a router renders when a route does not resolve, and
21
+ the band's job is not separable from the screen's. There is one correct page here
22
+ and it is short.
23
+
24
+ ## Guidelines
25
+
26
+ ### When to use
27
+
28
+ Use NotFoundPage as the body of whatever route your framework names for a
29
+ not-found response: Next's `not-found.tsx`, a Nuxt error page, a route your own
30
+ router falls through to.
31
+
32
+ Use it for every status that means "this address is not a page here", not only
33
+ 404. A 410 and a 404 are the same screen with a different code, and the code is a
34
+ prop.
35
+
36
+ ### When not to use
37
+
38
+ Do not use it for a request that failed. That is an error page with a retry, and a
39
+ reader who sees "this page does not exist" when the page exists and did not load
40
+ will not believe you next time.
41
+
42
+ Do not use it for a permission failure the reader might be granted later. That is
43
+ a 403, and it needs a sign-in link rather than a way back to the landing.
44
+
45
+ ### Best practices
46
+
47
+ - **The code is the `h1` and the sentence is not.** A not-found page whose `h1` is
48
+ "Page not found" gives a search engine and a screen reader nothing distinct to
49
+ index, and the code is the one string on the page that is the same for every
50
+ broken URL. The code takes the display step and the sentence takes the muted one,
51
+ which is the reverse of what a reader sees first and the right way round for
52
+ anything that reads the outline.
53
+ - Put the most useful destination first, and weight it as the primary action. A
54
+ not-found page that offers the homepage link before the documentation sends a
55
+ reader further from what they wanted.
56
+ - Leave `newTab` off every link. A reader who followed a broken link and is sent
57
+ to a new tab has to find their way back.
58
+ - Use the `children` slot for a search box or a list of recent posts, which is
59
+ what turns a dead end into a page.
60
+
61
+ ### Content guidelines
62
+
63
+ - Write the sentence as a fact about the address, not as an apology. "No node
64
+ here" beats "Sorry, we could not find that page".
65
+ - Say whether the page might exist later if it does. "This page does not exist
66
+ (yet)" is one clause longer and saves a support ticket.
67
+ - Keep each link label to one or two words.
68
+
69
+ **The not-found screen: the code as the h1, one sentence, and the ways out.**
70
+
71
+ ```tsx
72
+ import { NotFoundPage } from '@nanisoft/prism-ui/pages/not-found-page'
73
+
74
+ /** The not-found screen: the code as the h1, one sentence, and the ways out. */
75
+ export default function NotFoundPageDemo() {
76
+ return (
77
+ <NotFoundPage
78
+ code="404"
79
+ title="No node here."
80
+ description="The estate is fully mapped. This URL is not in the graph."
81
+ linksLabel="Ways out"
82
+ links={[
83
+ { label: 'Read the docs', href: '#docs' },
84
+ { label: 'Back to the landing', href: '#landing' },
85
+ ]}
86
+ />
87
+ )
88
+ }
89
+ ```
90
+
91
+ ## Props
92
+
93
+ **`code`** `string` · required · default: — — The status code, shown as the page's own `h1`. Required, and a string rather than a number because it is displayed, not computed: a Page never decides what code it is answering.
94
+ **`title`** `string` · required · default: — — The headline under the code: the sentence that says what happened. It is the part a reader actually reads, and it is the caller's because every product says it differently - "No node here", "This page does not exist (yet)".
95
+ **`description`** `string` · optional · default: — — One or two sentences under the headline, for anything a reader should know before they follow one of the links: that the URL may be mistyped, that the page is planned, that a search would find it.
96
+ **`links`** `readonly NotFoundLink[]` · required · default: — — The ways out, in the order a reader should see them. Put the destination most likely to help first; a not-found page that offers a homepage link before the documentation sends a reader further from what they wanted.
97
+ **`linksLabel`** `string` · required · default: — — The accessible name of the row of ways out. It is required, because it is a word a reader hears and a Page that ships no copy ships no reader-facing copy either. "Ways out" is the Page's own phrasing; a site that files its destinations differently names the same landmark differently.
98
+ **`children`** `ReactNode` · optional · default: — — A slot for whatever else the site wants to say here: a search box, a list of recent posts, a contact address.
99
+ **`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited.
100
+
101
+ ## Composition
102
+
103
+ **`exports`** `NotFoundPage` — the public runtime names this Page promises
104
+ **`source`** `packages/ui/src/pages/not-found-page/index.tsx` — the file this Page is defined in
105
+ **`dependencies`** `CtaLink, Prose, Section` — the public Prism exports this item composes
@@ -0,0 +1,206 @@
1
+ # SettingsPage
2
+
3
+ A full settings screen composing the app shell, a page header and tabs of grouped settings forms.
4
+
5
+ ```tsx
6
+ import { SettingsPage } from '@nanisoft/prism-ui/pages/settings-page'
7
+ ```
8
+
9
+ ## Overview
10
+
11
+ SettingsPage is a complete settings screen. It composes the shell, a page header
12
+ and a set of tabs, where each tab is either a saved settings form or a read-only
13
+ panel. The page owns the sequence and the tab wiring only.
14
+
15
+ The page composes these parts:
16
+
17
+ | Region | Piece | Role |
18
+ | --- | --- | --- |
19
+ | Frame | AppShell01 | the navigation rail, the top bar and the mobile navigation sheet |
20
+ | Header | PageHeader01 | the trail, the screen title and its actions |
21
+ | Tabs | Tabs, TabsList, TabsTrigger, TabsContent | the peer settings groups |
22
+ | Forms | SettingsPanel01 | the grouped and saved form for one tab |
23
+
24
+ A tab that carries `panel` renders `SettingsPanel01`: a titled card with grouped
25
+ sections, a save footer and one submit. A tab that carries `content` renders the
26
+ node as-is, which suits a read-only summary or a view that is not a form. Sections,
27
+ fields, options and labels are all props, and the page fetches nothing.
28
+
29
+ ## Guidelines
30
+
31
+ ### When to use
32
+
33
+ Use SettingsPage when a screen changes several settings that group naturally, and
34
+ each group can be saved on its own. It works when the tabs are stable and a reader
35
+ returns to one group rather than scanning the whole screen.
36
+
37
+ ### When not to use
38
+
39
+ Do not use it for a single setting. One field behind a tab is a heavier frame
40
+ than the choice deserves; put the control on the screen that owns it.
41
+
42
+ Do not use it when the settings must be compared side by side. Tabs hide one
43
+ group to show another, so a choice that depends on another group's value belongs
44
+ on one page, not behind a tab.
45
+
46
+ ### Best practices
47
+
48
+ - Keep one save per panel. A mixed model, where some fields save and others apply
49
+ immediately, makes the footer's promise unclear.
50
+ - Give every field a stable `id`, so the label is linked to the control.
51
+ - Use `content` for a read-only group. A panel with no `submitLabel` renders no
52
+ footer, which is the honest shape for a view that does not save.
53
+ - Set `defaultValue` to the group a reader is most likely to want, rather than
54
+ relying on the first tab by luck.
55
+ - Pass the same navigation node to both the rail and the sheet, and keep its ids
56
+ unique because AppShell01 renders it twice.
57
+
58
+ ### Content guidelines
59
+
60
+ - A tab label is one word in sentence case: "General", "Notifications".
61
+ - A section title is one or two words and a field label is a short noun phrase.
62
+ - A description states the effect of the group, not a policy for it.
63
+
64
+ **The settings page, with a grouped form per tab.**
65
+
66
+ ```tsx
67
+ 'use client'
68
+
69
+ import { SettingsPage } from '@nanisoft/prism-ui/pages/settings-page'
70
+
71
+ const LINKS = [
72
+ { href: '#general', label: 'General', current: false },
73
+ { href: '#settings', label: 'Settings', current: true },
74
+ { href: '#members', label: 'Members', current: false },
75
+ ]
76
+
77
+ /** The settings page, with a grouped form per tab. */
78
+ export default function SettingsPageDemo() {
79
+ return (
80
+ <SettingsPage
81
+ shell={{
82
+ navigationLabel: 'Primary',
83
+ brand: <span className="text-sm font-semibold">Northwind</span>,
84
+ breadcrumbs: [{ label: 'Settings', href: '#settings' }, { label: 'Workspace' }],
85
+ navigation: (
86
+ <ul className="flex flex-col gap-1 text-sm">
87
+ {LINKS.map((link) => (
88
+ <li key={link.href}>
89
+ <a
90
+ href={link.href}
91
+ className={
92
+ link.current
93
+ ? 'bg-accent text-accent-foreground block rounded-md px-3 py-2 font-medium'
94
+ : 'text-muted-foreground hover:text-foreground block rounded-md px-3 py-2'
95
+ }
96
+ >
97
+ {link.label}
98
+ </a>
99
+ </li>
100
+ ))}
101
+ </ul>
102
+ ),
103
+ }}
104
+ header={{
105
+ title: 'Workspace settings',
106
+ description: 'Manage how this workspace behaves for everyone on the team.',
107
+ }}
108
+ tabs={[
109
+ {
110
+ value: 'general',
111
+ label: 'General',
112
+ panel: {
113
+ title: 'General',
114
+ description: 'Shown to everyone you collaborate with.',
115
+ submitLabel: 'Save changes',
116
+ secondaryAction: { label: 'Cancel' },
117
+ sections: [
118
+ {
119
+ id: 'identity',
120
+ title: 'Identity',
121
+ fields: [
122
+ {
123
+ kind: 'text',
124
+ id: 'settings-workspace-name',
125
+ label: 'Workspace name',
126
+ defaultValue: 'Northwind',
127
+ },
128
+ {
129
+ kind: 'textarea',
130
+ id: 'settings-workspace-description',
131
+ label: 'Description',
132
+ placeholder: 'What does this workspace do?',
133
+ rows: 3,
134
+ },
135
+ {
136
+ kind: 'select',
137
+ id: 'settings-workspace-region',
138
+ label: 'Data region',
139
+ placeholder: 'Choose a region',
140
+ defaultValue: 'eu-west',
141
+ options: [
142
+ { label: 'Europe West', value: 'eu-west' },
143
+ { label: 'US East', value: 'us-east' },
144
+ ],
145
+ },
146
+ ],
147
+ },
148
+ ],
149
+ },
150
+ },
151
+ {
152
+ value: 'notifications',
153
+ label: 'Notifications',
154
+ panel: {
155
+ title: 'Notifications',
156
+ description: 'Choose what the workspace sends and when.',
157
+ submitLabel: 'Save changes',
158
+ sections: [
159
+ {
160
+ id: 'email',
161
+ title: 'Email',
162
+ fields: [
163
+ {
164
+ kind: 'switch',
165
+ id: 'settings-weekly-digest',
166
+ label: 'Weekly digest',
167
+ description: 'A summary of activity every Monday.',
168
+ defaultChecked: true,
169
+ },
170
+ {
171
+ kind: 'switch',
172
+ id: 'settings-mention-alerts',
173
+ label: 'Mention alerts',
174
+ description: 'Notify me when someone mentions my name.',
175
+ },
176
+ ],
177
+ },
178
+ ],
179
+ },
180
+ },
181
+ ]}
182
+ />
183
+ )
184
+ }
185
+ ```
186
+
187
+ ## Props
188
+
189
+ **`shell`** `Omit<ComponentProps<typeof AppShell01>, 'children'>` · required · default: — — The frame: rail, top bar and mobile navigation sheet.
190
+ **`header`** `ComponentProps<typeof PageHeader01>` · required · default: — — The page title band.
191
+ **`tabs`** `SettingsPageTab[]` · required · default: — — The tabs, in order. At least one is required.
192
+ **`defaultValue`** `string` · optional · default: — — The tab shown first, for uncontrolled tabs. Defaults to the first tab.
193
+ **`value`** `string` · optional · default: — — The controlled active tab.
194
+ **`onValueChange`** `(value: string) => void` · optional · default: —
195
+
196
+ ## Composition
197
+
198
+ **`exports`** `SettingsPage` — the public runtime names this Page promises
199
+ **`source`** `packages/ui/src/pages/settings-page/index.tsx` — the file this Page is defined in
200
+ **`dependencies`** `AppShell01, PageHeader01, SettingsPanel01, Tabs` — the public Prism exports this item composes
201
+
202
+ ## Blocks
203
+
204
+ - [AppShell01](https://prism.nanisoft.com/blocks/app-shell-01.md)
205
+ - [PageHeader01](https://prism.nanisoft.com/blocks/page-header-01.md)
206
+ - [SettingsPanel01](https://prism.nanisoft.com/blocks/settings-panel-01.md)
@@ -0,0 +1,50 @@
1
+ # Prism agent skill
2
+
3
+ Prism is NaniSoft's design system: design tokens, a React component library, a
4
+ documentation site, and this agent surface. This is the fast path. The index is
5
+ [`/llms.txt`](https://prism.nanisoft.com/llms.txt) and every page in full is
6
+ [`/llms-full.txt`](https://prism.nanisoft.com/llms-full.txt); both are generated from the
7
+ checked catalogue and the authored pages.
8
+
9
+ ## Start here
10
+
11
+ ```tsx
12
+ import '@nanisoft/prism-ui/styles.css'
13
+
14
+ import { PrismProvider, PrismThemeScript } from '@nanisoft/prism-ui/provider'
15
+ ```
16
+
17
+ Import the one stylesheet once. The provider is optional: the declarative axes
18
+ are `data-pack` on `<html>` and the `dark` class for mode.
19
+
20
+ ## Import contract
21
+
22
+ - Components: `@nanisoft/prism-ui/components/<slug>`
23
+ - Blocks: `@nanisoft/prism-ui/blocks/<slug>`
24
+ - Pages: `@nanisoft/prism-ui/pages/<slug>`
25
+
26
+ Compound parts stay inside their module. Base UI and every internal path are
27
+ never a consumer import.
28
+
29
+ ## MCP
30
+
31
+ The read-only MCP endpoint is `https://prism.nanisoft.com/mcp`. It exposes nine tools:
32
+ `list_items`, `get_item_doc`, `get_item_props`, `get_item_source`,
33
+ `get_theme_doc`, `list_pages`, `get_page`, `search_docs` and
34
+ `get_changelog`.
35
+
36
+ ## Truth rules
37
+
38
+ - Prism is the one source of truth. A consumer composes; it never writes CSS and
39
+ never overrides a style.
40
+ - There is no override path. When Prism lacks a component, token or variant,
41
+ request it upstream.
42
+ - Generated code imports from `@nanisoft/prism-ui` only.
43
+
44
+ ## This corpus
45
+
46
+ Generated from the catalogue and the authored pages: 34
47
+ Components, 19 Blocks and 6 Pages, plus the Overview,
48
+ Foundation, Content and Changelogs pages. The Changelogs pages are each
49
+ published package's own changelog, byte for byte; `get_changelog` returns one
50
+ package's, optionally one version of it.
@@ -0,0 +1,203 @@
1
+ /**
2
+ * The `PrismDocsStore` contract: the one type the MCP server validates at
3
+ * runtime, and the one runtime guard that produces it.
4
+ *
5
+ * Ticket 12 section 7 makes this file the canonical home. The store is a
6
+ * build-time projection of the catalogue, the authored pages and the token
7
+ * cascade; the MCP server imports both the type and `parsePrismDocsStore` and
8
+ * never redeclares either.
9
+ *
10
+ * `kind` is ticket 09's closed union. The JSON arrives as `unknown`, the guard
11
+ * narrows it structurally, and `kind` is validated through a local list that is
12
+ * tied to the catalogue's type with `satisfies` plus a type-equality assertion.
13
+ * A widened `kind: string` is rejected at runtime and at compile time, which is
14
+ * the bug the old package recorded.
15
+ */
16
+ import type { CatalogKind, ComponentCategory } from '@nanisoft/prism-ui/catalog';
17
+ export declare const STORE_KINDS: readonly ["component", "block", "page"];
18
+ export declare const STORE_CATEGORIES: readonly ["Call to action", "Forms and inputs", "Feedback", "Layout", "Data display", "Typography", "Miscellaneous"];
19
+ export declare const STORE_STATUSES: readonly ["stable", "deprecated"];
20
+ /**
21
+ * The content Sections, in the reading order the site publishes them, and the
22
+ * same order `llms.txt` groups them in.
23
+ *
24
+ * These are the Section *directories*, so the list is the walk the corpus builder
25
+ * takes and the set of directories the site's gate checks. The three catalogue
26
+ * Sections are not here: an Item is a catalogue entry with a `kind`, and its page
27
+ * is emitted from the Catalogue rather than walked out of the content tree, so
28
+ * adding `components` to this list would make the walk look for a directory that
29
+ * is not one.
30
+ *
31
+ * **A Section's route is its directory, and the two were renames.** `docs` is
32
+ * `overview` and `foundations` is `foundation`, which is the rule that a prose
33
+ * Section is one body of knowledge and takes a singular route while a catalogue
34
+ * Section is a collection of many Items and takes a plural one. An agent holding
35
+ * a cached `llms.txt` from before the move still resolves every URL it names,
36
+ * because the site Worker redirects each of these routes permanently, and the
37
+ * corpus is rebuilt per release and points at the new ones. Nothing here is
38
+ * aliased: a page's `section` is the directory it is filed in, which is what
39
+ * `get_page` matches on, and a `Record<StoreSection, string>` over a list that
40
+ * had to be edited in the same commit as the rename is a second list that can be
41
+ * half done.
42
+ */
43
+ export declare const STORE_SECTIONS: readonly ["overview", "foundation", "content", "changelogs"];
44
+ /**
45
+ * The label each content Section is read under, in every artifact that groups
46
+ * pages by Section.
47
+ *
48
+ * `Record<StoreSection, string>` rather than a separate list, because a Section
49
+ * added to `STORE_SECTIONS` with no label is a compile error here rather than a
50
+ * Section that `llms.txt`, `list_pages` and the Corpus each spell their own way.
51
+ * The keys are the Section directories themselves, so the label cannot be filed
52
+ * under a Section that does not exist.
53
+ *
54
+ * The label is the Section's name rather than its directory, which is the whole
55
+ * point of the pair: the directory is what the tree is called, and the name is
56
+ * what a reader and an agent are told. `llms.txt` groups under these headings and
57
+ * `list_pages` counts them, so a Section renamed without its label renamed here
58
+ * would be advertised under two names in two artifacts.
59
+ */
60
+ export declare const STORE_SECTION_TITLES: Record<StoreSection, string>;
61
+ export declare const STORE_PACKS: readonly ["default", "blush", "mint", "lavender", "sky", "peach"];
62
+ export declare const STORE_MODES: readonly ["light", "dark"];
63
+ export declare const STORE_SCALE_GROUPS: readonly ["motion", "typography", "spacing", "shadow", "breakpoint", "container"];
64
+ export type StoreKind = (typeof STORE_KINDS)[number];
65
+ export type StoreStatus = (typeof STORE_STATUSES)[number];
66
+ export type StoreSection = (typeof STORE_SECTIONS)[number];
67
+ export type PackId = (typeof STORE_PACKS)[number];
68
+ export type Mode = (typeof STORE_MODES)[number];
69
+ export type PrismScaleGroup = (typeof STORE_SCALE_GROUPS)[number];
70
+ /** `'doc'` is a non-item page (a guide, a Foundation, a Content page). */
71
+ export type TokenGroup = 'semantic' | PrismScaleGroup;
72
+ export interface PrismDocsExample {
73
+ readonly title: string;
74
+ readonly code: string;
75
+ }
76
+ export interface PrismDocsStoreEntry {
77
+ readonly id: string;
78
+ readonly slug: string;
79
+ readonly kind: CatalogKind;
80
+ readonly name: string;
81
+ readonly category: ComponentCategory | null;
82
+ readonly status: StoreStatus;
83
+ readonly description: string;
84
+ /** The item's canonical site path, for example `/components/button`. */
85
+ readonly url: string;
86
+ /** The canonical path plus `.md`, for example `/components/button.md`. */
87
+ readonly mirror: string;
88
+ readonly source: string;
89
+ readonly exports: readonly string[];
90
+ /** The public import line ticket 11 section 9 fixes. */
91
+ readonly importLine: string;
92
+ /** The full per-item spec, byte-identical to the mirror file. */
93
+ readonly doc: string;
94
+ /** The `## Props` section body, for a Component. */
95
+ readonly props?: string;
96
+ /** The `## Composition` section body, for a Block or a Page. */
97
+ readonly composition?: string;
98
+ /** The verbatim demo plus its title, when a demo exists. */
99
+ readonly example?: PrismDocsExample;
100
+ readonly references: {
101
+ readonly blocks: readonly string[];
102
+ readonly pages: readonly string[];
103
+ };
104
+ }
105
+ export interface PrismDocsPage {
106
+ readonly id: string;
107
+ /** The page's path below its Section, without the extension: `tokens/colors`. */
108
+ readonly slug: string;
109
+ /** The top-level Section directory the page sits in. */
110
+ readonly section: StoreSection;
111
+ readonly title: string;
112
+ readonly description: string;
113
+ /** The page's canonical site path, for example `/overview/quickstart`. */
114
+ readonly url: string;
115
+ readonly markdown: string;
116
+ readonly mirror: string;
117
+ }
118
+ /**
119
+ * One version entry of a published package's changelog.
120
+ *
121
+ * `body` is the text under the version's own `## <version>` heading, sliced by
122
+ * the shared changelog rule and never re-levelled: the file is published whole
123
+ * and re-levelling a heading would be another transformation between the
124
+ * package's bytes and the agent's.
125
+ */
126
+ export interface PrismChangelogRelease {
127
+ readonly version: string;
128
+ readonly body: string;
129
+ }
130
+ /**
131
+ * One published package's changelog, projected from the generated file the site
132
+ * renders.
133
+ *
134
+ * This is the field the ninth read-only tool answers from, and it exists so that
135
+ * a breaking change in a published package is discoverable by an agent. The
136
+ * reference design system shipped a breaking module-system change that no agent
137
+ * using it could find, because its corpus had no changelog field and no tool
138
+ * could return one.
139
+ *
140
+ * `text` is the generated file verbatim, which is a byte-for-byte copy of the
141
+ * package's own `CHANGELOG.md`. `releases` is the shared rule's reading of those
142
+ * same bytes, and the two cannot disagree because the rule is the only thing
143
+ * that produces either.
144
+ */
145
+ export interface PrismChangelog {
146
+ /** The published npm name, which is what an agent asks for. */
147
+ readonly package: string;
148
+ /** The route segment the changelog is published at: the unscoped name. */
149
+ readonly slug: string;
150
+ /** The site's route for it, and the mirror an agent can fetch instead. */
151
+ readonly route: string;
152
+ /** The file's own first heading, which names the package. */
153
+ readonly title: string;
154
+ /** Every version the file records, newest first as the generator writes it. */
155
+ readonly versions: readonly string[];
156
+ readonly releases: readonly PrismChangelogRelease[];
157
+ /** The generated file, byte for byte. */
158
+ readonly text: string;
159
+ }
160
+ export interface PrismSemanticToken {
161
+ readonly token: string;
162
+ readonly value: string;
163
+ }
164
+ export interface PrismScaleToken {
165
+ readonly token: string;
166
+ readonly value: string;
167
+ /** The Tailwind binding, when the token has a mirror custom property. */
168
+ readonly binding?: string;
169
+ }
170
+ export interface PrismThemeTokens {
171
+ readonly pack: PackId;
172
+ readonly mode: Mode;
173
+ readonly semantic: readonly PrismSemanticToken[];
174
+ }
175
+ export interface PrismTokensProjection {
176
+ readonly packs: readonly PackId[];
177
+ readonly modes: readonly Mode[];
178
+ readonly themes: readonly PrismThemeTokens[];
179
+ readonly scales: Record<PrismScaleGroup, readonly PrismScaleToken[]>;
180
+ }
181
+ export interface PrismDocsStore {
182
+ readonly version: string;
183
+ readonly items: readonly PrismDocsStoreEntry[];
184
+ readonly pages: readonly PrismDocsPage[];
185
+ /**
186
+ * One entry per published package that ships a changelog. Required rather than
187
+ * optional: the field is what makes a published breaking change discoverable
188
+ * by an agent, and a store that quietly omitted it would leave the tool that
189
+ * reads it answering for nothing while every other gate stayed green.
190
+ */
191
+ readonly changelogs: readonly PrismChangelog[];
192
+ readonly tokens: PrismTokensProjection;
193
+ }
194
+ /**
195
+ * Narrow an `unknown` JSON payload to a `PrismDocsStore`, or throw with the
196
+ * offending path. This is the only place a `PrismDocsStore` is produced from
197
+ * JSON: nothing is assigned with `as`, and `kind` is never widened to `string`.
198
+ *
199
+ * The order of the fields is the order of the layers that have to have carried
200
+ * the change. `items` before `changelogs`, so a document with a widened `kind`
201
+ * reports the path a reader is more likely to be looking at.
202
+ */
203
+ export declare function parsePrismDocsStore(raw: unknown): PrismDocsStore;