@uniformdev/uniform-mcp 20.14.2-alpha.69 → 20.20.3

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.
package/dist/index.mjs CHANGED
@@ -61438,8 +61438,7 @@ var ChipContainer = css`
61438
61438
  }
61439
61439
 
61440
61440
  &:hover {
61441
- [role='presentation'],
61442
- [role='separator'] {
61441
+ [role='presentation'] {
61443
61442
  transition: opacity var(--duration-fast) var(--timing-ease-out);
61444
61443
  opacity: var(--opacity-100);
61445
61444
  }
@@ -61451,8 +61450,7 @@ var ChipContainer = css`
61451
61450
  }
61452
61451
 
61453
61452
  :where([aria-disabled='true'], :disabled):hover {
61454
- [role='presentation'],
61455
- [role='separator'] {
61453
+ [role='presentation'] {
61456
61454
  opacity: var(--opacity-50);
61457
61455
  cursor: not-allowed;
61458
61456
  }
@@ -61469,12 +61467,6 @@ var ChipIcon = css`
61469
61467
  display: flex;
61470
61468
  opacity: var(--opacity-50);
61471
61469
  `;
61472
- var ChipSeparator = css`
61473
- display: flex;
61474
- border-right: 1px solid var(--white);
61475
- opacity: var(--opacity-50);
61476
- margin-left: -1px;
61477
- `;
61478
61470
  var ChipSmall = css`
61479
61471
  font-size: var(--fs-sm);
61480
61472
  padding-inline: var(--spacing-sm);
@@ -66515,7 +66507,7 @@ async function applyCompositionPatches(existingComposition, deletedComponentsInS
66515
66507
  type: parameterEdit.update.parameterType
66516
66508
  };
66517
66509
  const property = properties[parameterEdit.update.parameterId];
66518
- const newValue = parameterEdit.propertyDefinition.type === "richText" ? convertMarkdownToLexical(parameterEdit.result.newValue) : parameterEdit.result.treatNewValueAsJson ? JSON.parse(parameterEdit.result.newValue) : parameterEdit.result.newValue;
66510
+ const newValue = parameterEdit.propertyDefinition.type === "richText" ? convertMarkdownToLexical(parameterEdit.result.newValue) : parameterEdit.propertyDefinition.type === "number" ? Number(parameterEdit.result.newValue) : parameterEdit.result.treatNewValueAsJson ? JSON.parse(parameterEdit.result.newValue) : parameterEdit.result.newValue;
66519
66511
  if (parameterEdit.update.locale) {
66520
66512
  property.locales ??= {};
66521
66513
  property.locales[parameterEdit.update.locale] = newValue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/uniform-mcp",
3
- "version": "20.14.2-alpha.69+5c5fa31b75",
3
+ "version": "20.20.3",
4
4
  "description": "Uniform MCP Server",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "bin": {
@@ -28,21 +28,22 @@
28
28
  "@lexical/rich-text": "0.25.0",
29
29
  "@lexical/table": "0.25.0",
30
30
  "@modelcontextprotocol/sdk": "^1.12.0",
31
- "@uniformdev/canvas": "20.14.2-alpha.69+5c5fa31b75",
31
+ "@uniformdev/canvas": "20.20.3",
32
32
  "fast-json-patch": "^3.1.1",
33
33
  "immer": "10.1.1",
34
34
  "lexical": "0.25.0",
35
35
  "zod": "3.23.8"
36
36
  },
37
37
  "files": [
38
- "/dist"
38
+ "/dist",
39
+ "/references/*.mdc"
39
40
  ],
40
41
  "publishConfig": {
41
42
  "access": "public"
42
43
  },
43
44
  "devDependencies": {
44
- "@uniformdev/design-system": "^20.14.2-alpha.69+5c5fa31b75",
45
+ "@uniformdev/design-system": "^20.20.3",
45
46
  "vitest": "^3.1.4"
46
47
  },
47
- "gitHead": "5c5fa31b757bcb9cbfe0ce6934f6ee743319f8cb"
48
+ "gitHead": "3e58ece2c26439f3ee48d2ff445898a3be59b349"
48
49
  }
@@ -0,0 +1,314 @@
1
+ ---
2
+ description: Uniform React Next Page Router Developer Reference - details how to use Uniform with React.js with Next Page Router
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+
7
+ [uniform.mdc](mdc:.cursor/rules/uniform.mdc) describes general Uniform principles and practices.
8
+ [uniform-sdk.mdc](mdc:.cursor/rules/uniform-sdk.mdc) describes framework-agnostic developer principles.
9
+ [uniform-context-sdk.mdc](mdc:references/uniform-context-sdk.mdc) describes personalization and a/b testing developer practices.
10
+
11
+ ### Required npm packages
12
+
13
+ The following npm packages must be installed to wire Uniform CMS to Next Page Router:
14
+
15
+ @uniformdev/canvas
16
+ @uniformdev/canvas-react
17
+ @uniformdev/canvas-next
18
+ @uniformdev/context-react
19
+
20
+ ### Fetching and rendering the composition
21
+
22
+ In your dynamic catch-all route file (`pages/[[...path]].{tsx|jsx}`), it is necessary to fetch the Uniform composition instance for the current route. This is done for server-side rendering using the `withUniformGetServerSideProps` function:
23
+
24
+ ```tsx
25
+ import type { UniformCompositionNextPage } from "@uniformdev/canvas-next";
26
+ import { withUniformGetServerSideProps } from "@uniformdev/canvas-next/route";
27
+ import { UniformComposition } from "@uniformdev/canvas-react";
28
+
29
+ // fetch the composition using SSR
30
+ export const getServerSideProps = withUniformGetServerSideProps();
31
+
32
+ // the function provides the composition to the route component as the `data` prop
33
+ // the UniformCompositionNextPage type provides typings to make sure that is clear
34
+ const page: UniformCompositionNextPage = ({ data }) => {
35
+ // the UniformComposition component takes over rendering the components on the composition data
36
+ return <UniformComposition data={data} />;
37
+ };
38
+
39
+ export { page as default };
40
+ ```
41
+
42
+ ### Rendering Uniform Components using React Components
43
+
44
+ > IMPORTANT: before generating Uniform component code, always fetch available component definitions from Uniform to be aware of the schema.
45
+
46
+ The `UniformComposition` component needs to know how to map a Uniform Component instance's `type` to a React component that implements the UI for that component. This is done using the Component Registry. To use the component registry, create a component and register it:
47
+
48
+ `components/Hero.tsx`:
49
+
50
+ ```tsx
51
+ import { registerUniformComponent } from "@uniformdev/canvas-react";
52
+
53
+ function Hero() {
54
+ return <div>Hero Component Content</div>;
55
+ }
56
+
57
+ registerUniformComponent({
58
+ type: "hero",
59
+ component: Hero,
60
+ });
61
+ ```
62
+ Conventionally Uniform components (like Hero.tsx above) are imported to a barrel file in `components/uniformComponents.ts` (e.g. `import 'componentFileName';`), and that barrel file is imported into `_app.tsx` (e.g. `import '../components/uniformComponents';`) to ensure the registrations are processed.
63
+
64
+ #### Mapping Uniform Components to React Components
65
+
66
+ React components that receive Uniform Component data are passed props that correspond to the shape of the component definition they render. The `ComponentProps` type can be used to make the mapping explicit:
67
+
68
+ ```tsx
69
+ import {
70
+ AssetParamValue,
71
+ LinkParamValue,
72
+ RichTextParamValue,
73
+ } from "@uniformdev/canvas";
74
+
75
+ type HeroProps = ComponentProps<{
76
+ textParameter?: string;
77
+ richTextParameter?: RichTextParamValue;
78
+ linkParameter?: LinkParamValue;
79
+ assetParameter?: AssetParamValue;
80
+ // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
81
+ }>;
82
+
83
+ function Hero(props: HeroProps) {
84
+ return <div>{props.textParameter}</div>;
85
+ }
86
+ ```
87
+
88
+ #### Rendering child slots
89
+
90
+ If a Uniform Component definition has slots defined, the components in those slots can be rendered using the `UniformSlot` component.
91
+
92
+ ```tsx
93
+ import { UniformSlot } from "@uniformdev/canvas-react";
94
+
95
+ function Hero() {
96
+ return (
97
+ <div>
98
+ <div>
99
+ <UniformSlot name="start" />
100
+ </div>
101
+ <div>
102
+ <UniformSlot name="end" />
103
+ </div>
104
+ </div>
105
+ );
106
+ }
107
+ ```
108
+
109
+ #### Rendering parameter/field values
110
+
111
+ ##### Text parameters/fields
112
+
113
+ When rendering a `text` type parameter, always use the `UniformText` component to render the value. This will enable authors to edit the value within the Uniform preview directly. Text parameters that do not have a visible component, such as alt text, should be rendered as their raw text value:
114
+
115
+ ```tsx
116
+ import { UniformText } from "@uniformdev/canvas-react";
117
+
118
+ function Hero() {
119
+ return (
120
+ <div>
121
+ {/* always specify placeholder text that an author will see in the visual editor when the value is empty */}
122
+ <UniformText parameterId="textParameter" placeholder="Enter text" />
123
+ {/* optionally you can specify a className or wrapping tag, as well as placeholder text that an author will see in the visual editor when the value is empty */}
124
+ <UniformText parameterId="textParameter" as="h1" className="excellent" placeholder="Enter text" />
125
+ </div>
126
+ );
127
+ }
128
+ ```
129
+
130
+ ##### Rich text parameters/fields
131
+
132
+ For richText parameters, always use the `UniformRichText` component to automatically render the rich text (stored as Lexical JSON) to HTML:
133
+
134
+ ```tsx
135
+ import { UniformRichText } from "@uniformdev/canvas-react";
136
+
137
+ function Hero() {
138
+ return (
139
+ <div>
140
+ <UniformRichText parameterId="richTextParameter" placeholder="Prompt for author when value is empty" />
141
+ </div>
142
+ );
143
+ }
144
+ ```
145
+
146
+ ##### Asset parameters/fields
147
+
148
+ When rendering asset parameters, use the `flattenValues` helper to simplify value access:
149
+
150
+ ```tsx
151
+ import { AssetParamValue, flattenValues } from "@uniformdev/canvas";
152
+
153
+ interface MyComponentProps {
154
+ multipleImagesAssetParam: AssetParamValue;
155
+ singleImageAssetParam: AssetParamValue;
156
+ }
157
+
158
+ function MyComponent({
159
+ multipleImagesAssetParam,
160
+ singleImageAssetParam,
161
+ }: MyComponentProps) {
162
+ // when multiple assets are allowed, flatten to an array
163
+ const images = flattenValues(multipleImagesAssetParam);
164
+ // when only one asset is allowed, flatten to a single object
165
+ const image = flattenValues(singleImageAssetParam, { toSingle: true });
166
+
167
+ return (
168
+ <>
169
+ {images?.map((img, index) => (
170
+ <img key={index} src={img?.url} width={img?.width} height={img?.height} />
171
+ ))}
172
+ <img src={image?.url} width={image?.width} height={image?.height} />
173
+ </>
174
+ );
175
+ }
176
+ ```
177
+
178
+ ### Configuring Contextual Editing Live Preview
179
+
180
+ To enable contextual editing and live preview to operate within the Uniform application, we need to register a _preview handler_ and _playground page_. The preview handler is an API endpoint that Uniform invokes when preview starts. It is responsible for mapping the composition ID under preview to a redirect to the correct frontend route to display that composition. The default handler does this using project map hierarchy.
181
+
182
+ `pages/api/preview.ts`:
183
+
184
+ ```tsx
185
+ import { createPreviewHandler } from "@uniformdev/canvas-next";
186
+
187
+ const handler = createPreviewHandler({
188
+ // this is set in .env to an arbitrary value
189
+ secret: () => process.env.UNIFORM_PREVIEW_SECRET,
190
+ // optionally configure the playground route to enable previewing patterns
191
+ playgroundPath: "/playground",
192
+ });
193
+
194
+ export default handler;
195
+ ```
196
+
197
+ The preview playground is a special route used to preview Uniform Patterns (reusable chunks of a page). The playground route includes the global page shell of the application:
198
+
199
+ `pages/playground.tsx`:
200
+
201
+ ```tsx
202
+ import { UniformPlayground } from "@uniformdev/canvas-react";
203
+
204
+ export default function Playground() {
205
+ // wrap UniformPlayground in your page shell/styles to wrap the pattern previews with
206
+ return <UniformPlayground behaviorTracking="onLoad" />;
207
+ }
208
+ ```
209
+
210
+ ## Configuring Personalization and A/B Testing (Uniform Context)
211
+
212
+ ### Required Context Packages
213
+
214
+ The following npm packages must be installed to enable Uniform Context on Next Page Router:
215
+
216
+ @uniformdev/context
217
+ @uniformdev/context-next
218
+ @uniformdev/context-react
219
+ @uniformdev/cli
220
+
221
+ ### Pulling the Uniform Context Manifest
222
+
223
+ Uniform Context relies on a static _manifest_ that defines user classification criteria and active test names. This manifest is downloaded using an API endpoint to a local file that is built into the application. The following package.json script can be used to invoke the manifest download:
224
+
225
+ ```json
226
+ "uniform:pull:manifest": "uniform context manifest download --output ./src/uniform/contextManifest.json"
227
+ ```
228
+ The "dev" and "build" npm scripts should run "uniform:pull:manifest" before beginning their regular tasks.
229
+
230
+ ### Enable Uniform Context SDK
231
+
232
+ In order to initialize Uniform Context, we need to configure it and provide the manifest to it:
233
+
234
+ `src/uniform/createUniformContext.ts`:
235
+
236
+ ```tsx
237
+ import {
238
+ Context,
239
+ ManifestV2,
240
+ ContextPlugin,
241
+ enableDebugConsoleLogDrain,
242
+ enableContextDevTools
243
+ } from "@uniformdev/context";
244
+ import { NextCookieTransitionDataStore } from "@uniformdev/context-next";
245
+ import { NextPageContext } from "next";
246
+ import manifest from "./contextManifest.json";
247
+
248
+ export function createUniformContext(
249
+ serverContext?: NextPageContext
250
+ ): Context {
251
+ const plugins: ContextPlugin[] = [
252
+ // optional, but smart defaults to help with debugging setup
253
+ enableContextDevTools(),
254
+ enableDebugConsoleLogDrain("debug"),
255
+ ];
256
+
257
+ const context = new Context({
258
+ // disables needing visitor consent before storing data (for testing)
259
+ defaultConsent: true,
260
+ manifest: manifest as ManifestV2,
261
+ transitionStore: new NextCookieTransitionDataStore({
262
+ serverContext,
263
+ }),
264
+ plugins,
265
+ });
266
+
267
+ return context;
268
+ }
269
+ ```
270
+
271
+ The context instance must then be provided to the `_app.tsx` so Uniform knows about it when rendering:
272
+
273
+ `pages/_app.tsx`:
274
+ ```tsx
275
+ import { UniformContext } from "@uniformdev/context-react";
276
+ import { UniformAppProps } from "@uniformdev/context-next";
277
+ import { createUniformContext } from "../uniform/createUniformContext";
278
+
279
+ const clientContext = createUniformContext();
280
+
281
+ function MyApp({
282
+ Component,
283
+ pageProps,
284
+ serverUniformContext,
285
+ }: UniformAppProps) {
286
+ return (
287
+ <UniformContext
288
+ context={serverUniformContext ?? clientContext}
289
+ outputType={"standard"}
290
+ >
291
+ <Component {...pageProps} />
292
+ </UniformContext>
293
+ );
294
+ }
295
+
296
+ export default MyApp;
297
+ ```
298
+
299
+ We must also configure the server-side Uniform Context instance when using server-side rendering:
300
+
301
+ `pages/_document.tsx`:
302
+ ```tsx
303
+ import { enableNextSsr } from "@uniformdev/context-next";
304
+ import { createUniformContext } from "../uniform/uniformContext";
305
+
306
+ // required to enable SSR personalization
307
+ static async getInitialProps(
308
+ ctx: DocumentContext
309
+ ): Promise<DocumentInitialProps> {
310
+ const serverTracker = createUniformContext(ctx);
311
+ enableNextSsr(ctx, serverTracker);
312
+ return await Document.getInitialProps(ctx);
313
+ }
314
+ ```
@@ -0,0 +1,263 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+ # Uniform React Next App Router Developer Reference
7
+
8
+ This document details how to use Uniform with React.js with Next App Router.
9
+
10
+ @uniform.mdc describes general Uniform principles and practices.
11
+ @uniform-sdk.mdc describes framework-agnostic developer principles.
12
+
13
+ ### Required npm packages
14
+
15
+ The following npm packages must be installed to wire Uniform to Next App Router:
16
+
17
+ @uniformdev/canvas-next-rsc
18
+ @uniformdev/canvas
19
+
20
+ ### Fetching and rendering the composition
21
+
22
+ In your dynamic route file (`app/[[...path]]/page.{tsx|jsx}`), it is necessary to fetch the Uniform composition instance for the current route.
23
+
24
+ ```tsx
25
+ import {
26
+ UniformComposition,
27
+ PageParameters,
28
+ retrieveRoute,
29
+ } from "@uniformdev/canvas-next-rsc";
30
+ import { resolveComponent } from "@/uniform/resolve";
31
+
32
+ export default async function Page(props: PageParameters) {
33
+ const route = await retrieveRoute(props);
34
+ return (
35
+ <>
36
+ <UniformComposition
37
+ {...props}
38
+ route={route}
39
+ resolveComponent={resolveComponent}
40
+ mode="server"
41
+ />
42
+ </>
43
+ );
44
+ }
45
+ ```
46
+
47
+ ### Wrapping page in Uniform Context
48
+
49
+ In order for personalization and A/B testing functionality to work client side, we must wrap the entire page in the UniformContext component. This should modify `app/layout.tsx` and wrap `{children}`.
50
+
51
+ ```tsx
52
+ import { UniformContext } from "@uniformdev/canvas-next-rsc";
53
+
54
+ export default function RootLayout({
55
+ children,
56
+ }: {
57
+ children: React.ReactNode;
58
+ }) {
59
+ return (
60
+ <html lang="en">
61
+ <body>
62
+ <main className="main">
63
+ <UniformContext>{children}</UniformContext>
64
+ </main>
65
+ </body>
66
+ </html>
67
+ );
68
+ }
69
+ ```
70
+
71
+ ### Rendering Uniform Components using React Components
72
+
73
+ The `UniformComposition` component needs to know how to map a Uniform Component instance's `type` to a React component that implements the UI for that component. This is done using resolveComponent. To use the component registry, first create a component:
74
+
75
+ ```tsx
76
+ export const HeaderComponent = () => {
77
+ return <>Header</>;
78
+ };
79
+ ```
80
+
81
+ Then register it in the resolveComponent function:
82
+
83
+ ```tsx
84
+ import {
85
+ DefaultNotImplementedComponent,
86
+ ResolveComponentFunction,
87
+ ResolveComponentResult,
88
+ } from "@uniformdev/canvas-next-rsc/component";
89
+ import { HeaderComponent } from "@/components/header";
90
+
91
+ export const resolveComponent: ResolveComponentFunction = ({ component }) => {
92
+ let result: ResolveComponentResult = {
93
+ component: DefaultNotImplementedComponent,
94
+ };
95
+
96
+ if (component.type === "header") {
97
+ result = {
98
+ component: HeaderComponent,
99
+ };
100
+ }
101
+
102
+ return result;
103
+ };
104
+ ```
105
+
106
+ #### Mapping Uniform Components to React Components
107
+
108
+ React components that receive Uniform Component data are passed props that correspond to the shape of the component definition they render. The `ComponentProps` type can be used to make the mapping explicit:
109
+
110
+ ```tsx
111
+ import { ComponentProps } from "@uniformdev/canvas-next-rsc/component";
112
+ import { RichTextParamValue } from "@uniformdev/canvas";
113
+
114
+ type HeaderParameters = {
115
+ textParameter?: string;
116
+ richTextParameter?: RichTextParamValue;
117
+ // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
118
+ };
119
+
120
+ type HeaderProps = ComponentProps<HeaderParameters>;
121
+
122
+ export const HeaderComponent = ({ textParameter }: HeaderProps) => {
123
+ return (
124
+ <>
125
+ <span>{textParameter}</span>
126
+ </>
127
+ );
128
+ };
129
+ ```
130
+
131
+ #### Rendering child slots
132
+
133
+ If a Uniform Component definition has slots defined, the components in those slots can be rendered using the `UniformSlot` component.
134
+
135
+ ```tsx
136
+ import {
137
+ ComponentProps,
138
+ UniformSlot,
139
+ } from "@uniformdev/canvas-next-rsc/component";
140
+ import { RichTextParamValue } from "@uniformdev/canvas";
141
+
142
+ type HeaderParameters = {
143
+ textParameter?: string;
144
+ richTextParameter?: RichTextParamValue;
145
+ // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
146
+ };
147
+ type HeaderSlots = "logo" | "navigation";
148
+
149
+ type HeaderProps = ComponentProps<HeaderParameters, HeaderSlots>;
150
+
151
+ export const HeaderComponent = ({ slots, context, component }: HeaderProps) => {
152
+ return (
153
+ <>
154
+ <UniformSlot context={context} data={component} slot={slots.logo} />
155
+ <UniformSlot context={context} data={component} slot={slots.navigation} />
156
+ </>
157
+ );
158
+ };
159
+ ```
160
+
161
+ #### Rendering parameter values
162
+
163
+ When rendering a `text` type parameter, using the `UniformText` component will enable authors to edit the value within the Uniform preview directly. Text parameters that do not have a visible component, such as alt text, should be rendered as their raw text value:
164
+
165
+ ```tsx
166
+ import {
167
+ ComponentProps,
168
+ UniformText,
169
+ } from "@uniformdev/canvas-next-rsc/component";
170
+ import { RichTextParamValue } from "@uniformdev/canvas";
171
+
172
+ type HeaderParameters = {
173
+ textParameter?: string;
174
+ richTextParameter?: RichTextParamValue;
175
+ // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
176
+ };
177
+
178
+ type HeaderProps = ComponentProps<HeaderParameters>;
179
+
180
+ export const HeaderComponent = ({ component, context }: HeaderProps) => {
181
+ return (
182
+ <>
183
+ <UniformText
184
+ component={component}
185
+ context={context}
186
+ parameterId="textParameter"
187
+ as="h1"
188
+ />
189
+ </>
190
+ );
191
+ };
192
+ ```
193
+
194
+ For rich text parameters, the `UniformRichText` component will automatically render the rich text stored as JSON to HTML:
195
+
196
+ ```tsx
197
+ import {
198
+ ComponentProps,
199
+ UniformRichText,
200
+ } from "@uniformdev/canvas-next-rsc/component";
201
+ import { RichTextParamValue } from "@uniformdev/canvas";
202
+
203
+ type HeaderParameters = {
204
+ textParameter?: string;
205
+ richTextParameter?: RichTextParamValue;
206
+ // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
207
+ };
208
+
209
+ type HeaderProps = ComponentProps<HeaderParameters>;
210
+
211
+ export const HeaderComponent = ({ component, context }: HeaderProps) => {
212
+ return (
213
+ <>
214
+ <UniformRichText
215
+ component={component}
216
+ context={context}
217
+ parameterId="richTextParameter"
218
+ />
219
+ </>
220
+ );
221
+ };
222
+ ```
223
+
224
+ Note: asset parameters are rendered directly from props, there is no `UniformAsset` component.
225
+
226
+ ### Configuring Contextual Editing Live Preview
227
+
228
+ To enable contextual editing and live preview to operate within the Uniform application, we need to register a _preview handler_ and _playground page_. The preview handler is an API endpoint that Uniform invokes when preview starts. It is responsible for mapping the composition ID under preview to a redirect to the correct frontend route to display that composition. The default handler does this using project map hierarchy.
229
+
230
+ `app/api/preview/route.ts`:
231
+
232
+ ```tsx
233
+ import {
234
+ createPreviewGETRouteHandler,
235
+ createPreviewPOSTRouteHandler,
236
+ createPreviewOPTIONSRouteHandler,
237
+ } from '@uniformdev/canvas-next-rsc/handler';
238
+
239
+ export const GET = createPreviewGETRouteHandler({
240
+ playgroundPath: '/playground',
241
+ resolveFullPath: ({ path }) => (path ? path : '/playground'),
242
+ });
243
+ export const POST = createPreviewPOSTRouteHandler();
244
+ export const OPTIONS = createPreviewOPTIONSRouteHandler();
245
+ ```
246
+
247
+ The preview playground is a special route used to preview Uniform Patterns (reusable chunks of a page). It should use the same resolveComponent function. The playground route includes the global page shell of the application:
248
+
249
+ `app/playground/page.tsx`:
250
+
251
+ ```tsx
252
+ import {
253
+ UniformPlayground,
254
+ UniformPlaygroundProps,
255
+ } from "@uniformdev/canvas-next-rsc";
256
+ import { resolveComponent } from "@/uniform/resolve";
257
+
258
+ export default function PlaygroundPage(props: {
259
+ searchParams: UniformPlaygroundProps["searchParams"];
260
+ }) {
261
+ return <UniformPlayground {...props} resolveComponent={resolveComponent} />;
262
+ }
263
+ ```
@@ -0,0 +1,97 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+ # Uniform SDK Developer Reference
7
+
8
+ This document details general information and practices about how Uniform works for developers writing frontend applications.
9
+
10
+ [uniform.mdc](mdc:.cursor/rules/uniform.mdc) describes general Uniform principles and practices.
11
+
12
+ ## Authenticating to Uniform
13
+
14
+ To fetch a composition, you need a Uniform API key configured. API keys are commonly stored as `UNIFORM_API_KEY` in a `.env` file. They follow the format `uf......`. The API key requires "Read Published Compositions" permission.
15
+
16
+ ## How Uniform transfers layout data to frontend applications
17
+
18
+ Uniform provides _composition instances_, a hierarchical JSON structure of components that define screens or pages in an application. A composition is made up of any number of _components_ which have a type that we map to a frontend component.
19
+
20
+ ### Routing
21
+
22
+ Uniform's _Project Map_ feature enables automatic dynamic route delegation to Uniform authors. Frontend applications define a wildcard route that delegates routing to the Uniform _Route API_, which takes a dynamic path and resolves the correct composition instance data to display for that path.
23
+
24
+ ### Syncing data with the Uniform CLI
25
+
26
+ Uniform provides a CLI which can be used to sync the state of a Uniform project, such as component definitions, pattern definitions, or compositions, to files on disk. These files may be committed to source control and used to ensure the states of environment or developer-specific projects are kept up to date to reduce the chance of errors.
27
+
28
+ #### Required package for Uniform CLI
29
+
30
+ The Uniform CLI is contained in the `@uniformdev/cli` npm package.
31
+
32
+ #### Authenticating with the Uniform CLI
33
+
34
+ The Uniform CLI requires a Uniform API key to authenticate. The API key and other connectivity details are stored in a `.env` file. When creating an API key for the CLI, the user can use the "Copy as .env" function in the Uniform dashboard to get the appropriate environment variable values.
35
+ API keys used for the Uniform CLI require read and write permissions to any entity types that are to be synced. The default 'developer' role is a shortcut to full permissions.
36
+
37
+ #### Configuring the Uniform CLI
38
+
39
+ Uniform CLI is configured using the `uniform.config.{ts,js}` file in the root of a project. The file can be configured in two ways: to sync everything (choose this for initial setup), or to pick specific entity types to sync. Sync operates as a mirror by default, meaning creates, updates, and deletes are all synced.
40
+
41
+ `uniform.config.ts` (sync all):
42
+
43
+ ```ts
44
+ import { uniformConfig } from "@uniformdev/cli/config";
45
+
46
+ export default uniformConfig({ preset: "all" });
47
+ ```
48
+
49
+ `uniform.config.ts` (sync explicit types and customization options):
50
+
51
+ ```ts
52
+ import { uniformConfig } from "@uniformdev/cli/config";
53
+
54
+ export default uniformConfig({
55
+ // 'none' starts with no entities, and each entity type to sync is added explicitly
56
+ preset: "none",
57
+ config: {
58
+ serialization: {
59
+ // optionally override the default `./uniform-data` to store serialized files
60
+ directory: "./custom-path-to-serialized-files",
61
+ // optionally change the default yaml format to json
62
+ format: "json",
63
+ entitiesConfig: {
64
+ // specify entity types to sync. Each type can optionally override
65
+ // the defaults just for itself, i.e. directory, format
66
+ component: {},
67
+ componentPattern: { publish: true },
68
+ },
69
+ },
70
+ },
71
+ });
72
+ ```
73
+
74
+ #### Invoking the Uniform CLI
75
+
76
+ The Uniform CLI operates using two primary commands:
77
+
78
+ `uniform sync push` - takes the serialized state of entities (files on disk) and pushes that state into a Uniform project online.
79
+
80
+ `uniform sync pull` - takes the online state of a Uniform project and pulls it into serialized files.
81
+
82
+ Conventionally these commands are registered as package scripts to make it unnecessary to install the CLI package globally:
83
+
84
+ `package.json`:
85
+
86
+ ```json
87
+ {
88
+ "scripts": {
89
+ "uniform:pull": "uniform sync pull",
90
+ "uniform:push": "uniform sync push"
91
+ }
92
+ }
93
+ ```
94
+
95
+ #### Getting Uniform CLI help
96
+
97
+ The Uniform CLI has a built-in help system. To get help on a command, run `uniform <command> --help`, for example `uniform sync pull --help`.
@@ -0,0 +1,153 @@
1
+ ---
2
+ description: Uniform Content Modeling Reference - details content modeling options and techniques in Uniform CMS
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+
7
+ ## Uniform Core Concepts
8
+
9
+ Uniform is a modern, headless, component-based Content Management System (CMS). Its primary purpose is to allow non-technical authors (marketers, etc) to create and maintain websites and other similar experiences in a visual editor.
10
+
11
+ ### Uniform Compositions
12
+
13
+ A composition instance in Uniform is roughly equivalent to a page. Composition definitions define a reusable schema for composition instances. Composition definitions have a structure identical to a Uniform Component, i.e. parameters and slots. Composition instances differ from components in that they also define a route or page. Instances of a composition create pages or routes within an application. The term "Composition" can be used to refer either to a definition or instance of a composition, you will need to infer which is meant (schema/reusable template = definition, page/route = instance).
14
+
15
+ Composition parameters should only be used for global content that will never need to be personalized.
16
+ Good example: OpenGraph data and meta tags (if they exist)
17
+ Bad example: "hero title" belongs in a Hero component in the content slot.
18
+
19
+ A single composition definition called 'Page' is generally a good starting point. Additional composition definitions are only required if the page shell is different (e.g. Page, Popup, Minimal Page), or if there are different parameters needed on the composition definition
20
+
21
+ In developer terms, a composition instance is a dynamic layout that is defined by non-technical authors; a composition definition is a hierarchical content schema definition.
22
+
23
+ ### Uniform Components
24
+
25
+ Uniform Components are used to allow CMS authors to create and manipulate visual elements on a composition. Each property of a Uniform Component, such as a title or image, is called a _Component Parameter_. See _Uniform Parameter/Field Types_ for the exact types of parameter that are allowed. Components have both a definition (their schema) and instances (when an instance of that schema is placed within a slot on a composition).
26
+
27
+ Uniform Components can define named _slots_.
28
+
29
+ - A slot allows additional components to be inserted within the Uniform Component. For example an accordion component could have an 'items' slot that allows adding Accordion Item components.
30
+ - Each named slot has 0..n child components. The order in the slot determines the order of rendering.
31
+ - Each slot definition allows only specific Uniform Components to be placed within it (by public id). It can also define the minimum and maximum number of components allowed.
32
+ - Components allowed within slots can also have their own slots, with no depth limit - but it is generally undesirable to nest more than 2-3 levels deep to improve author understanding.
33
+ - When a Uniform Composition is defined, it almost always has a generic 'content' slot added to it that allows using various components to define the layout.
34
+
35
+ Uniform Component Definition attributes:
36
+
37
+ - _name_
38
+ - _public ID_
39
+ - _parameters_
40
+ - _slots_
41
+
42
+ Uniform Slot Definition attributes:
43
+
44
+ - _name_
45
+ - _public ID_
46
+ - _allowed components_
47
+ - _min components_
48
+ - _max components_
49
+
50
+ In technical terms, a Uniform Component maps directly to a presentational frontend component such as a React component. The parameters are component props. Slots are component props that contain rendered child components.
51
+
52
+ ### Uniform Content Types
53
+
54
+ Uniform Content Types define a reusable structure for individual reusable pieces of content. A Uniform content type differs from a Uniform component because a component represents a specific visual element on a composition/page, but a content type is an abstract, reusable content schema. An instance of a Uniform Content Type is called an _Entry_. Entries each have their own built-in slug: there is no need to define an explicit slug field.
55
+
56
+ For example a Product might be a Uniform Content Type, and the data from instances of that Product could be presented in different contexts by Uniform Patterns such as Product List, Product Detail, or Product Card.
57
+
58
+ Uniform Content Types define content properties called _Fields_ (e.g. a blog post could have a single-line text input for title, and a rich text editor for body). See _Uniform Parameter/Field Types_ for the exact types of field that are allowed.
59
+
60
+ Uniform Content Type attributes:
61
+
62
+ - _name_
63
+ - _public ID_
64
+ - _fields_
65
+
66
+ ### Uniform Patterns
67
+
68
+ Patterns allow reusing the same content across compositions. The simplest way to think of a pattern is that it is a _shared component instance_ that can be placed within a slot to insert the pattern's content there. The pattern, like any other component instance, can have values in its parameters and child components in its slots. All usages of the same pattern reference the same shared content. Updates made to patterns are immediately reflected to all usages. Patterns may be nested within each other (e.g. a Blog Post Hero pattern could include a Author Bio pattern in one of its slots). Nesting beyond 2-3 levels can cause performance issues.
69
+
70
+ #### Uniform Pattern Overrides
71
+
72
+ Parameters on patterns can be defined _overridable_ by the pattern definition. Overridable parameter values default to using the value defined on the pattern, but consumers of the pattern may choose to break the inheritance of that parameter value and replace it with their own instance-specific value. Patterns that contain other patterns may not alter the overridability of nested pattern parameters: once overridable, any consumer of the pattern can change the value. Overrides are used to allow partial content sharing and exception cases.
73
+
74
+ #### Using Uniform Patterns as Shared Content Snippets
75
+
76
+ Patterns can be used to reuse shared content, for example the same legal disclaimer might be required on every press release. Both patterns and components allow content reuse: the difference is that patterns reuse exact content, whereas components reuse content schemas but do not provide content values.
77
+
78
+ #### Using Uniform Patterns as Data Binding Templates
79
+
80
+ Patterns can be used to create bindings between structured data (from Uniform Entries or external data sources, like REST APIs or other CMSes) and presentation parameters. A pattern can define a _Data Resource_ which is the result of fetching from a data source. Then parameters in the pattern can use _Dynamic Tokens_ to bind to elements within the data resource. For example, we might have a Card component that has a title and image. Then we create a Product Card pattern, based on the Card component, which has a Uniform Entry Data Resource that fetches an entry specified by the pattern consumer. The Product Card automatically binds the title and image from the product entry to the Card component's parameters. As an author, one can then insert a Product Card pattern, choose the product to use, and have the title and image automatically set up for them.
81
+
82
+ Example of a resolved Data Resource (named 'myEntry'):
83
+ { "myEntry": { "fields": { "title": "hello world" } } }
84
+
85
+ Example of a Dynamic Token in a text parameter referencing the myEntry title:
86
+ "today's greeting: ${#jptr:/myEntry/fields/title}" (this resolves to "today's greeting: hello world")
87
+
88
+ #### Uniform Pattern attributes
89
+
90
+ - _name_
91
+ - _type_ - public ID of the base Uniform Component
92
+ - _public id_ - id of the pattern
93
+ - _data resources_ (name, type)
94
+ - _parameters_ (value, overridable)
95
+ - _slots_
96
+
97
+ ## Conventions
98
+
99
+ ### Uniform Field/Parameter Types
100
+
101
+ Uniform Fields or Uniform Parameters attributes:
102
+
103
+ - _name_
104
+ - _public ID_. Must be unique within a Uniform Component or Uniform Content Type (including the ID of group fields/parameters)
105
+ - _localizable_. Localizable values have a distinct value for each locale; otherwise the value is the same for all locales.
106
+ - _required_. Required means that a CMS author must input a value in order to be considered valid.
107
+ - _type_. See list below.
108
+ - _guidance_. Brief LLM instructions used when generating or editing values.
109
+ - _overridable_. Only applies for fields/parameters on a pattern definition. Allows consumers of the pattern to break inheritance and change the pattern definition's value for the field/parameter.
110
+
111
+ Exhaustive list of allowed field/parameter types:
112
+
113
+ - _text_: Plain text content
114
+ - _richText_: Formatted text with styling (Lexical JSON format)
115
+ - _select_: Choose between a controlled vocabulary of options
116
+ - _multi-select_: Choose between a controlled vocabulary of options, allowing multiple selections
117
+ - _number_: Numeric value
118
+ - _date_: Calendar date
119
+ - _dateTime_: Date with timezone
120
+ - _checkbox_: Boolean toggle
121
+ - _link_: URL or internal reference
122
+ - _asset_: Image, video, audio, or other file
123
+ - _json_: A JSON object. Not for use in author-facing fields/parameters, who will have trouble editing JSON.
124
+ - _contentReference_: References a single or multiple Entries of a specified type. Can only be used in Fields on Content Types (not Parameters on Components)
125
+ - _enrichmentTag_: Tag content with enrichments (relevant segments) to make viewing the content alter the classification of the visitor that saw it.
126
+ - _group_: Group multiple fields/parameters together visually, for example a group of address fields. IMPORTANT: fields added to a group must come directly after the group in the fields list.
127
+
128
+ ### Uniform Naming Conventions
129
+
130
+ - All names should be title-cased prose, not technical shorthand (e.g. "Main Header" not "main-header" or "MainHeader"). There is no need to include the type of entity in a name (e.g. 'Hero' not 'Hero Component').
131
+ - Do not name Uniform Components, Uniform Content Types, or Fields/Parameters based on visible content found in inputs; treat it as FPO (e.g. <h1>Hello</h1> does not mean name the component 'Hello' - describe its meaning instead, such as 'Headline').
132
+ - _Public ID_ are developer-facing identifiers for Uniform entities. They are based on a slugified version of the name. Use a camel case, for example if the name is "Main Header", the public ID is "mainHeader". Public IDs must be unique within a given entity type (e.g. Uniform Components). You cannot alter public IDs after creating an entity.
133
+ - Descriptions or help text should be no longer than 1 short sentence. It is not necessary to write help text unless we have specific expectations for authors. For example a 'Title' doesn't need help text. But if we identify an image that needs to be 250x250px, that expectation belongs in help text. Descriptions and help text are plain text, no markdown or HTML.
134
+
135
+ ## Tool Usage Tips
136
+
137
+ - Before creating or updating Uniform Patterns, fetch Uniform Component Definitions to ensure you know about valid component types and parameters.
138
+ - When making multiple updates to the same Uniform Pattern, such as adding a component and setting a parameter value, batch changes together into a single tool call to improve performance and consistency.
139
+ - When a Uniform tool provides you with an edit URL offer it to the user as a link, unless you already have recently.
140
+ - Before inserting, removing, or reordering parameters or fields from a Uniform Component or Uniform Content Type, make sure to fetch the latest definition data to ensure you target the correct location.
141
+ - If you are tasked with reordering fields or parameters, you must remove them and re-add them in the new order
142
+
143
+ ## Unsupported Features
144
+
145
+ The following Uniform features cannot currently be changed using MCP/AI. If asked to perform the following actions, explain you cannot yet do that, and when possible offer a link to perform the task in the Uniform web app.
146
+
147
+ - Managing Uniform locales, both global registration and enablement on compositions or entries
148
+ - Managing the project map, including adding or fetching nodes, or attaching compositions to project map nodes.
149
+ - Managing compositions or entries (creating, updating)
150
+ - Managing entry patterns
151
+ - Managing block fields/parameters, or block type definitions
152
+ - Setting the value of asset or reference type fields/parameters
153
+ - Data sources, data types, and data resources