@sntlr/registry-shell 1.0.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 (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -0
  3. package/dist/adapter/custom.d.ts +47 -0
  4. package/dist/adapter/custom.js +53 -0
  5. package/dist/adapter/custom.js.map +1 -0
  6. package/dist/adapter/default.d.ts +40 -0
  7. package/dist/adapter/default.js +202 -0
  8. package/dist/adapter/default.js.map +1 -0
  9. package/dist/cli/build.d.ts +1 -0
  10. package/dist/cli/build.js +31 -0
  11. package/dist/cli/build.js.map +1 -0
  12. package/dist/cli/dev.d.ts +1 -0
  13. package/dist/cli/dev.js +26 -0
  14. package/dist/cli/dev.js.map +1 -0
  15. package/dist/cli/index.d.ts +12 -0
  16. package/dist/cli/index.js +49 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/cli/init.d.ts +1 -0
  19. package/dist/cli/init.js +70 -0
  20. package/dist/cli/init.js.map +1 -0
  21. package/dist/cli/shared.d.ts +33 -0
  22. package/dist/cli/shared.js +278 -0
  23. package/dist/cli/shared.js.map +1 -0
  24. package/dist/cli/start.d.ts +1 -0
  25. package/dist/cli/start.js +24 -0
  26. package/dist/cli/start.js.map +1 -0
  27. package/dist/config-loader.d.ts +49 -0
  28. package/dist/config-loader.js +140 -0
  29. package/dist/define-config.d.ts +188 -0
  30. package/dist/define-config.js +21 -0
  31. package/dist/index.d.ts +11 -0
  32. package/dist/index.js +9 -0
  33. package/package.json +124 -0
  34. package/src/adapter/custom.ts +90 -0
  35. package/src/adapter/default.ts +241 -0
  36. package/src/cli/build.ts +38 -0
  37. package/src/cli/dev.ts +38 -0
  38. package/src/cli/index.ts +52 -0
  39. package/src/cli/init.ts +76 -0
  40. package/src/cli/shared.ts +306 -0
  41. package/src/cli/start.ts +28 -0
  42. package/src/config-loader.ts +190 -0
  43. package/src/define-config.ts +206 -0
  44. package/src/index.ts +17 -0
  45. package/src/next-app/app/[...asset]/route.ts +81 -0
  46. package/src/next-app/app/_user-global.css +6 -0
  47. package/src/next-app/app/_user-sources.css +9 -0
  48. package/src/next-app/app/a11y/[name]/route.ts +19 -0
  49. package/src/next-app/app/api/search-index/route.ts +19 -0
  50. package/src/next-app/app/components/[name]/page.tsx +61 -0
  51. package/src/next-app/app/components/layout.tsx +18 -0
  52. package/src/next-app/app/docs/[slug]/page.tsx +53 -0
  53. package/src/next-app/app/docs/layout.tsx +18 -0
  54. package/src/next-app/app/globals.css +329 -0
  55. package/src/next-app/app/layout.tsx +102 -0
  56. package/src/next-app/app/page.tsx +9 -0
  57. package/src/next-app/app/preview-snapshot/[name]/page.tsx +20 -0
  58. package/src/next-app/app/preview-snapshot/layout.tsx +17 -0
  59. package/src/next-app/app/props/[name]/route.ts +19 -0
  60. package/src/next-app/app/r/[name]/route.ts +14 -0
  61. package/src/next-app/app/tests/[name]/route.ts +19 -0
  62. package/src/next-app/components/a11y-info.tsx +287 -0
  63. package/src/next-app/components/a11y-provider.tsx +39 -0
  64. package/src/next-app/components/component-breadcrumb.tsx +55 -0
  65. package/src/next-app/components/component-icon.tsx +140 -0
  66. package/src/next-app/components/component-preview.tsx +13 -0
  67. package/src/next-app/components/component-tabs.tsx +209 -0
  68. package/src/next-app/components/docs-toc.tsx +86 -0
  69. package/src/next-app/components/global-mobile-sidebar.tsx +35 -0
  70. package/src/next-app/components/header.tsx +188 -0
  71. package/src/next-app/components/heading-anchor.tsx +52 -0
  72. package/src/next-app/components/homepage-demo.tsx +180 -0
  73. package/src/next-app/components/locale-toggle.tsx +35 -0
  74. package/src/next-app/components/localized-mdx-client.tsx +14 -0
  75. package/src/next-app/components/localized-mdx.tsx +27 -0
  76. package/src/next-app/components/mobile-sidebar.tsx +22 -0
  77. package/src/next-app/components/nav-data-provider.tsx +37 -0
  78. package/src/next-app/components/navigation-progress.tsx +62 -0
  79. package/src/next-app/components/preview-canvas.tsx +368 -0
  80. package/src/next-app/components/preview-controls.tsx +94 -0
  81. package/src/next-app/components/preview-layout.tsx +218 -0
  82. package/src/next-app/components/props-table.tsx +134 -0
  83. package/src/next-app/components/resizable-preview.tsx +101 -0
  84. package/src/next-app/components/search.tsx +177 -0
  85. package/src/next-app/components/settings-modal.tsx +98 -0
  86. package/src/next-app/components/shell-ui/accordion.tsx +70 -0
  87. package/src/next-app/components/shell-ui/backdrop.tsx +29 -0
  88. package/src/next-app/components/shell-ui/badge.tsx +55 -0
  89. package/src/next-app/components/shell-ui/breadcrumb.tsx +120 -0
  90. package/src/next-app/components/shell-ui/button.tsx +64 -0
  91. package/src/next-app/components/shell-ui/card.tsx +127 -0
  92. package/src/next-app/components/shell-ui/checkbox.tsx +33 -0
  93. package/src/next-app/components/shell-ui/dialog.tsx +171 -0
  94. package/src/next-app/components/shell-ui/empty-state.tsx +66 -0
  95. package/src/next-app/components/shell-ui/input.tsx +27 -0
  96. package/src/next-app/components/shell-ui/kbd.tsx +30 -0
  97. package/src/next-app/components/shell-ui/label.tsx +25 -0
  98. package/src/next-app/components/shell-ui/select.tsx +204 -0
  99. package/src/next-app/components/shell-ui/separator.tsx +32 -0
  100. package/src/next-app/components/shell-ui/skeleton.tsx +18 -0
  101. package/src/next-app/components/shell-ui/table.tsx +124 -0
  102. package/src/next-app/components/shell-ui/tabs.tsx +102 -0
  103. package/src/next-app/components/shell-ui/toggle.tsx +56 -0
  104. package/src/next-app/components/sidebar-layout.tsx +37 -0
  105. package/src/next-app/components/sidebar-provider.tsx +75 -0
  106. package/src/next-app/components/sidebar.tsx +222 -0
  107. package/src/next-app/components/snapshot-preview.tsx +28 -0
  108. package/src/next-app/components/test-info.tsx +155 -0
  109. package/src/next-app/components/theme-provider.tsx +16 -0
  110. package/src/next-app/components/theme-toggle.tsx +21 -0
  111. package/src/next-app/components/translated-text.tsx +8 -0
  112. package/src/next-app/fallback/homepage.tsx +112 -0
  113. package/src/next-app/fallback/previews.ts +17 -0
  114. package/src/next-app/hooks/use-active-section.ts +23 -0
  115. package/src/next-app/hooks/use-controls.ts +72 -0
  116. package/src/next-app/hooks/use-mobile.ts +19 -0
  117. package/src/next-app/lib/branding.ts +52 -0
  118. package/src/next-app/lib/components-nav.ts +8 -0
  119. package/src/next-app/lib/docs.ts +16 -0
  120. package/src/next-app/lib/github.ts +38 -0
  121. package/src/next-app/lib/i18n.tsx +630 -0
  122. package/src/next-app/lib/locales.ts +17 -0
  123. package/src/next-app/lib/preview-loader.ts +7 -0
  124. package/src/next-app/lib/registry-adapter.ts +199 -0
  125. package/src/next-app/lib/utils.ts +6 -0
  126. package/src/next-app/next-env.d.ts +6 -0
  127. package/src/next-app/next.config.ts +101 -0
  128. package/src/next-app/postcss.config.mjs +7 -0
  129. package/src/next-app/public/favicon.ico +0 -0
  130. package/src/next-app/public/favicon_dark.svg +3 -0
  131. package/src/next-app/public/favicon_light.svg +3 -0
  132. package/src/next-app/registry.config.ts +50 -0
  133. package/src/next-app/tsconfig.json +29 -0
  134. package/src/next-app/user-aliases.d.ts +17 -0
@@ -0,0 +1,199 @@
1
+ import type { ComponentType, ReactNode } from "react"
2
+
3
+ /** One entry in the registry's navigation — a UI component or a block. */
4
+ export interface ComponentMeta {
5
+ /** URL-safe slug, e.g. `"button"` or `"auth-login"`. */
6
+ name: string
7
+ /** Human-readable title, e.g. `"Button"` or `"Auth Login"`. */
8
+ label: string
9
+ /**
10
+ * `"component"` for low-level UI primitives (Button, Dialog), `"block"` for
11
+ * composed screens/patterns (Auth Login, Data Table). Shell groups these
12
+ * into separate sidebar sections.
13
+ */
14
+ kind: "component" | "block"
15
+ }
16
+
17
+ /** Doc page metadata (frontmatter + slug). Drives the docs sidebar. */
18
+ export interface DocMeta {
19
+ /** URL-safe slug, matches the `.mdx` filename without extension. */
20
+ slug: string
21
+ /** Default-locale title (typically English). */
22
+ title: string
23
+ description: string
24
+ /** Sidebar sort order. Lower = higher up. Default 999. */
25
+ order: number
26
+ /** Per-locale titles, e.g. `{ en: "Getting Started", fr: "Démarrage" }`. */
27
+ titles: Record<string, string>
28
+ }
29
+
30
+ /** Full MDX body of a doc for one locale, plus its metadata. */
31
+ export interface DocContent {
32
+ meta: Omit<DocMeta, "titles">
33
+ /** Raw MDX string — the shell renders it via `next-mdx-remote`. */
34
+ content: string
35
+ }
36
+
37
+ /**
38
+ * Renders interactive component previews on the detail pages. The registry
39
+ * owns the dynamic-import map (see `sntlr-registry/components/previews/index.ts`
40
+ * for a reference implementation) because Next.js `dynamic()` needs string
41
+ * literal paths at compile time.
42
+ */
43
+ export interface PreviewLoader {
44
+ /**
45
+ * Stable wrapper component. Use this in shell code:
46
+ * `<Preview name={compName} fallback={<EmptyState/>} />`. Avoids the
47
+ * `react-hooks/static-components` lint that fires when a component type is
48
+ * looked up inside render.
49
+ */
50
+ Preview: ComponentType<{ name: string; fallback?: ReactNode }>
51
+ /** All names for which `load()` returns a component. */
52
+ names(): string[]
53
+ /** Low-level lookup. Prefer `Preview`; exposed for edge cases. */
54
+ load(name: string): ComponentType | null
55
+ }
56
+
57
+ /** Props the shell passes to an optional custom `HomePage` component. */
58
+ export interface HomePageProps {
59
+ /** Slug of the first doc (lowest `order`), so the homepage can link to it. */
60
+ firstDocSlug?: string
61
+ }
62
+
63
+ /**
64
+ * Branding displayed in the shell chrome (header, favicon, HTML title) and on
65
+ * the built-in Getting Started landing. Pure data — safe to import from client
66
+ * components.
67
+ */
68
+ export interface GithubConfig {
69
+ owner: string
70
+ repo: string
71
+ label?: string
72
+ showStars?: boolean
73
+ }
74
+
75
+ export interface BrandingConfig {
76
+ /** Full product name, e.g. `"Scintillar UI"`. Used in HTML title. */
77
+ siteName: string
78
+ /** Short breadcrumb label, e.g. `"UI"`. Shown next to the logo. */
79
+ shortName: string
80
+ /** Canonical URL of the deployed registry, e.g. `"https://ui.sntlr.app"`. */
81
+ siteUrl?: string
82
+ /** SEO description. Used in `<meta name="description">`, OG, Twitter. */
83
+ description?: string
84
+ /** OG image URL (1200×630 recommended). */
85
+ ogImage?: string
86
+ /** Twitter handle without the `@`. */
87
+ twitterHandle?: string
88
+ /** Optional GitHub link button in the header. */
89
+ github?: GithubConfig
90
+ /** Accessible alt text for the logo image. */
91
+ logoAlt?: string
92
+ /** Public path to the dark-theme SVG favicon. */
93
+ faviconDark?: string
94
+ /** Public path to the light-theme SVG favicon. */
95
+ faviconLight?: string
96
+ /** Public path to a fallback `.ico` favicon. */
97
+ faviconIco?: string
98
+ }
99
+
100
+ /**
101
+ * Client-safe slice of a registry — bundles everything the shell renders in
102
+ * the browser (without pulling in the server-only adapter that uses `fs`).
103
+ * Wire this in `ui-registry/registry.client.ts`.
104
+ *
105
+ * A registry package typically exposes this via a `client.ts` module that
106
+ * re-exports `branding`, `previewLoader`, a default `HomePage`, and optional
107
+ * `extraTranslations`. See `sntlr-registry/client.ts` for a reference.
108
+ */
109
+ export interface RegistryClient {
110
+ branding: BrandingConfig
111
+ previewLoader: PreviewLoader
112
+ /**
113
+ * Optional custom homepage component. When set, the shell's `/` route
114
+ * renders this instead of the built-in Getting Started / generic index.
115
+ * When `undefined`/`null`, the shell uses `GenericIndexPage` (a plain
116
+ * component/block listing).
117
+ */
118
+ HomePage?: ComponentType<HomePageProps> | null
119
+ /**
120
+ * Locale → key → value dictionaries merged into the shell's i18n table.
121
+ * Use this to ship marketing/homepage copy; the shell owns the generic UI
122
+ * keys (sidebar, header, search, a11y, etc.). Invariant: if `HomePage` is
123
+ * set, this must include every key the homepage references.
124
+ */
125
+ extraTranslations?: Record<string, Record<string, string>>
126
+ }
127
+
128
+ /**
129
+ * The complete server-side contract the shell consumes. A registry package
130
+ * implements this (typically in `adapter.ts`) and the shell imports the
131
+ * default export via `ui-registry/registry.config.ts`.
132
+ *
133
+ * All filesystem reads, registry-JSON serving, and MDX parsing live here —
134
+ * the shell never touches the registry's files directly. This is what makes
135
+ * the shell swappable across arbitrary registries.
136
+ */
137
+ export interface RegistryAdapter {
138
+ /**
139
+ * Full list of navigable items (components + blocks). Typically scans the
140
+ * registry's `components/ui` and `registry/STYLE/blocks` folders at build
141
+ * time, where STYLE is e.g. "new-york" or "default".
142
+ */
143
+ getAllComponents(): ComponentMeta[]
144
+
145
+ /** Full list of MDX docs with their frontmatter. */
146
+ getAllDocs(): DocMeta[]
147
+
148
+ /**
149
+ * Return doc content for one slug, preferring the requested locale. Fall
150
+ * back to the default locale when the localized file doesn't exist. Return
151
+ * `null` when the slug is unknown so the shell can `notFound()`.
152
+ */
153
+ getDocBySlug(slug: string, locale?: string): DocContent | null
154
+
155
+ /** Return `{ [locale]: rawMdx }` for all locales a doc is translated into. */
156
+ getDocAllLocales(slug: string): Record<string, string>
157
+
158
+ /**
159
+ * Raw source of a component/block file for the "Code" tab. Should check
160
+ * both the component directory and the primitives/blocks directories.
161
+ * Return `null` if unknown.
162
+ */
163
+ getComponentSource(name: string): string | null
164
+
165
+ /**
166
+ * Return the shadcn-format JSON for a registry item. Usually reads the
167
+ * pre-built `public/r/{name}.json` produced by `shadcn build`. Accepts the
168
+ * slug with or without a trailing `.json`.
169
+ */
170
+ getRegistryItem(name: string): Promise<unknown | null>
171
+
172
+ /**
173
+ * Return the a11y metadata JSON for a component. Powers the Accessibility
174
+ * tab. Convention: `public/a11y/{name}.json` generated from
175
+ * `content/a11y/{name}.yaml` by the registry's `generate:a11y` script.
176
+ */
177
+ getA11yData?(name: string): Promise<unknown | null>
178
+
179
+ /**
180
+ * Return the test summary JSON for a component. Powers the Tests tab.
181
+ * Convention: `public/tests/{name}.json` generated by `generate:tests`.
182
+ */
183
+ getTestData?(name: string): Promise<unknown | null>
184
+
185
+ /**
186
+ * Return the prop-documentation JSON for a component. Powers the props
187
+ * table inside the Docs tab. Convention: `public/props/{name}.json`
188
+ * generated by `generate:props`.
189
+ */
190
+ getPropsData?(name: string): Promise<unknown | null>
191
+
192
+ previewLoader: PreviewLoader
193
+ branding: BrandingConfig
194
+
195
+ /** See `RegistryClient.HomePage`. */
196
+ homePage?: ComponentType<HomePageProps> | null
197
+ /** See `RegistryClient.extraTranslations`. */
198
+ extraTranslations?: Record<string, Record<string, string>>
199
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,101 @@
1
+ import type { NextConfig } from "next"
2
+ import fs from "node:fs"
3
+ import path from "node:path"
4
+ import { fileURLToPath } from "node:url"
5
+
6
+ const HERE = path.dirname(fileURLToPath(import.meta.url))
7
+ const USER_ROOT = process.env.USER_REGISTRY_ROOT
8
+
9
+ /**
10
+ * Resolve a virtual `@user/*` alias to the user's file when it exists, else
11
+ * to a shell-bundled fallback under `fallback/`. Called once at Next boot.
12
+ */
13
+ function toPosix(p: string): string {
14
+ // Turbopack on Windows rejects backslash absolute paths.
15
+ return p.replace(/\\/g, "/")
16
+ }
17
+
18
+ /** Common ancestor directory of two absolute paths. */
19
+ function findCommonRoot(a: string, b: string): string {
20
+ const pa = path.resolve(a).split(path.sep)
21
+ const pb = path.resolve(b).split(path.sep)
22
+ const common: string[] = []
23
+ for (let i = 0; i < Math.min(pa.length, pb.length); i++) {
24
+ if (pa[i] !== pb[i]) break
25
+ common.push(pa[i])
26
+ }
27
+ return common.join(path.sep) || path.sep
28
+ }
29
+
30
+ function resolveUserModule(relativePath: string, fallback: string): string {
31
+ if (USER_ROOT) {
32
+ // Try a few extensions since users may write .ts or .tsx.
33
+ const candidates = [relativePath, `${relativePath}.ts`, `${relativePath}.tsx`]
34
+ for (const c of candidates) {
35
+ const abs = path.isAbsolute(c) ? c : path.join(USER_ROOT, c)
36
+ if (fs.existsSync(abs) && fs.statSync(abs).isFile()) return toPosix(abs)
37
+ const indexTs = path.join(abs, "index.ts")
38
+ if (fs.existsSync(indexTs)) return toPosix(indexTs)
39
+ const indexTsx = path.join(abs, "index.tsx")
40
+ if (fs.existsSync(indexTsx)) return toPosix(indexTsx)
41
+ }
42
+ }
43
+ return toPosix(path.join(HERE, fallback))
44
+ }
45
+
46
+ const USER_PREVIEWS = resolveUserModule("components/previews", "fallback/previews.ts")
47
+ const USER_HOMEPAGE = process.env.USER_HOMEPAGE_PATH
48
+ ? resolveUserModule(process.env.USER_HOMEPAGE_PATH, "fallback/homepage.tsx")
49
+ : toPosix(path.join(HERE, "fallback/homepage.tsx"))
50
+
51
+ // The CLI's `build` / `start` commands set USER_DIST_DIR to
52
+ // `<user-project>/.next` so Next writes its output (and reads it back on
53
+ // start) at the user's project root, not inside node_modules. Absolute
54
+ // path — Next accepts that for `distDir`.
55
+ const USER_DIST_DIR = process.env.USER_DIST_DIR
56
+
57
+ const nextConfig: NextConfig = {
58
+ output: process.env.BUILD_STANDALONE === "true" ? "standalone" : undefined,
59
+ ...(USER_DIST_DIR ? { distDir: toPosix(USER_DIST_DIR) } : {}),
60
+
61
+ // When installed as an external package (link:../registry-shell, npm, etc.),
62
+ // the shell's TSX lives under the user's node_modules and Next won't
63
+ // transpile it by default. The registry can list additional packages via
64
+ // `transpilePackages` in its config (CLI forwards as USER_TRANSPILE_PACKAGES).
65
+ transpilePackages: [
66
+ "@sntlr/registry-shell",
67
+ ...(process.env.USER_TRANSPILE_PACKAGES
68
+ ? process.env.USER_TRANSPILE_PACKAGES.split(",").filter(Boolean)
69
+ : []),
70
+ ],
71
+
72
+ // Turbopack root: walk up until we find a dir that contains both the shell
73
+ // package and the user's project. For a pnpm workspace setup that's the
74
+ // workspace root. Falls back to process.cwd() (which is the user's project
75
+ // when run via `registry-shell dev`).
76
+ turbopack: {
77
+ root: process.env.TURBOPACK_ROOT
78
+ ? toPosix(process.env.TURBOPACK_ROOT)
79
+ : toPosix(findCommonRoot(HERE, USER_ROOT ?? process.cwd())),
80
+ resolveAlias: {
81
+ "@user/previews": USER_PREVIEWS,
82
+ "@user/homepage": USER_HOMEPAGE,
83
+ },
84
+ },
85
+
86
+ webpack: (config) => {
87
+ config.resolve = config.resolve ?? {}
88
+ config.resolve.alias = {
89
+ ...(config.resolve.alias ?? {}),
90
+ "@user/previews": USER_PREVIEWS,
91
+ "@user/homepage": USER_HOMEPAGE,
92
+ // Shell's internal alias — its own files.
93
+ "@shell": toPosix(HERE),
94
+ // shadcn convention: user files use `@/` for their own project root.
95
+ ...(USER_ROOT ? { "@": toPosix(USER_ROOT) } : {}),
96
+ }
97
+ return config
98
+ },
99
+ }
100
+
101
+ export default nextConfig
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ }
6
+
7
+ export default config
Binary file
@@ -0,0 +1,3 @@
1
+ <svg width="128" height="82" viewBox="0 0 128 82" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M95.7812 3.18066C97.3554 1.60657 99.9073 1.60659 101.481 3.18066C103.056 4.7548 103.056 7.30671 101.481 8.88086L79.3223 31.04C73.7739 36.5884 73.774 45.5844 79.3223 51.1328L100.905 72.7158C102.508 74.3181 102.508 76.9163 100.905 78.5186C99.3031 80.1203 96.7057 80.1204 95.1035 78.5186L73.5205 56.9346C67.9722 51.3864 58.9761 51.3864 53.4277 56.9346L32.3223 78.041C30.7481 79.6152 28.1952 79.6152 26.6211 78.041C25.047 76.4669 25.047 73.914 26.6211 72.3398L47.7275 51.2344C53.2757 45.686 53.2759 36.6899 47.7275 31.1416L26.041 9.45605C24.4388 7.85382 24.4388 5.25556 26.041 3.65332C27.6433 2.0512 30.2415 2.05112 31.8438 3.65332L53.5293 25.3398C59.0777 30.8882 68.0737 30.8882 73.6221 25.3398L95.7812 3.18066ZM61.0986 69.4502C62.7013 67.8476 65.2988 67.8476 66.9014 69.4502C68.504 71.0528 68.504 73.6513 66.9014 75.2539C65.2989 76.856 62.7012 76.856 61.0986 75.2539C59.496 73.6513 59.496 71.0528 61.0986 69.4502ZM4.98926 33.3418C8.97557 29.3555 15.4395 29.3555 19.4258 33.3418C23.4117 37.3281 23.4119 43.7911 19.4258 47.7773C15.4395 51.7637 8.97557 51.7637 4.98926 47.7773C1.00321 43.7912 1.00342 37.3281 4.98926 33.3418ZM108.574 33.3418C112.561 29.3555 119.024 29.3555 123.011 33.3418C126.997 37.3281 126.997 43.7912 123.011 47.7773C119.024 51.7637 112.561 51.7637 108.574 47.7773C104.588 43.7911 104.588 37.3281 108.574 33.3418Z" stroke="#005E3E" stroke-width="4"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="128" height="82" viewBox="0 0 128 82" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M95.7812 3.18066C97.3554 1.60657 99.9073 1.60659 101.481 3.18066C103.056 4.7548 103.056 7.30671 101.481 8.88086L79.3223 31.04C73.7739 36.5884 73.774 45.5844 79.3223 51.1328L100.905 72.7158C102.508 74.3181 102.508 76.9163 100.905 78.5186C99.3031 80.1203 96.7057 80.1204 95.1035 78.5186L73.5205 56.9346C67.9722 51.3864 58.9761 51.3864 53.4277 56.9346L32.3223 78.041C30.7481 79.6152 28.1952 79.6152 26.6211 78.041C25.047 76.4669 25.047 73.914 26.6211 72.3398L47.7275 51.2344C53.2757 45.686 53.2759 36.6899 47.7275 31.1416L26.041 9.45605C24.4388 7.85382 24.4388 5.25556 26.041 3.65332C27.6433 2.0512 30.2415 2.05112 31.8438 3.65332L53.5293 25.3398C59.0777 30.8882 68.0737 30.8882 73.6221 25.3398L95.7812 3.18066ZM61.0986 69.4502C62.7013 67.8476 65.2988 67.8476 66.9014 69.4502C68.504 71.0528 68.504 73.6513 66.9014 75.2539C65.2989 76.856 62.7012 76.856 61.0986 75.2539C59.496 73.6513 59.496 71.0528 61.0986 69.4502ZM4.98926 33.3418C8.97557 29.3555 15.4395 29.3555 19.4258 33.3418C23.4117 37.3281 23.4119 43.7911 19.4258 47.7773C15.4395 51.7637 8.97557 51.7637 4.98926 47.7773C1.00321 43.7912 1.00342 37.3281 4.98926 33.3418ZM108.574 33.3418C112.561 29.3555 119.024 29.3555 123.011 33.3418C126.997 37.3281 126.997 43.7912 123.011 47.7773C119.024 51.7637 112.561 51.7637 108.574 47.7773C104.588 43.7911 104.588 37.3281 108.574 33.3418Z" stroke="#5CD6AD" stroke-width="4"/>
3
+ </svg>
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Server-side registry adapter. Not user-editable anymore — the shell reads
3
+ * the user's `registry-shell.config.ts` via env vars set by the CLI and
4
+ * instantiates the default convention-based adapter (or a user-supplied
5
+ * custom one).
6
+ *
7
+ * Loaded once at Next.js module init.
8
+ */
9
+ import "server-only"
10
+ import type { RegistryAdapter } from "@shell/lib/registry-adapter"
11
+ import { loadResolvedConfig } from "../config-loader"
12
+ import { createDefaultAdapter } from "../adapter/default"
13
+ import { loadCustomAdapterOverrides } from "../adapter/custom"
14
+
15
+ function buildAdapter(): RegistryAdapter | null {
16
+ const resolved = loadResolvedConfig()
17
+ if (!resolved) return null
18
+
19
+ const base = createDefaultAdapter(resolved)
20
+ // Shallow-merged on top of `base` so a custom adapter can override one
21
+ // method (e.g. getAllComponents from a DB) and keep the defaults for the
22
+ // rest. Loaded via jiti — the adapter file can be plain TS.
23
+ const overrides = loadCustomAdapterOverrides(resolved) as Partial<RegistryAdapter>
24
+
25
+ return {
26
+ getAllComponents: overrides.getAllComponents ?? base.getAllComponents,
27
+ getAllDocs: overrides.getAllDocs ?? base.getAllDocs,
28
+ getDocBySlug: overrides.getDocBySlug ?? base.getDocBySlug,
29
+ getDocAllLocales: overrides.getDocAllLocales ?? base.getDocAllLocales,
30
+ getComponentSource: overrides.getComponentSource ?? base.getComponentSource,
31
+ getRegistryItem: overrides.getRegistryItem ?? base.getRegistryItem,
32
+ getA11yData: overrides.getA11yData ?? base.getA11yData,
33
+ getTestData: overrides.getTestData ?? base.getTestData,
34
+ getPropsData: overrides.getPropsData ?? base.getPropsData,
35
+ previewLoader: UNUSED_SERVER_SIDE_PREVIEW_LOADER,
36
+ branding: base.branding,
37
+ extraTranslations: overrides.extraTranslations ?? base.extraTranslations,
38
+ }
39
+ }
40
+
41
+ // The adapter's `previewLoader` field is never read on the server — previews
42
+ // are imported directly from the `@user/previews` alias in client code (see
43
+ // lib/preview-loader.ts). This placeholder satisfies the interface.
44
+ const UNUSED_SERVER_SIDE_PREVIEW_LOADER: RegistryAdapter["previewLoader"] = {
45
+ Preview: () => null,
46
+ load: () => null,
47
+ names: () => [],
48
+ }
49
+
50
+ export const registry: RegistryAdapter | null = buildAdapter()
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "incremental": true,
10
+ "module": "esnext",
11
+ "esModuleInterop": true,
12
+ "moduleResolution": "bundler",
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "jsx": "preserve",
16
+ "plugins": [{ "name": "next" }],
17
+ "paths": {
18
+ "@shell/*": ["./*"]
19
+ }
20
+ },
21
+ "include": [
22
+ "next-env.d.ts",
23
+ "user-aliases.d.ts",
24
+ ".next/types/**/*.ts",
25
+ "**/*.ts",
26
+ "**/*.tsx"
27
+ ],
28
+ "exclude": ["node_modules"]
29
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Virtual modules resolved by next.config.ts based on `USER_REGISTRY_ROOT`.
3
+ * At build time they point at the user's files; if the user has none, they
4
+ * fall back to shell-bundled stubs under `fallback/`.
5
+ */
6
+
7
+ declare module "@user/previews" {
8
+ import type { PreviewLoader } from "@shell/lib/registry-adapter"
9
+ export const previewLoader: PreviewLoader
10
+ }
11
+
12
+ declare module "@user/homepage" {
13
+ import type { ComponentType } from "react"
14
+ import type { HomePageProps } from "@shell/lib/registry-adapter"
15
+ const HomePage: ComponentType<HomePageProps>
16
+ export default HomePage
17
+ }