@contractspec/bundle.library 3.9.8 → 3.9.9

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 (70) hide show
  1. package/.turbo/turbo-build.log +222 -214
  2. package/CHANGELOG.md +52 -0
  3. package/dist/components/docs/DocsIndexPage.js +2 -2
  4. package/dist/components/docs/docsManifest.js +1 -1
  5. package/dist/components/docs/getting-started/DataViewTutorialPage.js +81 -6
  6. package/dist/components/docs/getting-started/index.js +94 -19
  7. package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.d.ts +6 -0
  8. package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.js +176 -0
  9. package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.d.ts +1 -0
  10. package/dist/components/docs/guides/GuideDataExchangeImportTemplatesPage.js +176 -0
  11. package/dist/components/docs/guides/GuidesIndexPage.js +2 -2
  12. package/dist/components/docs/guides/index.d.ts +1 -0
  13. package/dist/components/docs/guides/index.js +220 -46
  14. package/dist/components/docs/index.js +1003 -309
  15. package/dist/components/docs/libraries/LibrariesApplicationShellPage.content.d.ts +22 -5
  16. package/dist/components/docs/libraries/LibrariesApplicationShellPage.content.js +125 -37
  17. package/dist/components/docs/libraries/LibrariesApplicationShellPage.js +125 -37
  18. package/dist/components/docs/libraries/LibrariesDataViewsPage.js +120 -3
  19. package/dist/components/docs/libraries/LibrariesDesignSystemPage.js +101 -2
  20. package/dist/components/docs/libraries/LibrariesOverviewPage.js +1 -1
  21. package/dist/components/docs/libraries/LibrariesPersonalizationPage.js +58 -4
  22. package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.content.d.ts +10 -0
  23. package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.content.js +43 -0
  24. package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.d.ts +1 -0
  25. package/dist/components/docs/libraries/LibrariesTranslationRuntimePage.js +43 -0
  26. package/dist/components/docs/libraries/index.d.ts +1 -0
  27. package/dist/components/docs/libraries/index.js +496 -97
  28. package/dist/components/docs/specs/SpecsDataViewsPage.js +49 -3
  29. package/dist/components/docs/specs/index.js +60 -14
  30. package/dist/index.js +1014 -320
  31. package/dist/node/components/docs/DocsIndexPage.js +2 -2
  32. package/dist/node/components/docs/docsManifest.js +1 -1
  33. package/dist/node/components/docs/getting-started/DataViewTutorialPage.js +81 -6
  34. package/dist/node/components/docs/getting-started/index.js +94 -19
  35. package/dist/node/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.js +175 -0
  36. package/dist/node/components/docs/guides/GuideDataExchangeImportTemplatesPage.js +175 -0
  37. package/dist/node/components/docs/guides/GuidesIndexPage.js +2 -2
  38. package/dist/node/components/docs/guides/index.js +220 -46
  39. package/dist/node/components/docs/index.js +1003 -309
  40. package/dist/node/components/docs/libraries/LibrariesApplicationShellPage.content.js +125 -37
  41. package/dist/node/components/docs/libraries/LibrariesApplicationShellPage.js +125 -37
  42. package/dist/node/components/docs/libraries/LibrariesDataViewsPage.js +120 -3
  43. package/dist/node/components/docs/libraries/LibrariesDesignSystemPage.js +101 -2
  44. package/dist/node/components/docs/libraries/LibrariesOverviewPage.js +1 -1
  45. package/dist/node/components/docs/libraries/LibrariesPersonalizationPage.js +58 -4
  46. package/dist/node/components/docs/libraries/LibrariesTranslationRuntimePage.content.js +42 -0
  47. package/dist/node/components/docs/libraries/LibrariesTranslationRuntimePage.js +42 -0
  48. package/dist/node/components/docs/libraries/index.js +496 -97
  49. package/dist/node/components/docs/specs/SpecsDataViewsPage.js +49 -3
  50. package/dist/node/components/docs/specs/index.js +60 -14
  51. package/dist/node/index.js +1014 -320
  52. package/package.json +74 -26
  53. package/src/components/docs/docsManifest.test.ts +87 -0
  54. package/src/components/docs/docsManifest.ts +90 -3
  55. package/src/components/docs/generated/docs-index.notifications.json +7 -7
  56. package/src/components/docs/getting-started/DataViewTutorialPage.tsx +181 -50
  57. package/src/components/docs/guides/GuideDataExchangeImportTemplatesPage.content.ts +185 -0
  58. package/src/components/docs/guides/GuideDataExchangeImportTemplatesPage.tsx +186 -0
  59. package/src/components/docs/guides/GuidesIndexPage.tsx +49 -42
  60. package/src/components/docs/guides/index.ts +1 -0
  61. package/src/components/docs/libraries/LibrariesApplicationShellPage.content.ts +148 -35
  62. package/src/components/docs/libraries/LibrariesApplicationShellPage.tsx +38 -5
  63. package/src/components/docs/libraries/LibrariesDataViewsPage.tsx +267 -64
  64. package/src/components/docs/libraries/LibrariesDesignSystemPage.tsx +235 -0
  65. package/src/components/docs/libraries/LibrariesOverviewPage.tsx +8 -2
  66. package/src/components/docs/libraries/LibrariesPersonalizationPage.tsx +141 -31
  67. package/src/components/docs/libraries/LibrariesTranslationRuntimePage.content.ts +78 -0
  68. package/src/components/docs/libraries/LibrariesTranslationRuntimePage.tsx +137 -0
  69. package/src/components/docs/libraries/index.ts +1 -0
  70. package/src/components/docs/specs/SpecsDataViewsPage.tsx +239 -113
@@ -1,4 +1,7 @@
1
1
  import { CodeBlock } from '@contractspec/lib.design-system';
2
+ import { HStack, VStack } from '@contractspec/lib.design-system/layout';
3
+ import { List, ListItem } from '@contractspec/lib.design-system/list';
4
+ import { H1, H2, P, Text } from '@contractspec/lib.design-system/typography';
2
5
  import Link from '@contractspec/lib.ui-link';
3
6
  import { ArrowRight, CheckCircle2, GitBranch } from 'lucide-react';
4
7
 
@@ -31,6 +34,13 @@ const guides = [
31
34
  href: '/docs/guides/contract-driven-forms',
32
35
  time: '25 min',
33
36
  },
37
+ {
38
+ title: 'Flexible import templates',
39
+ description:
40
+ 'Accept partner CSV, JSON, and XML files with alternate headers and localized values while preserving a canonical import contract.',
41
+ href: '/docs/guides/data-exchange-import-templates',
42
+ time: '25 min',
43
+ },
34
44
  {
35
45
  title: 'Generate docs and clients',
36
46
  description:
@@ -84,64 +94,61 @@ const guides = [
84
94
 
85
95
  export function GuidesIndexPage() {
86
96
  return (
87
- <div className="space-y-10">
88
- <div className="space-y-3">
89
- <p className="editorial-kicker">Build</p>
90
- <h1 className="font-serif text-4xl tracking-[-0.04em] md:text-5xl">
97
+ <VStack className="space-y-10">
98
+ <VStack className="space-y-3">
99
+ <Text className="editorial-kicker">Build</Text>
100
+ <H1 className="font-serif text-4xl tracking-[-0.04em] md:text-5xl">
91
101
  Adoption guides for teams that want to keep their code.
92
- </h1>
93
- <p className="max-w-3xl text-lg text-muted-foreground leading-8">
102
+ </H1>
103
+ <P className="max-w-3xl text-lg text-muted-foreground leading-8">
94
104
  These guides assume you are introducing ContractSpec into a real code
95
105
  base. Start with a narrow surface, verify the generated outputs, and
96
106
  expand only after the contract loop feels trustworthy.
97
- </p>
98
- </div>
107
+ </P>
108
+ </VStack>
99
109
 
100
- <div className="grid gap-4 md:grid-cols-2">
110
+ <VStack className="grid gap-4 md:grid-cols-2">
101
111
  {guides.map((guide) => (
102
112
  <Link key={guide.href} href={guide.href} className="editorial-panel">
103
- <div className="flex items-start justify-between gap-4">
104
- <div>
105
- <h2 className="font-semibold text-xl">{guide.title}</h2>
106
- <p className="mt-2 text-muted-foreground text-sm leading-7">
113
+ <HStack className="flex items-start justify-between gap-4">
114
+ <VStack>
115
+ <H2 className="font-semibold text-xl">{guide.title}</H2>
116
+ <P className="mt-2 text-muted-foreground text-sm leading-7">
107
117
  {guide.description}
108
- </p>
109
- </div>
118
+ </P>
119
+ </VStack>
110
120
  <ArrowRight className="mt-1 shrink-0" size={18} />
111
- </div>
112
- <div className="mt-4 flex items-center gap-2 text-muted-foreground text-xs">
121
+ </HStack>
122
+ <HStack className="mt-4 flex items-center gap-2 text-muted-foreground text-xs">
113
123
  <CheckCircle2 size={14} />
114
- <span>Target time: {guide.time}</span>
115
- </div>
124
+ <Text>Target time: {guide.time}</Text>
125
+ </HStack>
116
126
  </Link>
117
127
  ))}
118
- </div>
128
+ </VStack>
119
129
 
120
- <div className="editorial-panel space-y-4">
121
- <div className="flex items-center gap-2 font-semibold text-[color:var(--rust)] text-sm uppercase tracking-[0.2em]">
130
+ <VStack className="editorial-panel space-y-4">
131
+ <HStack className="flex items-center gap-2 font-semibold text-[color:var(--rust)] text-sm uppercase tracking-[0.2em]">
122
132
  <GitBranch size={16} />
123
- Working style
124
- </div>
125
- <ul className="editorial-list">
126
- <li>
127
- <span className="editorial-list-marker" />
128
- <span>Run each guide in a branch or sandboxed workspace.</span>
129
- </li>
130
- <li>
131
- <span className="editorial-list-marker" />
132
- <span>
133
+ <Text>Working style</Text>
134
+ </HStack>
135
+ <List className="editorial-list">
136
+ <ListItem>
137
+ <Text>Run each guide in a branch or sandboxed workspace.</Text>
138
+ </ListItem>
139
+ <ListItem>
140
+ <Text>
133
141
  Prefer one bounded surface at a time: one endpoint, one workflow,
134
142
  one integration, one unsafe module.
135
- </span>
136
- </li>
137
- <li>
138
- <span className="editorial-list-marker" />
139
- <span>
143
+ </Text>
144
+ </ListItem>
145
+ <ListItem>
146
+ <Text>
140
147
  Use the example and reference outputs to verify what changed, not
141
148
  just the narrative page.
142
- </span>
143
- </li>
144
- </ul>
149
+ </Text>
150
+ </ListItem>
151
+ </List>
145
152
  <CodeBlock
146
153
  language="bash"
147
154
  filename="guides-quickstart"
@@ -151,7 +158,7 @@ contractspec examples list
151
158
  # validate the examples in this workspace
152
159
  contractspec examples validate --repo-root .`}
153
160
  />
154
- </div>
155
- </div>
161
+ </VStack>
162
+ </VStack>
156
163
  );
157
164
  }
@@ -4,6 +4,7 @@ export { GuideCIDiffGatingPage } from './GuideCIDiffGatingPage';
4
4
  export { GuideConnectInRepoPage } from './GuideConnectInRepoPage';
5
5
  export { GuideContractDrivenFormsPage } from './GuideContractDrivenFormsPage';
6
6
  export { GuideContractTypesPage } from './GuideContractTypesPage';
7
+ export { GuideDataExchangeImportTemplatesPage } from './GuideDataExchangeImportTemplatesPage';
7
8
  export { GuideDocsPipelinePage } from './GuideDocsPipelinePage';
8
9
  export { GuideFirstModuleBundlePage } from './GuideFirstModuleBundlePage';
9
10
  export { GuideGenerateDocsClientsSchemasPage } from './GuideGenerateDocsClientsSchemasPage';
@@ -1,11 +1,12 @@
1
1
  export const shellUsageExample = `import {
2
2
  AppShell,
3
- PageOutline,
4
- type AppShellNavigationSection,
3
+ type ShellCommandGroup,
4
+ type ShellNavSection,
5
+ type ShellNotificationCenter,
5
6
  type PageOutlineItem,
6
7
  } from "@contractspec/lib.design-system/shell";
7
8
 
8
- const navigation: AppShellNavigationSection[] = [
9
+ const navigation: ShellNavSection[] = [
9
10
  {
10
11
  title: "Workspace",
11
12
  items: [
@@ -22,6 +23,16 @@ const navigation: AppShellNavigationSection[] = [
22
23
  },
23
24
  ];
24
25
 
26
+ const commands: ShellCommandGroup[] = [
27
+ {
28
+ heading: "Quick actions",
29
+ items: [
30
+ { id: "new-contract", label: "New contract", shortcut: "N" },
31
+ { id: "import", label: "Import existing app" },
32
+ ],
33
+ },
34
+ ];
35
+
25
36
  const outline: PageOutlineItem[] = [
26
37
  {
27
38
  id: "architecture",
@@ -34,43 +45,108 @@ const outline: PageOutlineItem[] = [
34
45
  },
35
46
  ];
36
47
 
48
+ const notifications: ShellNotificationCenter = {
49
+ label: "Notifications",
50
+ loading: false,
51
+ unreadCount: 2,
52
+ items: [
53
+ {
54
+ id: "contract-approved",
55
+ title: "Contract approved",
56
+ body: "Billing.create is ready to publish.",
57
+ status: "unread",
58
+ createdAt: "2026-04-29T09:30:00Z",
59
+ actionUrl: "/contracts/billing.create",
60
+ category: "Review",
61
+ },
62
+ ],
63
+ onSelect: (item) => openNotificationTarget(item),
64
+ onMarkRead: (item) => markNotificationRead(item.id),
65
+ onMarkAllRead: () => markAllNotificationsRead(),
66
+ };
67
+
37
68
  export function WorkspacePage() {
38
69
  return (
39
70
  <AppShell
40
- brand={{ label: "ContractSpec", href: "/dashboard" }}
71
+ title="ContractSpec"
72
+ homeHref="/dashboard"
41
73
  navigation={navigation}
74
+ commands={commands}
42
75
  breadcrumbs={[
43
76
  { label: "Workspace", href: "/dashboard" },
44
77
  { label: "Contracts" },
45
78
  ]}
46
- command={{
47
- placeholder: "Search contracts or run an action",
48
- groups: [
49
- {
50
- title: "Quick actions",
51
- actions: [
52
- { id: "new-contract", label: "New contract" },
53
- { id: "import", label: "Import existing app" },
54
- ],
55
- },
56
- ],
57
- }}
58
- user={{
59
- name: "Ada Lovelace",
60
- email: "ada@example.com",
61
- actions: [{ label: "Sign out", onSelect: () => signOut() }],
62
- }}
63
- pageOutline={<PageOutline items={outline} activeId="desktop" />}
79
+ notifications={notifications}
80
+ pageOutline={outline}
81
+ activeHref="/contracts"
82
+ activeOutlineId="desktop"
83
+ userMenu={<UserMenu onSignOut={() => signOut()} />}
64
84
  >
65
85
  <main>{/* route content */}</main>
66
86
  </AppShell>
67
87
  );
68
88
  }`;
69
89
 
90
+ export const notificationCenterExample = `import {
91
+ ListNotificationsOutputModel,
92
+ MarkNotificationReadInputModel,
93
+ } from "@contractspec/lib.contracts-spec/notifications";
94
+ import {
95
+ notificationsSchemaContribution,
96
+ renderNotificationTemplate,
97
+ } from "@contractspec/lib.notification";
98
+ import type { ShellNotificationCenter } from "@contractspec/lib.design-system/shell";
99
+
100
+ type NotificationListResult = {
101
+ unreadCount: number;
102
+ notifications: Array<{
103
+ id: string;
104
+ title: string;
105
+ body: string;
106
+ type: string;
107
+ status: string;
108
+ readAt?: string | Date | null;
109
+ createdAt: string | Date;
110
+ actionUrl?: string;
111
+ metadata?: Record<string, unknown>;
112
+ }>;
113
+ };
114
+
115
+ export function toShellNotifications(
116
+ data: NotificationListResult,
117
+ actions: {
118
+ open: (id: string) => void;
119
+ markRead: (input: { notificationId: string }) => void;
120
+ markAllRead: () => void;
121
+ }
122
+ ): ShellNotificationCenter {
123
+ return {
124
+ unreadCount: data.unreadCount,
125
+ items: data.notifications.map((notification) => ({
126
+ id: notification.id,
127
+ title: notification.title,
128
+ body: notification.body,
129
+ status: notification.status,
130
+ createdAt: notification.createdAt,
131
+ actionUrl: notification.actionUrl,
132
+ category: notification.type,
133
+ metadata: notification.metadata,
134
+ })),
135
+ onSelect: (item) => actions.open(item.id),
136
+ onMarkRead: (item) => actions.markRead({ notificationId: item.id }),
137
+ onMarkAllRead: actions.markAllRead,
138
+ };
139
+ }
140
+
141
+ void ListNotificationsOutputModel;
142
+ void MarkNotificationReadInputModel;
143
+ void notificationsSchemaContribution;
144
+ void renderNotificationTemplate;`;
145
+
70
146
  export const scratchPrompt = `You are implementing a modern application shell from scratch.
71
147
 
72
148
  Goal:
73
- Build a reusable application shell for a React/Next.js web app and an Expo React Native app. The shell must provide a desktop sidebar, desktop topbar, command search, breadcrumbs, nested navigation, user/auth actions, and an in-page section navigator called PageOutline.
149
+ Build a reusable application shell for a React/Next.js web app and an Expo React Native app. The shell must provide a desktop sidebar, desktop topbar, command search, breadcrumbs, nested navigation, user/auth actions, in-app notifications, and an in-page section navigator called PageOutline.
74
150
 
75
151
  Use this architecture:
76
152
  - Keep route content independent from navigation chrome.
@@ -78,29 +154,37 @@ Use this architecture:
78
154
  - Create a command model with search input, grouped suggestions, quick actions, keyboard shortcut labels, empty state, and loading state.
79
155
  - Create a breadcrumb model for the topbar.
80
156
  - Create a PageOutline model for right-side in-page navigation with exactly three supported levels. It should render anchors, support active section state, and degrade gracefully when no sections exist.
157
+ - Create a ShellNotificationCenter model with render-ready items, unread count, loading and empty states, onSelect, onMarkRead, onMarkAllRead, and optional custom item rendering.
81
158
  - Expose the system from the design system or a dedicated shell module, not from a single app route.
82
159
 
160
+ Notification boundary:
161
+ - Use @contractspec/lib.contracts-spec/notifications as the canonical source for notification contracts, operation models, and feature metadata.
162
+ - Use @contractspec/lib.notification for reusable notification entities, schema contribution, channels, templates, and i18n helpers.
163
+ - Keep persistence, polling/subscriptions, delivery providers, and optimistic mutations in the host application or notification runtime layer.
164
+ - Pass only render-ready ShellNotificationCenter state into AppShell so the design system does not import or own notification runtime behavior.
165
+
83
166
  Desktop behavior:
84
167
  - Persistent left sidebar with app logo/title, command trigger, grouped navigation, nested submenus, and current user/auth/logout area.
85
168
  - Topbar with breadcrumbs and an optional command trigger.
169
+ - Topbar notification trigger with unread badge, loading/empty states, mark-read actions, and item selection.
86
170
  - Content area with optional right PageOutline.
87
171
  - Keep dimensions stable. Navigation labels must not resize layout on hover or active state.
88
172
 
89
173
  Mobile web behavior:
90
174
  - Use bottom navigation for the primary destinations.
91
- - Put deeper navigation, command search, auth actions, and secondary actions behind a menu or drawer.
175
+ - Put deeper navigation, command search, notifications, auth actions, and secondary actions behind a menu or drawer when the topbar cannot safely hold them.
92
176
  - Keep route content first and make the shell controls reachable without covering important content.
93
177
 
94
178
  Native behavior:
95
179
  - Add .native.tsx entrypoints for Expo/React Native.
96
- - Prefer bottom tabs for primary destinations and a menu/sheet for deeper navigation and account actions.
97
- - Keep the same typed navigation, command, breadcrumb, and PageOutline data contracts across web and native.
180
+ - Prefer bottom tabs for primary destinations and a menu/sheet for deeper navigation, notifications, and account actions.
181
+ - Keep the same typed navigation, command, breadcrumb, notification, and PageOutline data contracts across web and native.
98
182
 
99
183
  Implementation constraints:
100
184
  - Reuse the existing design-system primitives, tokens, icons, and accessibility patterns.
101
185
  - Do not hardcode app-specific routes in the shell component.
102
186
  - Do not introduce a new dependency unless the repo already uses it for dialogs, menus, icons, or navigation.
103
- - Include tests for navigation rendering, nested items, command filtering, breadcrumbs, PageOutline level handling, active section state, and mobile/native adaptation contracts.
187
+ - Include tests for navigation rendering, nested items, command filtering, breadcrumbs, notification unread badge/loading/empty/callback behavior, PageOutline level handling, active section state, and mobile/native adaptation contracts.
104
188
  - Update docs and exports so developers can import the shell from a stable public API.
105
189
 
106
190
  Deliverables:
@@ -108,17 +192,20 @@ Deliverables:
108
192
  - Web shell components.
109
193
  - Native shell components or adapters.
110
194
  - PageOutline component with three-level support.
195
+ - ShellNotifications or equivalent notification center component for web and native shell placement.
111
196
  - Usage example.
112
197
  - Focused tests and typecheck/build evidence.`;
113
198
 
114
199
  export const refactorPrompt = `You are refactoring an existing application to use the shared application shell system.
115
200
 
116
201
  Goal:
117
- Replace app-specific sidebar, topbar, breadcrumb, command palette, account menu, mobile navigation, and in-page table-of-contents code with the shared AppShell and PageOutline system.
202
+ Replace app-specific sidebar, topbar, breadcrumb, command palette, notification badge/inbox, account menu, mobile navigation, and in-page table-of-contents code with the shared AppShell, ShellNotifications, and PageOutline system.
118
203
 
119
204
  Start by auditing:
120
205
  - Current layout wrappers and route groups.
121
206
  - Sidebar, topbar, breadcrumb, command/search, auth menu, and mobile navigation implementations.
207
+ - Existing notification badges, inbox panels, toasts that represent durable in-app items, unread count queries, mark-read actions, and delivery modules.
208
+ - Imports from @contractspec/module.notifications that should migrate to @contractspec/lib.contracts-spec/notifications or @contractspec/lib.notification.
122
209
  - Any duplicated navigation arrays, route labels, icon maps, access-control checks, and active-state logic.
123
210
  - Any in-page summary/table-of-contents components that should become PageOutline data.
124
211
  - Web-only assumptions that would block Expo/React Native adaptation.
@@ -127,21 +214,24 @@ Refactor plan:
127
214
  1. Define a single typed navigation source for primary nav, grouped sidebar nav, nested children, labels, icons, badges, disabled states, and permissions.
128
215
  2. Map existing command/search behavior into grouped command actions with search text and quick actions.
129
216
  3. Map existing route metadata into breadcrumbs.
130
- 4. Convert page table-of-contents or section summary data into PageOutline items with a maximum of three levels.
131
- 5. Wrap app routes in AppShell while keeping page content components route-local.
132
- 6. Move primary mobile destinations into bottom navigation and deeper/account actions into a menu or drawer.
133
- 7. Add or preserve .native.tsx adapters when the app targets Expo.
217
+ 4. Move canonical notification contracts to @contractspec/lib.contracts-spec/notifications and reusable helpers to @contractspec/lib.notification; keep the old module shim only for compatibility imports that still need the legacy module id.
218
+ 5. Convert notification query results into ShellNotificationCenter items with unreadCount, loading, empty state, onSelect, onMarkRead, and onMarkAllRead callbacks.
219
+ 6. Convert page table-of-contents or section summary data into PageOutline items with a maximum of three levels.
220
+ 7. Wrap app routes in AppShell while keeping page content components route-local.
221
+ 8. Move primary mobile destinations into bottom navigation and deeper/account/notification actions into a menu or drawer.
222
+ 9. Add or preserve .native.tsx adapters when the app targets Expo.
134
223
 
135
224
  Preserve behavior:
136
225
  - Existing route URLs and access rules.
137
226
  - Existing keyboard shortcuts where they are public behavior.
138
227
  - Existing analytics or telemetry events on navigation and command actions.
228
+ - Existing notification delivery semantics, unread count semantics, deep links, and mark-read behavior.
139
229
  - Existing auth/logout behavior.
140
230
  - Existing responsive breakpoints unless there is a documented design-system breakpoint to adopt.
141
231
 
142
232
  Quality gates:
143
233
  - Add regression tests around current visible navigation before removing old shell code when coverage is missing.
144
- - Test active nav state, nested nav expansion, command search/action invocation, breadcrumbs, auth menu, mobile bottom navigation, and PageOutline anchor behavior.
234
+ - Test active nav state, nested nav expansion, command search/action invocation, breadcrumbs, notification unread badge/loading/empty/callback behavior, auth menu, mobile bottom navigation, and PageOutline anchor behavior.
145
235
  - Run lint, typecheck, and the app's relevant test/build command.
146
236
  - Remove dead app-specific shell components only after the shared shell path is verified.
147
237
 
@@ -150,6 +240,25 @@ Output:
150
240
  - List new shared shell integration points.
151
241
  - Include before/after route coverage and verification commands.`;
152
242
 
243
+ export const notificationGuide = [
244
+ {
245
+ title: 'Contracts stay canonical',
246
+ body: 'Use @contractspec/lib.contracts-spec/notifications for operation models, feature metadata, and contract-level compatibility.',
247
+ },
248
+ {
249
+ title: 'Runtime helpers stay reusable',
250
+ body: 'Use @contractspec/lib.notification for schema contribution, channel adapters, templates, and i18n without importing the deprecated module shim in new code.',
251
+ },
252
+ {
253
+ title: 'Apps own live state',
254
+ body: 'Fetch, subscribe, persist, mutate, and reconcile notification state in the host app or runtime layer where auth and tenancy are known.',
255
+ },
256
+ {
257
+ title: 'Shell receives view state',
258
+ body: 'Pass AppShell a ShellNotificationCenter with render-ready items, counts, loading state, and callbacks; the design system only renders affordances.',
259
+ },
260
+ ] as const;
261
+
153
262
  export const shellParts = [
154
263
  {
155
264
  title: 'Sidebar',
@@ -157,14 +266,18 @@ export const shellParts = [
157
266
  },
158
267
  {
159
268
  title: 'Topbar',
160
- body: 'Breadcrumbs stay visible while the current route changes. The command trigger can live here when the sidebar is collapsed or hidden.',
269
+ body: 'Breadcrumbs stay visible while the current route changes. Command search and notification affordances can live here when the sidebar is collapsed or hidden.',
161
270
  },
162
271
  {
163
272
  title: 'PageOutline',
164
273
  body: 'The right-side in-page navigator replaces ad hoc tables of contents. It supports three levels of section anchors and active state.',
165
274
  },
275
+ {
276
+ title: 'Notifications',
277
+ body: 'The shell renders unread badges, item lists, loading/empty states, mark-read actions, and deep-link selection from host-owned notification state.',
278
+ },
166
279
  {
167
280
  title: 'Mobile adapters',
168
- body: 'Small web and native surfaces move primary destinations to bottom navigation and reserve drawers or menus for deep navigation and account actions.',
281
+ body: 'Small web and native surfaces move primary destinations to bottom navigation and reserve drawers or menus for deep navigation, notifications, and account actions.',
169
282
  },
170
283
  ] as const;
@@ -11,6 +11,8 @@ import {
11
11
  import Link from '@contractspec/lib.ui-link';
12
12
  import { ChevronRight } from 'lucide-react';
13
13
  import {
14
+ notificationCenterExample,
15
+ notificationGuide,
14
16
  refactorPrompt,
15
17
  scratchPrompt,
16
18
  shellParts,
@@ -25,7 +27,8 @@ export function LibrariesApplicationShellPage() {
25
27
  <P className="text-lg text-muted-foreground">
26
28
  A reusable navigation system for product apps: desktop sidebar, topbar
27
29
  breadcrumbs, command search, account actions, mobile adapters, and a
28
- Notion-style <Code>PageOutline</Code> for page sections.
30
+ Notion-style <Code>PageOutline</Code> for page sections, with
31
+ prop-driven in-app notifications for web and native shells.
29
32
  </P>
30
33
  </VStack>
31
34
 
@@ -62,11 +65,37 @@ export function LibrariesApplicationShellPage() {
62
65
  />
63
66
  </VStack>
64
67
 
68
+ <VStack className="space-y-4">
69
+ <H2 className="font-bold text-2xl">Notification Center Boundary</H2>
70
+ <P className="text-muted-foreground">
71
+ Notifications are part of the shell experience, but the design system
72
+ only renders the affordance. Contracts, runtime helpers, persistence,
73
+ delivery, auth, and subscriptions stay outside the shell and feed a
74
+ render-ready <Code>ShellNotificationCenter</Code> into{' '}
75
+ <Code>AppShell</Code>.
76
+ </P>
77
+ <Box className="grid gap-4 md:grid-cols-2">
78
+ {notificationGuide.map((part) => (
79
+ <Box key={part.title} className="card-subtle p-4">
80
+ <H3 className="font-semibold">{part.title}</H3>
81
+ <P className="mt-2 text-muted-foreground text-sm leading-7">
82
+ {part.body}
83
+ </P>
84
+ </Box>
85
+ ))}
86
+ </Box>
87
+ <CodeBlock
88
+ language="tsx"
89
+ filename="notification-center-boundary.ts"
90
+ code={notificationCenterExample}
91
+ />
92
+ </VStack>
93
+
65
94
  <VStack className="space-y-4">
66
95
  <H2 className="font-bold text-2xl">AI Prompt: Build From Scratch</H2>
67
96
  <P className="text-muted-foreground">
68
- Use this prompt when the app does not already have a shell or when the
69
- design-system package needs the reusable primitive first.
97
+ Use this prompt when the app does not already have a shell, command
98
+ surface, page outline, or in-app notification center.
70
99
  </P>
71
100
  <CodeBlock
72
101
  language="markdown"
@@ -79,7 +108,8 @@ export function LibrariesApplicationShellPage() {
79
108
  <H2 className="font-bold text-2xl">AI Prompt: Refactor An App</H2>
80
109
  <P className="text-muted-foreground">
81
110
  Use this prompt when an app already has custom navigation chrome and
82
- needs to migrate without breaking route behavior.
111
+ notification UI that need to migrate without breaking route behavior,
112
+ unread counts, or delivery semantics.
83
113
  </P>
84
114
  <CodeBlock
85
115
  language="markdown"
@@ -95,7 +125,10 @@ export function LibrariesApplicationShellPage() {
95
125
  <Code>PageOutline</Code> for the in-page navigation helper. The latter
96
126
  is the product-app equivalent of a table of contents, but it is
97
127
  intentionally named for live page sections rather than static
98
- documentation.
128
+ documentation. Use <Code>ShellNotifications</Code> for the
129
+ notification affordance when it is rendered directly, or pass the same
130
+ data contract through <Code>AppShell</Code> with the{' '}
131
+ <Code>notifications</Code> prop.
99
132
  </P>
100
133
  </VStack>
101
134