diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json
new file mode 100644
index 0000000..b0f0792
--- /dev/null
+++ b/.cursor-plugin/marketplace.json
@@ -0,0 +1,25 @@
+{
+ "name": "uniform.dev",
+ "owner": {
+ "name": "Uniform.dev",
+ "email": "plugins@example.com"
+ },
+ "metadata": {
+ "description": "Uniform.dev",
+ "version": "1.0.0"
+ },
+ "plugins": [
+ {
+ "name": "uniform-rules",
+ "source": "uniform-rules",
+ "description": "Uniform CMS rules for AI-assisted development (compositions, components, patterns, SDK, mesh)",
+ "keywords": ["uniform", "cms", "headless", "canvas", "sveltekit", "next"]
+ },
+ {
+ "name": "enterprise-toolkit",
+ "source": "enterprise-toolkit",
+ "description": "Enterprise development toolkit with security, compliance, and automation",
+ "keywords": ["enterprise", "security", "compliance", "code-review"]
+ }
+ ]
+}
diff --git a/enterprise-toolkit/.cursor-plugin/plugin.json b/enterprise-toolkit/.cursor-plugin/plugin.json
new file mode 100644
index 0000000..803e063
--- /dev/null
+++ b/enterprise-toolkit/.cursor-plugin/plugin.json
@@ -0,0 +1,11 @@
+{
+ "name": "enterprise-toolkit",
+ "version": "1.0.0",
+ "description": "Enterprise development toolkit with security scanning, compliance checks, and automation",
+ "author": {
+ "name": "AI Rules",
+ "email": "plugins@example.com"
+ },
+ "keywords": ["enterprise", "security", "compliance", "code-review"],
+ "logo": "assets/logo.svg"
+}
diff --git a/enterprise-toolkit/.mcp.json b/enterprise-toolkit/.mcp.json
new file mode 100644
index 0000000..4c596b6
--- /dev/null
+++ b/enterprise-toolkit/.mcp.json
@@ -0,0 +1,9 @@
+{
+ "mcpServers": {
+ "filesystem": {
+ "command": "npx",
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
+ "env": {}
+ }
+ }
+}
diff --git a/enterprise-toolkit/README.md b/enterprise-toolkit/README.md
new file mode 100644
index 0000000..5b82b89
--- /dev/null
+++ b/enterprise-toolkit/README.md
@@ -0,0 +1,22 @@
+# Enterprise Toolkit
+
+Cursor plugin with security standards, compliance checks, and automation for enterprise development.
+
+## Contents
+
+- **Rules**: `security-standards.mdc`, `code-style.mdc`
+- **Skills**: `compliance-check`, `security-review`
+- **Agents**: `security-reviewer`, `compliance-checker`
+- **Commands**: `run-compliance-scan`
+- **Hooks**: afterFileEdit (format), beforeShellExecution (validate), sessionEnd (audit)
+- **MCP**: Optional filesystem server (configure path in `.mcp.json`)
+
+## Configuration
+
+- Edit `hooks/hooks.json` to enable or disable hooks and matchers.
+- Edit `.mcp.json` to add or change MCP servers (e.g. database, APIs).
+- Replace placeholder scripts in `scripts/` with your formatters and validators.
+
+## Usage
+
+Install this plugin via the Cursor marketplace or from this repo. Rules and skills apply when the plugin is active. Use agents and commands from the Cursor UI as needed.
diff --git a/enterprise-toolkit/agents/compliance-checker.md b/enterprise-toolkit/agents/compliance-checker.md
new file mode 100644
index 0000000..72e5d9e
--- /dev/null
+++ b/enterprise-toolkit/agents/compliance-checker.md
@@ -0,0 +1,15 @@
+---
+name: compliance-checker
+description: Runs compliance and policy checks on the codebase
+---
+
+# Compliance Checker
+
+You run compliance and policy checks. When asked:
+
+1. Summarize security-related findings (secrets, dependencies, obvious vulnerabilities)
+2. Note licensing and policy documents (CONTRIBUTING, SECURITY, LICENSE)
+3. Compare current state to any stated policies
+4. Produce a short pass/warn/fail report with next steps
+
+Use the compliance-check skill when performing detailed audits.
diff --git a/enterprise-toolkit/agents/security-reviewer.md b/enterprise-toolkit/agents/security-reviewer.md
new file mode 100644
index 0000000..324d9f3
--- /dev/null
+++ b/enterprise-toolkit/agents/security-reviewer.md
@@ -0,0 +1,17 @@
+---
+name: security-reviewer
+description: Security-focused code reviewer that checks for vulnerabilities and proven approaches
+---
+
+# Security Reviewer
+
+You are a security-focused code reviewer. When reviewing code:
+
+1. Check for injection vulnerabilities (SQL, XSS, command injection)
+2. Verify proper authentication and authorization
+3. Look for sensitive data exposure (API keys, passwords, PII)
+4. Ensure secure cryptographic practices
+5. Review dependency security and known vulnerabilities
+6. Check for proper input validation and sanitization
+
+Report findings with severity and concrete remediation. Prefer safe defaults.
diff --git a/enterprise-toolkit/assets/logo.svg b/enterprise-toolkit/assets/logo.svg
new file mode 100644
index 0000000..252a7b4
--- /dev/null
+++ b/enterprise-toolkit/assets/logo.svg
@@ -0,0 +1,19 @@
+
+
+
diff --git a/enterprise-toolkit/commands/run-compliance-scan.md b/enterprise-toolkit/commands/run-compliance-scan.md
new file mode 100644
index 0000000..0d91e5f
--- /dev/null
+++ b/enterprise-toolkit/commands/run-compliance-scan.md
@@ -0,0 +1,27 @@
+---
+name: run-compliance-scan
+description: Run a full compliance scan (security, licensing, policy) on the current project
+---
+
+# Run compliance scan
+
+Execute a compliance scan for the current project:
+
+1. **Security**
+ - Check for hardcoded secrets and unsafe patterns
+ - List dependency audit commands (e.g. `npm audit`, `pnpm audit`) and suggest running them
+ - Note any obvious injection or auth issues in the codebase
+
+2. **Licensing**
+ - Identify root and package license files
+ - Summarize license types; flag any that may need legal review
+
+3. **Policy**
+ - Look for CONTRIBUTING.md, SECURITY.md, CODE_OF_CONDUCT.md, or similar
+ - Summarize requirements and whether the repo state aligns
+
+4. **Report**
+ - Output a short summary with pass/warn/fail per area
+ - Recommend concrete next steps (e.g. run `npm audit`, add SECURITY.md)
+
+Do not modify code or run destructive commands unless the user asks.
diff --git a/enterprise-toolkit/hooks/hooks.json b/enterprise-toolkit/hooks/hooks.json
new file mode 100644
index 0000000..603426e
--- /dev/null
+++ b/enterprise-toolkit/hooks/hooks.json
@@ -0,0 +1,21 @@
+{
+ "hooks": {
+ "afterFileEdit": [
+ {
+ "command": "./scripts/format-code.py",
+ "matcher": "**/*.py"
+ }
+ ],
+ "beforeShellExecution": [
+ {
+ "command": "./scripts/validate-shell.sh",
+ "matcher": "rm\\s+-rf|curl\\s+.*\\|\\s*sh|wget\\s+.*\\|\\s*sh"
+ }
+ ],
+ "sessionEnd": [
+ {
+ "command": "./scripts/audit.sh"
+ }
+ ]
+ }
+}
diff --git a/enterprise-toolkit/rules/code-style.mdc b/enterprise-toolkit/rules/code-style.mdc
new file mode 100644
index 0000000..6e91751
--- /dev/null
+++ b/enterprise-toolkit/rules/code-style.mdc
@@ -0,0 +1,13 @@
+---
+description: Consistent code style and cleanup
+alwaysApply: true
+globs:
+---
+
+# Code style
+
+- Prefer `const` over `let` for variables that are never reassigned.
+- Remove unused code and imports so linters and type checks pass.
+- Use the project's existing style (indentation, quotes, semicolons). When in doubt, match surrounding code.
+- Keep functions and files focused; avoid unnecessary abstraction.
+- Add comments in English when non-obvious logic needs explanation.
diff --git a/enterprise-toolkit/rules/security-standards.mdc b/enterprise-toolkit/rules/security-standards.mdc
new file mode 100644
index 0000000..83d8b07
--- /dev/null
+++ b/enterprise-toolkit/rules/security-standards.mdc
@@ -0,0 +1,16 @@
+---
+description: Security standards for code - injection, auth, secrets, crypto
+alwaysApply: false
+globs: "**/*.{ts,tsx,js,jsx,py,go,java}"
+---
+
+# Security standards
+
+When writing or reviewing code, enforce these practices:
+
+1. **Injection**: Never concatenate user input into SQL, shell commands, or HTML. Use parameterized queries, safe APIs, and output encoding.
+2. **Authentication and authorization**: Verify identity and permissions on every sensitive operation. Prefer established libraries (e.g. OAuth2, JWT validation).
+3. **Secrets**: Never commit API keys, passwords, or tokens. Use environment variables or secret managers. Do not log or expose secrets in errors.
+4. **Cryptography**: Use standard libraries and algorithms (e.g. bcrypt/argon2 for hashing, TLS for transport). Avoid custom crypto.
+5. **Input validation**: Validate and sanitize all external input. Enforce allowlists and bounds where possible.
+6. **Dependencies**: Keep dependencies updated. Check for known vulnerabilities (e.g. npm audit, dependabot).
diff --git a/enterprise-toolkit/scripts/audit.sh b/enterprise-toolkit/scripts/audit.sh
new file mode 100644
index 0000000..878a8c6
--- /dev/null
+++ b/enterprise-toolkit/scripts/audit.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+# Optional session-end audit. Hook script for enterprise-toolkit.
+# Placeholder: e.g. log session end, run lightweight checks.
+exit 0
diff --git a/enterprise-toolkit/scripts/format-code.py b/enterprise-toolkit/scripts/format-code.py
new file mode 100644
index 0000000..07d16cd
--- /dev/null
+++ b/enterprise-toolkit/scripts/format-code.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+"""
+Format Python files after edit. Hook script for enterprise-toolkit.
+Replace with actual formatter (e.g. black, ruff format) as needed.
+"""
+import sys
+
+# Placeholder: in production, run e.g. subprocess.run(["black", path])
+# This script is invoked by the afterFileEdit hook for **/*.py
+if __name__ == "__main__":
+ sys.exit(0)
diff --git a/enterprise-toolkit/scripts/validate-shell.sh b/enterprise-toolkit/scripts/validate-shell.sh
new file mode 100644
index 0000000..47d1634
--- /dev/null
+++ b/enterprise-toolkit/scripts/validate-shell.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+# Validates shell commands before execution. Hook script for enterprise-toolkit.
+# Placeholder: in production, parse stdin and block dangerous patterns (e.g. rm -rf /, curl | sh).
+exit 0
diff --git a/enterprise-toolkit/skills/compliance-check/SKILL.md b/enterprise-toolkit/skills/compliance-check/SKILL.md
new file mode 100644
index 0000000..fe1a9fd
--- /dev/null
+++ b/enterprise-toolkit/skills/compliance-check/SKILL.md
@@ -0,0 +1,21 @@
+---
+name: compliance-check
+description: Run compliance checks for security, licensing, and policy. Use when auditing a codebase, before releases, or when asked about compliance or policy.
+---
+
+# Compliance Check Skill
+
+## When to use
+
+- Auditing a codebase for security or policy compliance
+- Before releases or merge to main
+- When the user asks about compliance, licensing, or policy
+
+## Instructions
+
+1. **Security**: Scan for hardcoded secrets, unsafe dependencies, and obvious injection or auth issues. Suggest fixes or follow-up tools (e.g. npm audit, secret scanning).
+2. **Licensing**: Note any license files or package metadata. Flag incompatible or unclear licenses if the user cares about license compliance.
+3. **Policy**: If the project has a CONTRIBUTING, SECURITY, or policy doc, summarize requirements and check whether the current change aligns.
+4. **Reporting**: Summarize findings in a short report (pass/warn/fail per area). Recommend concrete next steps.
+
+Do not run destructive or invasive commands unless the user explicitly requests them.
diff --git a/enterprise-toolkit/skills/security-review/SKILL.md b/enterprise-toolkit/skills/security-review/SKILL.md
new file mode 100644
index 0000000..ebb41c4
--- /dev/null
+++ b/enterprise-toolkit/skills/security-review/SKILL.md
@@ -0,0 +1,25 @@
+---
+name: security-review
+description: Security-focused code review. Use when reviewing PRs, auditing for vulnerabilities, or improving secure coding practices.
+---
+
+# Security Reviewer Skill
+
+## When to use
+
+- Reviewing pull requests or diffs for security issues
+- Auditing code for vulnerabilities
+- Improving secure coding practices
+
+## Instructions
+
+When performing a security review:
+
+1. **Injection**: Look for SQL, command, or XSS injection (untrusted input in queries, exec, or DOM).
+2. **Auth and access control**: Check that sensitive operations require authentication and correct authorization.
+3. **Secrets and PII**: Ensure no API keys, passwords, or PII are logged, committed, or exposed in errors.
+4. **Crypto**: Verify hashing, encryption, and TLS usage follow best practices (no custom crypto, strong algorithms).
+5. **Dependencies**: Note outdated or known-vulnerable packages; suggest updates or alternatives.
+6. **Input validation**: Check that external input is validated and sanitized before use.
+
+Provide a concise list of findings with severity (high/medium/low) and concrete remediation steps. Prefer safe defaults and defense in depth.
diff --git a/readme.md b/readme.md
index 249f9a0..e3e2281 100644
--- a/readme.md
+++ b/readme.md
@@ -1,25 +1,63 @@
-# Uniform rules for AI-assisted development
+# Cursor Marketplace – AI Rules
-This is the library of Uniform-specific rules to help your LLM tools work better with Uniform.
-Feeding these rules to your LLM will help it understand the context of the project and the specific requirements of Uniform.
+This repository is a **Cursor marketplace**: a multi-plugin repo that can be submitted to the Cursor marketplace so others can install the plugins.
-## How to install
+## Structure
-Run this command and follow the prompt:
-```bash
-npx @uniformdev/cli ai rules install
```
+cursor-marketplace/
+├── .cursor-plugin/
+│ └── marketplace.json # Marketplace manifest (lists plugins)
+├── uniform-rules/ # Plugin: Uniform CMS rules
+│ ├── .cursor-plugin/
+│ │ └── plugin.json
+│ ├── rules/
+│ │ ├── uniform.mdc
+│ │ ├── uniform-sdk.mdc
+│ │ ├── uniform-sveltekit.mdc
+│ │ ├── uniform-next-app-router.mdc
+│ │ ├── uniform-next-page-router.mdc
+│ │ └── uniform-mesh.mdc
+│ └── README.md
+├── enterprise-toolkit/ # Plugin: Security, compliance, automation
+│ ├── .cursor-plugin/
+│ │ └── plugin.json
+│ ├── rules/
+│ ├── skills/
+│ ├── agents/
+│ ├── commands/
+│ ├── hooks/
+│ ├── .mcp.json
+│ ├── assets/
+│ ├── scripts/
+│ └── README.md
+└── README.md
+```
+
+## Plugins
+
+| Plugin | Description |
+|---------------------|-------------|
+| **uniform-rules** | Uniform CMS rules for compositions, components, patterns, SDK, SvelteKit, Next.js, Mesh. |
+| **enterprise-toolkit** | Rules, skills, agents, commands, hooks, and optional MCP for security, compliance, and automation. |
+
+## Submitting to the Cursor marketplace
+
+1. Push this repo (or the `cursor-marketplace` folder as its own repo) to a **public** Git host.
+2. Go to [cursor.com/marketplace/publish](https://cursor.com/marketplace/publish) and submit the repository URL.
+3. Ensure:
+ - Each plugin has a valid `.cursor-plugin/plugin.json` with a unique `name` (lowercase, kebab-case).
+ - All rules/skills/agents/commands have proper frontmatter.
+ - Paths in manifests are relative and valid.
+ - You have tested the plugins locally.
+
+## Local use
-## Must have rules for solution development:
-- [`rules/uniform.mdc`](./rules/uniform.mdc) - describes the core principles and concepts of Uniform
-- [`rules/uniform-sdk.mdc`](./rules/uniform-sdk.mdc) - describes the Uniform SDK and its capabilities
+To use as a local marketplace or single plugin:
-## Must-have rules for Uniform mesh app (custom integration) development
-- [`rules/uniform-mesh.mdc`](./rules/uniform-mesh.mdc)
+- **Multi-plugin**: Point Cursor at the root of `cursor-marketplace` (where `.cursor-plugin/marketplace.json` lives).
+- **Single plugin**: Point Cursor at `cursor-marketplace/uniform-rules` or `cursor-marketplace/enterprise-toolkit`.
-## Framework-specific rules:
-- [`rules/uniform-next-page-router.mdc`](./rules/uniform-next-page-router.mdc) - for Next.js Page Router
-- [`rules/uniform-next-app-router.mdc`](./rules/uniform-next-app-router.mdc) - for Next.js App Router
+## License
-### Optional rules:
-The rules files under [`rules/optional-personal-preferences`](./rules/optional-personal-preference/) contain non-essential rules that contain alternative defaults, highly recommended to review those and adjust to your liking.
+See repository license. Plugin manifests may specify their own license.
diff --git a/rules/uniform-mesh.mdc b/rules/uniform-mesh.mdc
deleted file mode 100644
index f2c4724..0000000
--- a/rules/uniform-mesh.mdc
+++ /dev/null
@@ -1,987 +0,0 @@
-
----
-description:
-globs:
-alwaysApply: true
----
-
-# Uniform Mesh Integrations - AI Development Rules
-
-## Overview
-
-Uniform Mesh is a framework that enables extending the Uniform user interface with custom web applications. These integrations run as web applications hosted on URLs that the developer defines and communicate with the Uniform dashboard through iframe messaging.
-
-### Why Build Custom Mesh Integrations
-
-#### Connect to Custom Data Sources
-Custom Mesh integrations let you connect to data sources that are not supported by Uniform's built-in integrations. This gives your authors a better and more tailored experience when working with external systems.
-
-#### Extend the Uniform UI
-In addition to connecting to custom data sources, you can also extend the Uniform UI to improve the authoring experience or tailor it to your business processes.
-
-## Core Architecture
-
-### Integration Structure
-- **Web Application**: Provides UI incorporated into Uniform dashboard and implements external system interaction logic
-- **Manifest**: JSON configuration that tells Uniform how to incorporate the integration (mesh-manifest.json)
-- **Locations**: Specific areas in the Uniform UI where custom interfaces are rendered
-
-### How Locations Work
-
-Each location receives two types of data:
-
-**Value** - The main data object that your location can view and modify
-- Contains the primary information your location is responsible for editing
-- Example: For a Data Source location, the value contains the Data Source definition (name, configuration, settings)
-- Your location can request changes to this data through the Mesh SDK
-
-**Metadata** - Supporting information provided for context (read-only)
-- Contains related data to help your location function properly
-- Example: For a Data Type editor, metadata includes the current project ID and a copy of the parent Data Source
-- This data cannot be modified by your location
-
-### Technology Stack Requirements
-- **Framework**: Next.js with page router (recommended)
-- **SDK**: `@uniformdev/mesh-sdk-react` (required for React-based integrations)
-- **Design System**: `@uniformdev/design-system` (required for consistent UI)
-- **Uniform CLI**: `@uniformdev/cli` (required CLI package to work with integrations - register it within a team and install it within a given project)
-- **Language**: TypeScript (strongly recommended)
-
-## Manifest Configuration
-
-### Base Manifest Structure
-```json
-{
- "type": "your-integration-type",
- "displayName": "Your Integration Name",
- "baseLocationUrl": "http://localhost:9000",
- "logoIconUrl": "https://example.com/logo.png",
- "badgeIconUrl": "https://example.com/badge.png",
- "category": "content|ai|analytics|commerce",
- "scopes": ["user:read"],
- "locations": {
- // Location definitions
- }
-}
-```
-
-### Required Fields
-- `type`: Unique identifier for the integration
-- `displayName`: Human-readable name shown in Uniform UI
-- `baseLocationUrl`: Base URL where the integration is hosted
-- `locations`: Object defining available integration points
-
-## Location Types and Implementation Patterns
-
-### 1. Basic Locations
-
-#### Install Location
-The Install location is shown in a drawer when installing an integration. Unlike other locations, this is not rendered in an iframe but configured directly in the manifest.
-
-**Manifest Configuration:**
-```json
-"install": {
- "description": [
- "Describe your mesh integration",
- "Each array element will create a new paragraph on the install dialog."
- ],
- "informationUrl": "https://yoursite.com/info-about-this-mesh-app"
-}
-```
-
-#### Settings Location
-Used for integration-wide configuration accessible from Project Settings > Integrations.
-
-**Manifest Configuration:**
-```json
-"settings": {
- "url": "/settings",
- "locations": {
- "settingsDialog": {
- "url": "/settings-dialog"
- }
- }
-}
-```
-
-**Implementation Pattern:**
-```tsx
-import { useMeshLocation } from '@uniformdev/mesh-sdk-react';
-import { Input, Button } from '@uniformdev/design-system';
-
-const Settings = () => {
- const { value, setValue } = useMeshLocation<'settings', { apiKey: string }>('settings');
- const [apiKey, setApiKey] = useState(value?.apiKey ?? '');
-
- const handleSave = () => {
- setValue((previous) => ({
- newValue: { ...previous, apiKey }
- }));
- };
-
- return (
-
- setApiKey(e.currentTarget.value)}
- />
-
-
- );
-};
-```
-
-**Security Note**: If your integration defines data connectors for edge-based data fetching, do not save access credentials in the Settings location. Instead, store them in the Data Source location which provides secure storage.
-
-### 2. Data Connectors
-Enable integration with external data sources for content mapping.
-
-**Manifest Configuration:**
-```json
-"dataConnectors": [
- {
- "type": "your-connector-type",
- "displayName": "Your Data Connector",
- "dataArchetypes": {
- "default": {
- "displayName": "Single Item",
- "dataEditorUrl": "/data-editor",
- "typeEditorUrl": "/type-editor"
- }
- },
- "dataSourceEditorUrl": "/data-source-editor"
- }
-]
-```
-
-**HTTP Fallback Behavior**: If any location of a data connector is not specified in the integration manifest, the UI from the standard `HTTP Request` data connector will be used automatically. This enables integration developers to produce fewer UIs if only looking to customize part of a data connector.
-
-#### Data Source Editor
-Configures connection settings for the external system.
-
-**Implementation Pattern:**
-```tsx
-import { useMeshLocation, DataSourceLocationValue } from '@uniformdev/mesh-sdk-react';
-
-type DataSourceConfig = {
- apiUrl: string;
- apiKey: string;
-};
-
-const DataSourceEditor = () => {
- const { value, setValue } = useMeshLocation<'dataSource'>();
- const config = value.custom as DataSourceConfig;
-
- const handleUpdate = (updates: Partial) => {
- setValue((current) => {
- const newConfig = { ...config, ...updates };
- const newValue: DataSourceLocationValue = {
- ...current,
- baseUrl: newConfig.apiUrl,
- headers: [{ key: 'Authorization', value: `Bearer ${newConfig.apiKey}` }],
- custom: newConfig,
- variants: {
- preview: {
- baseUrl: newConfig.apiUrl,
- parameters: [{ key: 'preview', value: 'true' }]
- }
- }
- };
- return { newValue, options: { isValid: true } };
- });
- };
-
- return (
-
- );
-};
-```
-
-### 5. Project Tools
-Add custom tools to project navigation.
-
-**Manifest Configuration:**
-```json
-"projectTools": [
- {
- "id": "analytics-tool",
- "name": "Analytics Dashboard",
- "url": "/analytics",
- "iconUrl": "/analytics-icon.svg"
- }
-]
-```
-
-Common use cases include:
-- Embedding external applications like analytics tools
-- Custom editorial tools like importers or editorial calendar
-- Project-specific documentation pages or Storybook component reference
-
-### 6. Dashboard Tools
-Add custom dashboards to the project dashboard page.
-
-**Manifest Configuration:**
-```json
-"dashboardTools": [
- {
- "id": "custom-dashboard-id",
- "name": "Custom dashboard",
- "url": "/dashboard-tool",
- "iconUrl": "/dashboard-icon.png"
- }
-]
-```
-
-Common use cases include:
-- Quick links to common content or content filters
-- Editorial dashboards for content editors that connect to external systems
-- Links to internal training or onboarding resources
-- Status or health dashboards for content operations
-
-## Routing in Mesh Locations
-
-Since Mesh locations are rendered inside iframes, standard browser navigation doesn't work for moving between different sections of the Uniform dashboard. The Mesh SDK provides routing helpers that allow your integration to programmatically navigate users to other areas of the platform.
-
-### Using the Router
-
-The router is available through the `useMeshLocation` hook:
-
-```tsx
-import { useMeshLocation } from '@uniformdev/mesh-sdk-react';
-
-const { router } = useMeshLocation<'projectTool'>();
-```
-
-### Navigation Options
-
-**Navigate within the current project:**
-```tsx
-router.navigatePlatform(path);
-```
-The router automatically handles the project context. For example, to navigate to entries: `/dashboards/canvas/entries`.
-
-**Open in a new tab:**
-```tsx
-router.navigatePlatform(path, { target: '_blank' });
-```
-
-**Navigate to a different project:**
-```tsx
-router.navigatePlatform(path, {
- projectId: 'target-project-id',
- target: '_blank'
-});
-```
-
-## Development Workflow
-
-### Create an Integration
-
-To create a new integration, use the Uniform CLI:
-
-```bash
-npx @uniformdev/cli@latest new-integration
-```
-
-The CLI will guide you through:
-- Authenticating to Uniform (including creating an account if needed)
-- Choosing the team to register the integration to
-- Choosing or creating a project to install the integration to
-- Cloning the integration starter kit and examples files
-- Automatically configuring Uniform API keys and environment variables
-
-### Register the Integration
-
-**Team Admin Permission Required**: To register an integration, you must have the Team admin permission.
-
-#### 1. Register at Team Level
-Register your integration to make it available across all projects within the team:
-
-- **Uniform Dashboard**: Navigate to `Settings > Custom integrations` in the team dashboard
-- **Uniform CLI**: Use the integration commands
-
-```bash
-uniform integration register --manifest mesh-manifest.json
-```
-
-#### 2. Install in Project
-Once registered, install the integration in specific projects where you want to use it.
-
-### Deploy an Integration
-
-#### Update Manifest for Production
-Once deployed, update the integration manifest with production URLs instead of local development URLs.
-
-**Best Practice**: Maintain different manifest files for different environments (development and production).
-
-#### Hosting Requirements
-- Mesh integrations can run on public or private domains
-- Browser must be able to access both the app's URL and https://uniform.app
-- HTTPS required for production (HTTP allowed for localhost development)
-- Configure appropriate CORS headers for API endpoints
-
-## Development Patterns and Best Practices
-
-> **⚠️ IMPORTANT**: After creating your integration, you MUST register it with Uniform before you can use it. See the "Installation and Deployment" section for detailed steps.
-
-### Required package
-Make sure to always install **Uniform CLI**: `@uniformdev/cli` as a developer dependency as it is required CLI package to work with integrations - register it within a team and install it within a given project.
-
-### Environment Setup
-```bash
-# Create new integration
-npx @uniformdev/cli@latest new-integration
-
-# Install dependencies
-npm install @uniformdev/mesh-sdk-react @uniformdev/design-system @uniformdev/cli
-
-# Set required environment variables for registration
-UNIFORM_API_KEY=your_api_key
-UNIFORM_TEAM_ID=your_team_id
-UNIFORM_PROJECT_ID=your_project_id
-
-# After development, register integration (see Installation and Deployment section)
-npm run register-to-team
-npm run install-to-project
-```
-
-### Validation Pattern
-```tsx
-import { ValidationResult } from '@uniformdev/mesh-sdk-react';
-
-const useValidation = (value: string): ValidationResult => {
- return useMemo(() => {
- if (!value || value.trim().length === 0) {
- return { isValid: false, validationMessage: 'Value is required' };
- }
-
- try {
- new URL(value);
- return { isValid: true };
- } catch {
- return { isValid: false, validationMessage: 'Invalid URL format' };
- }
- }, [value]);
-};
-
-// Usage in component
-const { value, setValue } = useMeshLocation('dataSource');
-const validation = useValidation(value.baseUrl);
-
-setValue((current) => ({
- newValue: { ...current, baseUrl: newValue },
- options: validation
-}));
-```
-
-### Dialog Management
-```tsx
-import { useOpenDialog, useCloseDialog } from '@uniformdev/mesh-sdk-react';
-
-const ComponentWithDialog = () => {
- const openDialog = useOpenDialog();
- const closeDialog = useCloseDialog();
-
- const handleOpenDialog = () => {
- openDialog({
- location: 'namedDialog',
- size: 'medium',
- title: 'Custom Dialog'
- });
- };
-
- return (
-
- );
-};
-```
-
-### Error Handling Pattern
-```tsx
-import { ErrorBoundary } from 'react-error-boundary';
-import { Callout } from '@uniformdev/design-system';
-
-const ErrorFallback = ({ error }: { error: Error }) => (
-
- {error.message}
-
-);
-
-const IntegrationComponent = () => (
-
-
-
-);
-```
-
-## Development Tools and Resources
-
-### SDK Packages
-The `@uniformdev/mesh-sdk-react` npm package includes full TypeScript typing information and JSDoc comments for all exports.
-
-### Design System Resources
-- [Uniform Design System Storybook](https://design.uniform.app/) - Complete component library for consistent UI
-- [React Mesh SDK Storybook](https://storybook.mesh.uniform.app/) - Usage examples for Mesh-specific components
-- [React Mesh SDK component reference](https://sdk.uniform.app/design-system) - Reference documentation for React Mesh SDK components
-
-### Starter Kit
-Complete examples of how to implement all locations, with tips and tricks, are available in the [Mesh integration starter kit](https://github.com/uniformdev/examples/tree/main/mesh/mesh-integration).
-
-## Custom Edgehancers (Advanced)
-
-Custom edgehancers enable server-side JavaScript execution at the edge for advanced data processing.
-
-### Prerequisites
-- Feature must be enabled for your team (contact Uniform)
-- Team Admin API key required for deployment
-
-### Hook Types
-
-#### Pre-Request Hook
-Modifies HTTP requests before caching.
-
-```typescript
-// edgehancer/preRequest.ts
-import { PreRequestContext } from '@uniformdev/mesh-sdk';
-
-export default function preRequest(context: PreRequestContext) {
- const { requests } = context;
-
- return requests.map(request => ({
- ...request,
- headers: {
- ...request.headers,
- 'Custom-Header': 'value'
- }
- }));
-}
-```
-
-#### Request Hook
-Replaces default HTTP fetch logic.
-
-```typescript
-// edgehancer/request.ts
-import { RequestContext } from '@uniformdev/mesh-sdk';
-
-export default async function request(context: RequestContext) {
- const { requests } = context;
-
- const responses = await Promise.all(
- requests.map(async (req) => {
- const response = await fetch(req.url, {
- headers: req.headers,
- method: req.method,
- body: req.body
- });
-
- const data = await response.json();
-
- // Transform response data
- return {
- ...data,
- processedAt: new Date().toISOString()
- };
- })
- );
-
- return responses;
-}
-```
-
-### Deployment
-```bash
-# Deploy edgehancer
-npm run deploy-edgehancer
-
-# Remove edgehancer
-npm run remove-edgehancer
-```
-
-## Installation and Deployment
-
-> **⚠️ CRITICAL NEXT STEP**: After bootstrapping your integration, you MUST complete the registration and installation process below before you can use your integration in Uniform.
-
-### Required Environment Variables
-
-Before using CLI registration commands, you must set these environment variables:
-
-```bash
-# Required for CLI registration and installation
-UNIFORM_API_KEY=your_api_key_here
-UNIFORM_TEAM_ID=your_team_id_here
-UNIFORM_PROJECT_ID=your_project_id_here
-```
-
-### Development Setup and Registration
-
-1. **Start Development Server**
- ```bash
- npm run dev
- ```
-
-2. **Register Integration to Team** (Required First Step)
- ```bash
- # Register the integration definition to your Uniform team
- npm run register-to-team
- ```
-
-3. **Install Integration to Project** (Required Second Step)
- ```bash
- # Install the integration to your specific project
- npm run install-to-project
- ```
-
-### Available npm Scripts
-
-Your integration project includes these essential scripts:
-
-```json
-{
- "register-to-team": "uniform integration definition register ./mesh-manifest.json",
- "unregister-from-team": "uniform integration definition remove your-integration-type",
- "install-to-project": "uniform integration install your-integration-type",
- "uninstall-from-project": "uniform integration uninstall your-integration-type"
-}
-```
-
-### Alternative: Manual Registration via Uniform UI
-
-If you prefer not to use CLI or don't have the environment variables set up:
-
-1. **Add Custom Integration**
- - Go to your Uniform team settings
- - Navigate to "Integrations" section
- - Click "Add Custom Integration"
- - Upload your `mesh-manifest.json` file
-
-2. **Install to Project**
- - Go to your project settings
- - Navigate to "Integrations" section
- - Find your custom integration
- - Click "Install" and configure as needed
-
-### Production Deployment
-
-1. **Deploy to Hosting Provider**
- - Deploy to Vercel, Netlify, or your preferred hosting
- - Ensure your integration is accessible via HTTPS
-
-2. **Update Manifest for Production**
- - Update `baseLocationUrl` in manifest to production URL
- - Re-register the updated manifest:
- ```bash
- npm run register-to-team
- ```
-
-3. **Test Integration**
- - Verify all locations work in production
- - Test integration functionality in Uniform dashboard
-
-## Security Considerations
-
-### API Key Management
-- Store sensitive data in integration settings, not in custom public config
-- Use `headers` array in data source configuration for authentication
-- Never expose API keys in client-side code
-
-### HTTPS Requirements
-- All production integrations must use HTTPS
-- Local development can use HTTP (localhost only)
-
-### CORS Configuration
-- Mesh integration URLs must be accessible to https://uniform.app
-- Configure appropriate CORS headers for API endpoints
-
-## Testing Strategies
-
-### Unit Testing Edgehancers
-```typescript
-// edgehancer/request.test.ts
-import { describe, it, expect } from 'vitest';
-import request from './request';
-
-describe('request edgehancer', () => {
- it('should transform response data', async () => {
- const mockContext = {
- requests: [{ url: 'https://api.example.com/data' }]
- };
-
- const result = await request(mockContext);
- expect(result[0]).toHaveProperty('processedAt');
- });
-});
-```
-
-### Integration Testing
-- Use "Test Data Type" function in Uniform dashboard
-- Test with various data configurations
-- Verify error handling and edge cases
-
-## Common Integration Patterns
-
-### CMS Integration
-- Data source for API connection configuration
-- Content type archetype for different content models
-- Field selection in type editor
-- Content picker in data editor
-
-### Asset Library Integration
-- Search and filter functionality
-- Asset transformation to Uniform format
-- Metadata preservation
-- Download/hotlinking considerations
-
-### Analytics Integration
-- Project tool for dashboard embedding
-- API proxy for secure data access
-- Real-time data updates
-- Chart and visualization components
-
-### Custom Parameter Integration
-- Specialized input components
-- Dynamic token support
-- Validation and constraints
-- Configuration options
-
-## Required Dependencies
-
-```json
-{
- "dependencies": {
- "@uniformdev/mesh-sdk-react": "latest",
- "@uniformdev/design-system": "latest",
- "next": "latest",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "typescript": "^5.0.0"
- }
-}
-```
-
-## File Structure Template
-
-```
-your-mesh-integration/
-├── pages/
-│ ├── _app.tsx
-│ ├── settings.tsx
-│ ├── data-source-editor.tsx
-│ ├── data-type-editor.tsx
-│ ├── data-resource-editor.tsx
-│ └── parameter-editor.tsx
-├── components/
-│ └── [custom-components].tsx
-├── lib/
-│ ├── types.ts
-│ ├── utils.ts
-│ └── api-client.ts
-├── edgehancer/ (optional)
-│ ├── preRequest.ts
-│ ├── request.ts
-│ └── *.test.ts
-├── mesh-manifest.json
-├── package.json
-└── tsconfig.json
-```
-
-This documentation provides the complete foundation for building Uniform Mesh integrations. Always refer to the latest Uniform documentation and SDK for any updates to the API or best practices.
-
-## Implementation guidance
-
-1. IMPORTANT: do not add anything extra to the implementation of locations that the user didn't ask for. Only add essential code that supports requested functionality.
\ No newline at end of file
diff --git a/rules/uniform-next-app-router.mdc b/rules/uniform-next-app-router.mdc
deleted file mode 100644
index 5ee5bb2..0000000
--- a/rules/uniform-next-app-router.mdc
+++ /dev/null
@@ -1,386 +0,0 @@
----
-description: Rules for Uniform SDK for Next.js App Router
-globs:
-alwaysApply: true
----
-
-# Uniform React Next App Router Developer Reference
-
-This document details how to use Uniform with React.js with Next App Router.
-
-@uniform.mdc describes general Uniform principles and practices.
-@uniform-sdk.mdc describes framework-agnostic developer principles.
-
-### Required npm packages
-
-The following npm packages must be installed to wire Uniform to Next App Router:
-
-@uniformdev/canvas-next-rsc
-@uniformdev/canvas
-
-### Uniform server config
-
-A file names `uniform.server.config.js` should exist in the root of the Next.js project with the following content:
-
-```js
-/** @type {import('@uniformdev/canvas-next-rsc/config').UniformServerConfig} */
-module.exports = {
- defaultConsent: true,
- evaluation: {
- personalization: "hybrid",
- },
- experimental: {
- quirkSerialization: true,
- },
-};
-```
-
-### Enable Uniform server config
-
-To make the configuration available in Next.js, modify the next.config.js file in the root of the project and add in `withUniformConfig`:
-
-```js
-const { withUniformConfig } = require("@uniformdev/canvas-next-rsc/config");
-
-/** @type {import('next').NextConfig} */
-const nextConfig = {
- reactStrictMode: true,
-};
-
-module.exports = withUniformConfig(nextConfig);
-```
-
-### Fetching and rendering the composition
-
-In your dynamic route file (`app/[[...path]]/page.{tsx|jsx}`), it is necessary to fetch the Uniform composition instance for the current route.
-
-```tsx
-import {
- UniformComposition,
- PageParameters,
- retrieveRoute,
-} from "@uniformdev/canvas-next-rsc";
-import { resolveComponent } from "@/uniform/resolve";
-
-export default async function Page(props: PageParameters) {
- const route = await retrieveRoute(props);
- return (
- <>
-
- >
- );
-}
-```
-
-### Wrapping page in Uniform Context
-
-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}`.
-
-```tsx
-import { UniformContext } from "@uniformdev/canvas-next-rsc";
-
-export default function RootLayout({
- children,
-}: {
- children: React.ReactNode;
-}) {
- return (
-
-
-
- {children}
-
-
-
- );
-}
-```
-
-### Rendering Uniform Components using React Components
-
-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:
-
-```tsx
-export const HeaderComponent = () => {
- return <>Header>;
-};
-```
-
-Then register it in the resolveComponent function:
-
-```tsx
-import {
- DefaultNotImplementedComponent,
- ResolveComponentFunction,
- ResolveComponentResult,
-} from "@uniformdev/canvas-next-rsc/component";
-import { HeaderComponent } from "@/components/header";
-
-export const resolveComponent: ResolveComponentFunction = ({ component }) => {
- let result: ResolveComponentResult = {
- component: DefaultNotImplementedComponent,
- };
-
- if (component.type === "header") {
- result = {
- component: HeaderComponent,
- };
- }
-
- return result;
-};
-```
-
-#### Mapping Uniform Components to React Components
-
-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:
-
-```tsx
-import { ComponentProps } from "@uniformdev/canvas-next-rsc/component";
-import {
- AssetParamValue,
- LinkParamValue,
- RichTextParamValue,
-} from "@uniformdev/canvas";
-
-type HeaderParameters = {
- textParameter?: string;
- richTextParameter?: RichTextParamValue;
- linkParameter?: LinkParamValue;
- assetParameter?: AssetParamValue;
- // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
-};
-
-type HeaderProps = ComponentProps;
-
-export const HeaderComponent = ({ textParameter }: HeaderProps) => {
- return (
- <>
- {textParameter}
- >
- );
-};
-```
-
-#### Accessing parameters
-
-IMPORTANT: When accessing component parameters, never use this way of accessing parameter values: `component?.parameters?..value`. While it works, there is a better way of destructuring the parameter name on props and accessing it directly as shown in the example below:
-
-```tsx
-import {
- ComponentProps,
- UniformText,
-} from "@uniformdev/canvas-next-rsc/component";
-
-import {
- LinkParamValue,
-} from "@uniformdev/canvas";
-
-type ComponentParameters = {
- icon?: string;
- label?: string;
- link?: LinkParamValue;
-};
-
-export const ComponentName = ({
- link,
- icon,
- label,
- component,
- context,
-}: ComponentProps) => {
- return (
-
- {icon}
-
- );
-};
-```
-
-#### Rendering child slots
-
-If a Uniform Component definition has slots defined, the components in those slots can be rendered using the `UniformSlot` component.
-
-```tsx
-import {
- ComponentProps,
- UniformSlot,
-} from "@uniformdev/canvas-next-rsc/component";
-import { RichTextParamValue } from "@uniformdev/canvas";
-
-type HeaderParameters = {
- textParameter?: string;
- richTextParameter?: RichTextParamValue;
- // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
-};
-type HeaderSlots = "logo" | "navigation";
-
-type HeaderProps = ComponentProps;
-
-export const HeaderComponent = ({ slots, context, component }: HeaderProps) => {
- return (
- <>
-
-
- >
- );
-};
-```
-
-#### Rendering parameter values
-
-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:
-
-```tsx
-import {
- ComponentProps,
- UniformText,
-} from "@uniformdev/canvas-next-rsc/component";
-import { RichTextParamValue } from "@uniformdev/canvas";
-
-type HeaderParameters = {
- textParameter?: string;
- richTextParameter?: RichTextParamValue;
- // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
-};
-
-type HeaderProps = ComponentProps;
-
-export const HeaderComponent = ({ component, context }: HeaderProps) => {
- return (
- <>
-
- >
- );
-};
-```
-
-For rich text parameters, the `UniformRichText` component will automatically render the rich text stored as JSON to HTML:
-
-```tsx
-import {
- ComponentProps,
- UniformRichText,
-} from "@uniformdev/canvas-next-rsc/component";
-import { RichTextParamValue } from "@uniformdev/canvas";
-
-type HeaderParameters = {
- textParameter?: string;
- richTextParameter?: RichTextParamValue;
- // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
-};
-
-type HeaderProps = ComponentProps;
-
-export const HeaderComponent = ({ component, context }: HeaderProps) => {
- return (
- <>
-
- >
- );
-};
-```
-
-Note: asset parameters are rendered directly from props, there is no `UniformAsset` component.
-
-##### Asset parameters/fields
-
-1. CRITICAL: Always use `flattenValues` from `@uniformdev/canvas` for handling asset parameters, not custom utility functions.
-2. CRITICAL: Destructure asset parameters directly from component props (e.g., `{ logos, component, context }`) rather than accessing through `component?.parameters?.parameterName`.
-3. Use `flattenValues(assetParam)` directly - it handles both single and multiple assets automatically.
-
-```tsx
-import { AssetParamValue, flattenValues } from "@uniformdev/canvas";
-
-interface MyComponentProps {
- multipleImagesAssetParam: AssetParamValue;
- singleImageAssetParam: AssetParamValue;
-}
-
-function MyComponent({
- multipleImagesAssetParam,
- singleImageAssetParam,
-}: MyComponentProps) {
- // when multiple assets are allowed, flatten to an array
- const images = flattenValues(multipleImagesAssetParam);
- // when only one asset is allowed, flatten to a single object
- const image = flattenValues(singleImageAssetParam, { toSingle: true });
-
- return (
- <>
- {images?.map((img, index) => (
-
- ))}
-
- >
- );
-}
-```
-
-4. Do NOT create custom utility functions like `getAssetValues` when `flattenValues` already exists and works perfectly.
-
-### Configuring Contextual Editing Live Preview
-
-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.
-
-`app/api/preview/route.ts`:
-
-```tsx
-import {
- createPreviewGETRouteHandler,
- createPreviewPOSTRouteHandler,
- createPreviewOPTIONSRouteHandler,
-} from "@uniformdev/canvas-next-rsc/handler";
-
-export const GET = createPreviewGETRouteHandler({
- playgroundPath: "/playground",
- resolveFullPath: ({ path }) => (path ? path : "/playground"),
-});
-export const POST = createPreviewPOSTRouteHandler();
-export const OPTIONS = createPreviewOPTIONSRouteHandler();
-```
-
-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:
-
-`app/playground/page.tsx`:
-
-```tsx
-import {
- UniformPlayground,
- UniformPlaygroundProps,
-} from "@uniformdev/canvas-next-rsc";
-import { resolveComponent } from "@/uniform/resolve";
-
-export default function PlaygroundPage(props: {
- searchParams: UniformPlaygroundProps["searchParams"];
-}) {
- return ;
-}
-```
-
-## Uniform manifest usage
-
-1. CRITICAL! If using Next.js App Router, you must ignore adding the following commands specific to Uniform manifest. This is for Next.js page router only.
-```bash
- "uniform:manifest": "uniform context manifest download --output ./lib/uniform/contextManifest.json",
- "uniform:publish": "uniform context manifest publish"
-```
diff --git a/rules/uniform-next-page-router.mdc b/rules/uniform-next-page-router.mdc
deleted file mode 100644
index 63fe9a1..0000000
--- a/rules/uniform-next-page-router.mdc
+++ /dev/null
@@ -1,320 +0,0 @@
----
-description:
-globs:
-alwaysApply: true
----
-
-[uniform.mdc](mdc:.cursor/rules/uniform.mdc) describes general Uniform principles and practices.
-[uniform-sdk.mdc](mdc:.cursor/rules/uniform-sdk.mdc) describes framework-agnostic developer principles.
-
-### Required npm packages
-
-The following npm packages must be installed to wire Uniform CMS to Next Page Router:
-
-@uniformdev/canvas
-@uniformdev/canvas-react
-@uniformdev/canvas-next
-@uniformdev/context-react
-
-### Fetching and rendering the composition
-
-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:
-
-```tsx
-import type { UniformCompositionNextPage } from "@uniformdev/canvas-next";
-import { withUniformGetServerSideProps } from "@uniformdev/canvas-next/route";
-import { UniformComposition } from "@uniformdev/canvas-react";
-
-// fetch the composition using SSR
-export const getServerSideProps = withUniformGetServerSideProps();
-
-// the function provides the composition to the route component as the `data` prop
-// the UniformCompositionNextPage type provides typings to make sure that is clear
-const page: UniformCompositionNextPage = ({ data }) => {
- // the UniformComposition component takes over rendering the components on the composition data
- return ;
-};
-
-export { page as default };
-```
-
-### Rendering Uniform Components using React Components
-
-> IMPORTANT: before generating Uniform component code, always fetch available component definitions from Uniform to be aware of the schema.
-
-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:
-
-`components/Hero.tsx`:
-
-```tsx
-import { registerUniformComponent } from "@uniformdev/canvas-react";
-
-function Hero() {
- return
Hero Component Content
;
-}
-
-registerUniformComponent({
- type: "hero",
- component: Hero,
-});
-```
-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.
-
-#### Mapping Uniform Components to React Components
-
-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:
-
-```tsx
-import {
- AssetParamValue,
- LinkParamValue,
- RichTextParamValue,
-} from "@uniformdev/canvas";
-
-type HeroProps = ComponentProps<{
- textParameter?: string;
- richTextParameter?: RichTextParamValue;
- linkParameter?: LinkParamValue;
- assetParameter?: AssetParamValue;
- // it is critical that all parameter props values are optional, because they can be undefined - even if 'required' on the component definition
-}>;
-
-function Hero(props: HeroProps) {
- return
{props.textParameter}
;
-}
-```
-
-#### Rendering child slots
-
-If a Uniform Component definition has slots defined, the components in those slots can be rendered using the `UniformSlot` component.
-
-```tsx
-import { UniformSlot } from "@uniformdev/canvas-react";
-
-function Hero() {
- return (
-
-
-
-
-
-
-
-
- );
-}
-```
-
-#### Rendering parameter/field values
-
-##### Text parameters/fields
-
-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:
-
-```tsx
-import { UniformText } from "@uniformdev/canvas-react";
-
-function Hero() {
- return (
-
- {/* always specify placeholder text that an author will see in the visual editor when the value is empty */}
-
- {/* 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 */}
-
-
- );
-}
-```
-
-##### Rich text parameters/fields
-
-For richText parameters, always use the `UniformRichText` component to automatically render the rich text (stored as Lexical JSON) to HTML:
-
-```tsx
-import { UniformRichText } from "@uniformdev/canvas-react";
-
-function Hero() {
- return (
-
-
-
- );
-}
-```
-
-##### Asset parameters/fields
-
-When rendering asset parameters, use the `flattenValues` helper to simplify value access:
-
-```tsx
-import { AssetParamValue, flattenValues } from "@uniformdev/canvas";
-
-interface MyComponentProps {
- multipleImagesAssetParam: AssetParamValue;
- singleImageAssetParam: AssetParamValue;
-}
-
-function MyComponent({
- multipleImagesAssetParam,
- singleImageAssetParam,
-}: MyComponentProps) {
- // when multiple assets are allowed, flatten to an array
- const images = flattenValues(multipleImagesAssetParam);
- // when only one asset is allowed, flatten to a single object
- const image = flattenValues(singleImageAssetParam, { toSingle: true });
-
- return (
- <>
- {images?.map((img, index) => (
-
- ))}
-
- >
- );
-}
-```
-
-### Configuring Contextual Editing Live Preview
-
-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.
-
-`pages/api/preview.ts`:
-
-```tsx
-import { createPreviewHandler } from "@uniformdev/canvas-next";
-
-const handler = createPreviewHandler({
- // this is set in .env to an arbitrary value
- secret: () => process.env.UNIFORM_PREVIEW_SECRET,
- // optionally configure the playground route to enable previewing patterns
- playgroundPath: "/playground",
-});
-
-export default handler;
-```
-
-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:
-
-`pages/playground.tsx`:
-
-```tsx
-import { UniformPlayground } from "@uniformdev/canvas-react";
-
-export default function Playground() {
- // wrap UniformPlayground in your page shell/styles to wrap the pattern previews with
- return ;
-}
-```
-
-## Configuring Personalization and A/B Testing (Uniform Context)
-
-### Required Context Packages
-
-The following npm packages must be installed to enable Uniform Context on Next Page Router:
-
-@uniformdev/context
-@uniformdev/context-next
-@uniformdev/context-react
-@uniformdev/cli (IMPORTANT: this package must be installed as a devDependency)
-
-### Pulling the Uniform Context Manifest
-
-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:
-
-```json
-"uniform:pull:manifest": "uniform context manifest download --output ./src/uniform/contextManifest.json"
-```
-The "dev" and "build" npm scripts should run "uniform:pull:manifest" before beginning their regular tasks.
-
-### Enable Uniform Context SDK
-
-In order to initialize Uniform Context, we need to configure it and provide the manifest to it:
-
-`src/uniform/createUniformContext.ts`:
-
-```tsx
-import {
- Context,
- ManifestV2,
- ContextPlugin,
- enableDebugConsoleLogDrain,
- enableContextDevTools
-} from "@uniformdev/context";
-import { NextCookieTransitionDataStore } from "@uniformdev/context-next";
-import { NextPageContext } from "next";
-import manifest from "./contextManifest.json";
-
-export function createUniformContext(
- serverContext?: NextPageContext
-): Context {
- const plugins: ContextPlugin[] = [
- // optional, but smart defaults to help with debugging setup
- enableContextDevTools(),
- enableDebugConsoleLogDrain("debug"),
- ];
-
- const context = new Context({
- // disables needing visitor consent before storing data (for testing)
- defaultConsent: true,
- manifest: manifest as ManifestV2,
- transitionStore: new NextCookieTransitionDataStore({
- serverContext,
- }),
- plugins,
- });
-
- return context;
-}
-```
-
-The context instance must then be provided to the `_app.tsx` so Uniform knows about it when rendering:
-
-`pages/_app.tsx`:
-```tsx
-import { UniformContext } from "@uniformdev/context-react";
-import { UniformAppProps } from "@uniformdev/context-next";
-import { createUniformContext } from "../uniform/createUniformContext";
-
-const clientContext = createUniformContext();
-
-function MyApp({
- Component,
- pageProps,
- serverUniformContext,
-}: UniformAppProps) {
- return (
-
-
-
- );
-}
-
-export default MyApp;
-```
-
-We must also configure the server-side Uniform Context instance when using server-side rendering:
-
-`pages/_document.tsx`:
-```tsx
-import { enableNextSsr } from "@uniformdev/context-next";
-import { createUniformContext } from "../uniform/uniformContext";
-
- // required to enable SSR personalization
- static async getInitialProps(
- ctx: DocumentContext
- ): Promise {
- const serverTracker = createUniformContext(ctx);
- enableNextSsr(ctx, serverTracker);
- return await Document.getInitialProps(ctx);
- }
-```
-
-CRITICAL! Ignore this if using Next.js app router. This is for page router only. When adding Uniform SDK only for Next.js page router, always add these npm scripts to package.json. Adapt the path to `contextManifest.json` as needed. Add `uniform:manifest` to the `dev` and `build` scripts so it is running before the dev server starts or before production build runs.
-
-```bash
- "uniform:manifest": "uniform context manifest download --output ./lib/uniform/contextManifest.json",
- "uniform:publish": "uniform context manifest publish"
-```
diff --git a/rules/uniform-sveltekit.mdc b/rules/uniform-sveltekit.mdc
deleted file mode 100644
index a087244..0000000
--- a/rules/uniform-sveltekit.mdc
+++ /dev/null
@@ -1,592 +0,0 @@
----
-description: Uniform SDK integration guide for SvelteKit applications. Use when integrating Uniform Canvas, Context, and personalization into a SvelteKit project.
-globs:
-alwaysApply: true
----
-
-[uniform.mdc](mdc:.cursor/rules/uniform.mdc) describes general Uniform principles and practices.
-[uniform-sdk.mdc](mdc:.cursor/rules/uniform-sdk.mdc) describes framework-agnostic developer principles.
-
-## Required npm packages
-
-The following npm packages must be installed to wire Uniform CMS to SvelteKit:
-
-### Core Canvas packages
-- `@uniformdev/canvas` - Core Canvas API client for fetching compositions
-- `@uniformdev/canvas-svelte` - Svelte components: `UniformComposition`, `UniformSlot`, `UniformText`, `UniformRichText`
-- `@uniformdev/canvas-sveltekit` - SvelteKit integrations: `createUniformLoad`, `createUniformHandle`, preview handler, ISR config
-
-### Core Context packages (for personalization)
-- `@uniformdev/context` - Personalization Context engine
-- `@uniformdev/context-svelte` - `UniformContext` provider component
-
-### Edge personalization packages (optional, for production)
-- `@uniformdev/context-edge` - Edge-side context processing
-- `@uniformdev/context-edge-sveltekit` - NESI response handler for edge personalization
-- `@vercel/functions` - Vercel edge functions support
-- `cookie` - Cookie parsing utility
-
-### Dev dependencies
-- `@uniformdev/cli` - CLI for pulling manifests and syncing content (IMPORTANT: must be installed as devDependency)
-
-## Configuring TypeScript Types
-
-Update `src/app.d.ts` to include Uniform preview data types:
-
-```typescript
-import type { UniformPreviewData } from '@uniformdev/canvas-sveltekit';
-
-declare global {
- namespace App {
- interface Locals {
- uniformPreview?: UniformPreviewData;
- }
- }
-}
-
-export {};
-```
-
-## Component Mapping
-
-Create `src/lib/uniform/componentMap.ts` to map Uniform component types to Svelte components:
-
-```typescript
-import type { ComponentMap } from '@uniformdev/canvas-svelte';
-import Hero from '$lib/components/Hero.svelte';
-import Page from '$lib/components/Page.svelte';
-
-/**
- * Maps Uniform component types to Svelte components.
- * The key is the component type from Uniform Canvas.
- * Use `type__variant` format to map specific variants.
- */
-export const componentMap: ComponentMap = {
- page: Page,
- hero: Hero,
- // Variant example: card__featured uses same component with variant styling
- // card__featured: Card,
-};
-```
-
-## Server Hooks Configuration
-
-Create `src/hooks.server.ts` to handle Uniform preview cookies:
-
-```typescript
-import { sequence } from '@sveltejs/kit/hooks';
-import { createUniformHandle } from '@uniformdev/canvas-sveltekit';
-
-const uniformHandle = createUniformHandle({
- onPreview: (event, previewData) => {
- if (previewData.isUniformContextualEditing) {
- console.log('[Uniform] Contextual editing mode active for:', previewData.compositionPath);
- }
- },
-});
-
-export const handle = sequence(uniformHandle);
-```
-
-## Root Layout with Context Provider
-
-Update `src/routes/+layout.svelte` to initialize Uniform Context:
-
-```svelte
-
-
-
- {@render children()}
-
-```
-
-**Important:** The `outputType` prop controls personalization rendering:
-- `standard`: Used in development - personalization happens client-side
-- `edge`: Used in production - outputs NESI placeholders that the edge middleware replaces
-
-## Catch-All Route for Compositions
-
-### Server Load Function
-
-Create `src/routes/[...path]/+page.server.ts` to fetch compositions:
-
-```typescript
-import { error } from '@sveltejs/kit';
-import { RouteClient } from '@uniformdev/canvas';
-import { env } from '$env/dynamic/private';
-import type { PageServerLoad } from './$types';
-
-// Optional: ISR on Vercel
-import { createVercelIsrConfig } from '@uniformdev/canvas-sveltekit';
-export const config = createVercelIsrConfig({ expiration: 60 });
-
-function hasUniformCredentials(): boolean {
- return Boolean(env.UNIFORM_API_KEY && env.UNIFORM_PROJECT_ID);
-}
-
-export const load: PageServerLoad = async (event) => {
- if (!hasUniformCredentials()) {
- error(500, 'Uniform credentials not configured. Set UNIFORM_API_KEY and UNIFORM_PROJECT_ID in your .env file.');
- }
-
- // Lazy import to avoid initialization errors when credentials are missing
- const { createUniformLoad } = await import('@uniformdev/canvas-sveltekit/route');
-
- const client = new RouteClient({
- apiKey: env.UNIFORM_API_KEY,
- projectId: env.UNIFORM_PROJECT_ID,
- });
-
- const uniformLoad = createUniformLoad({
- client,
- projectMapId: env.UNIFORM_PROJECT_MAP_ID,
- param: 'path', // Matches [...path]
- });
-
- return uniformLoad(event);
-};
-```
-
-### Page Component
-
-Create `src/routes/[...path]/+page.svelte` to render compositions:
-
-```svelte
-
-
-
-
-
-```
-
-### Error Page
-
-Create `src/routes/[...path]/+error.svelte`:
-
-```svelte
-
-
-
-
-
-```
-
-## Rendering Uniform Components with Svelte
-
-> IMPORTANT: before generating Uniform component code, always fetch available component definitions from Uniform to be aware of the schema.
-
-### Component Props Typing
-
-Use `ComponentProps` for type-safe parameter access. All parameter props must be optional since they can be undefined:
-
-```svelte
-
-```
-
-### Text Parameters
-
-Always use `UniformText` for editable text parameters. This enables inline editing in Canvas:
-
-```svelte
-
-
-
-
-
-
-
-```
-
-Text parameters without visible components (e.g., alt text) should use raw values.
-
-### Rich Text Parameters
-
-Always use `UniformRichText` for rich text parameters (stored as Lexical JSON):
-
-```svelte
-
-
-
-```
-
-### Slots
-
-Use `UniformSlot` to render nested child components from composition slots:
-
-```svelte
-
-
-
- {#if showCta}
-
- {/if}
-
-```
-
-## Edge Personalization (Production)
-
-For production edge personalization with NESI (Nested Edge-Side Includes), create `middleware.ts` in the project root:
-
-```typescript
-import {
- Context,
- CookieTransitionDataStore,
- UNIFORM_DEFAULT_COOKIE_NAME,
-} from '@uniformdev/context';
-import { createUniformNesiResponseHandler } from '@uniformdev/context-edge-sveltekit';
-import { next } from '@vercel/functions';
-import { parse } from 'cookie';
-import type { ManifestV2 } from '@uniformdev/context';
-import manifestJson from './src/lib/uniform/contextManifest.json';
-
-const manifest = manifestJson as ManifestV2;
-
-export default async function middleware(request: Request) {
- // Skip subrequests from this middleware
- if (request.headers.get('x-from-middleware') === 'true') {
- return next(request);
- }
-
- const url = new URL(request.url);
- const cookieValue = request.headers.get('cookie');
- const cookies = parse(cookieValue ?? '');
-
- const context = new Context({
- manifest: manifest as ManifestV2,
- defaultConsent: true,
- transitionStore: new CookieTransitionDataStore({
- serverCookieValue: cookies[UNIFORM_DEFAULT_COOKIE_NAME] ?? undefined,
- }),
- });
-
- await context.update({ cookies, url });
-
- const response = await fetch(url, {
- headers: { 'x-from-middleware': 'true' },
- });
-
- const handler = createUniformNesiResponseHandler();
- return handler({ response, context });
-}
-
-export const config = {
- matcher: [
- '/((?!_app|__data\\.json|@vite|@id|@fs|_next|.*\\..*|favicon\\.ico).*)',
- ],
-};
-```
-
-**Note:** The `@uniformdev/context-edge-sveltekit` package requires an NPM token. Create `.npmrc`:
-
-```
-//registry.npmjs.org/:_authToken=${NPM_TOKEN}
-```
-
-## CLI Configuration and Scripts
-
-### uniform.config.ts
-
-```typescript
-import { uniformConfig } from '@uniformdev/cli/config';
-
-export default uniformConfig({ preset: 'all', disableEntities: ['webhook'] });
-```
-
-### Package.json scripts
-
-Add these npm scripts:
-
-```json
-{
- "scripts": {
- "dev": "pnpm pull:manifest && vite dev",
- "build": "pnpm pull:manifest && vite build",
- "pull:manifest": "uniform context manifest download --output ./src/lib/uniform/contextManifest.json",
- "pull:content": "uniform sync pull",
- "push:content": "uniform sync push"
- }
-}
-```
-
-### Placeholder manifest
-
-Create `src/lib/uniform/contextManifest.json`:
-
-```json
-{
- "project": {}
-}
-```
-
-Add to `src/lib/uniform/.gitignore`:
-
-```
-contextManifest.json
-```
-
-## Environment Variables
-
-Required `.env` configuration:
-
-```bash
-UNIFORM_API_KEY= # From Uniform dashboard
-UNIFORM_PROJECT_ID= # Your Uniform project ID
-UNIFORM_PROJECT_MAP_ID= # Optional - uses default if not set
-UNIFORM_PREVIEW_SECRET=hello-world # Secret for preview validation
-```
-
-## Vercel Adapter Configuration
-
-For Vercel deployments, update `svelte.config.js`:
-
-```javascript
-import adapter from '@sveltejs/adapter-vercel';
-
-/** @type {import('@sveltejs/kit').Config} */
-const config = {
- kit: {
- adapter: adapter(),
- },
-};
-
-export default config;
-```
-
-## Project Structure Reference
-
-```
-your-project/
-├── src/
-│ ├── app.d.ts # TypeScript declarations
-│ ├── app.html # HTML template
-│ ├── hooks.server.ts # Server hooks
-│ ├── lib/
-│ │ ├── components/ # Svelte components
-│ │ │ ├── Hero.svelte
-│ │ │ ├── Page.svelte
-│ │ │ └── index.ts
-│ │ └── uniform/
-│ │ ├── componentMap.ts # Component type mapping
-│ │ ├── contextManifest.json # Generated by CLI
-│ │ └── .gitignore
-│ └── routes/
-│ ├── +layout.svelte # Root layout with UniformContext
-│ ├── [...path]/
-│ │ ├── +page.server.ts # Fetches compositions
-│ │ ├── +page.svelte # Renders compositions
-│ │ └── +error.svelte
-│ ├── playground/
-│ │ └── +page.svelte
-│ └── preview/
-│ └── +server.ts
-├── middleware.ts # Edge middleware (optional)
-├── uniform.config.ts # CLI configuration
-├── package.json
-├── svelte.config.js
-├── vite.config.ts
-└── .env
-```
-
-## Key Differences from Next.js
-
-| Aspect | Next.js Page Router | SvelteKit |
-|--------|---------------------|-----------|
-| Component registration | `registerUniformComponent()` | `componentMap` object |
-| SSR data loading | `withUniformGetServerSideProps()` | `createUniformLoad()` in `+page.server.ts` |
-| Preview handler | `pages/api/preview.ts` | `src/routes/preview/+server.ts` |
-| Server hooks | `_app.tsx` / `_document.tsx` | `hooks.server.ts` |
-| Context provider | HOC in `_app.tsx` | `UniformContext` in `+layout.svelte` |
-| Props pattern | `ComponentProps` generic | `ComponentProps` with `$props()` |
-| Reactivity | React hooks | Svelte runes (`$derived`, `$props`) |
-
-## Troubleshooting
-
-### Common Issues
-
-1. **"Cannot find module contextManifest.json"**
- - Run `pnpm pull:manifest` to download the manifest
- - Ensure valid `UNIFORM_API_KEY` and `UNIFORM_PROJECT_ID` are set
-
-2. **Preview not working**
- - Verify preview URL is configured in Uniform Canvas settings
- - Check `UNIFORM_PREVIEW_SECRET` matches in both places
- - Consult [troubleshooting guide](https://docs.uniform.app/docs/guides/composition/visual-editing/troubleshoot-preview)
-
-3. **Components not rendering**
- - Verify component type names in `componentMap` match Uniform Canvas
- - Check browser console for mapping errors
-
-4. **TypeScript errors with slots**
- - Ensure `UniformSlot` name matches the slot name in Uniform Canvas
-
-5. **Edge personalization not working**
- - Confirm `outputType="edge"` is set in production layout
- - Verify middleware is correctly deployed and matching paths
diff --git a/uniform-rules/.cursor-plugin/plugin.json b/uniform-rules/.cursor-plugin/plugin.json
new file mode 100644
index 0000000..61e9d62
--- /dev/null
+++ b/uniform-rules/.cursor-plugin/plugin.json
@@ -0,0 +1,9 @@
+{
+ "name": "uniform-rules",
+ "version": "1.0.0",
+ "description": "Uniform CMS rules for AI-assisted development: compositions, components, patterns, SDK, and framework guides",
+ "author": {
+ "name": "AI Rules"
+ },
+ "keywords": ["uniform", "cms", "headless", "canvas", "sveltekit", "next", "mesh"]
+}
diff --git a/uniform-rules/README.md b/uniform-rules/README.md
new file mode 100644
index 0000000..294b0b3
--- /dev/null
+++ b/uniform-rules/README.md
@@ -0,0 +1,16 @@
+# Uniform Rules
+
+Cursor plugin that provides Uniform CMS rules for AI-assisted development.
+
+## Contents
+
+- **uniform.mdc** – Core concepts: compositions, components, patterns, entries, content types, assets, localization
+- **uniform-sdk.mdc** – SDK: auth, routing, CLI, frontend integration
+- **uniform-sveltekit.mdc** – SvelteKit: packages, component mapping, hooks, preview, edge personalization
+- **uniform-next-app-router.mdc** – Next.js App Router
+- **uniform-next-page-router.mdc** – Next.js Page Router
+- **uniform-mesh.mdc** – Mesh integrations: manifest, locations, data connectors
+
+## Usage
+
+Install this plugin via the Cursor marketplace or from this repo. Use when building or maintaining projects that use Uniform CMS (Canvas, Context, Mesh).
diff --git a/rules/optional-personal-preference/solution-architecture.mdc b/uniform-rules/rules/solution-architecture.mdc
similarity index 93%
rename from rules/optional-personal-preference/solution-architecture.mdc
rename to uniform-rules/rules/solution-architecture.mdc
index d35d08d..9f880c4 100644
--- a/rules/optional-personal-preference/solution-architecture.mdc
+++ b/uniform-rules/rules/solution-architecture.mdc
@@ -1,5 +1,5 @@
---
-description:
+description: Optional coding standards and Uniform practices (React, Tailwind, slots, patterns)
globs:
alwaysApply: false
---
@@ -17,13 +17,13 @@ alwaysApply: false
# Uniform practices
-1. CRITICAL: Always create a component pattern when pushing a new component to Uniform project and fill it with content using previous examples of this component usage if possible. If not, generate content for component pattern yourself.
+1. CRITICAL: Always create a component pattern when pushing a new component to Uniform project and fill it with content using previous examples of this component usage if possible. If not, generate content for component pattern yourself.
2. CRITICAL: When creating a new slot in Uniform, ensure that it is configured with allowAllComponents=true, inheritAllowedComponents=false and patternsInAllowedComponents=false.
3. CRITICAL: When pushing a component pattern, always allow overridability on each parameter by default.
-4. CRITICAL: When registering components with Uniform and spotting repeated properties, always resort to modeling repeated set of properties as child components and create `` to render those. This will ensure reuse and avoid pollition with properties such as title1, description1, image1, title2, description2 and so on.
+4. CRITICAL: When registering components with Uniform and spotting repeated properties, always resort to modeling repeated set of properties as child components and create `` to render those. This will ensure reuse and avoid pollution with properties such as title1, description1, image1, title2, description2 and so on.
# Environment variables
diff --git a/uniform-rules/rules/uniform-mesh.mdc b/uniform-rules/rules/uniform-mesh.mdc
new file mode 100644
index 0000000..c1b5ca3
--- /dev/null
+++ b/uniform-rules/rules/uniform-mesh.mdc
@@ -0,0 +1,31 @@
+---
+description: Uniform Mesh integrations - custom web apps extending the Uniform UI and data connectors
+globs:
+alwaysApply: true
+---
+
+# Uniform Mesh Integrations
+
+Uniform Mesh extends the Uniform UI with custom web applications. Integrations run on URLs you host and communicate with the Uniform dashboard via iframe messaging.
+
+## Core stack
+
+- **Framework**: Next.js with page router (recommended)
+- **SDK**: `@uniformdev/mesh-sdk-react`
+- **Design**: `@uniformdev/design-system`
+- **CLI**: `@uniformdev/cli` (register in team, install in project)
+- **Language**: TypeScript (recommended)
+
+## Manifest (mesh-manifest.json)
+
+Required: `type`, `displayName`, `baseLocationUrl`, `locations`. Optional: `logoIconUrl`, `badgeIconUrl`, `category`, `scopes`.
+
+## Location types
+
+- **Install**: Shown when installing; configure in manifest (description, informationUrl).
+- **Settings**: Integration-wide config; use `useMeshLocation<'settings'>` with value/setValue.
+- **Data Connectors**: Data Source Editor (connection settings, secure storage), Data Type Editor (path, parameters), Data Resource Editor (object search). Do not store secrets in Data Type; use Data Source for credentials.
+
+## Implementation
+
+Use `useMeshLocation()` for value and setValue. Use design-system components for consistent UI. Locations receive **value** (editable) and **metadata** (read-only).
diff --git a/uniform-rules/rules/uniform-next-app-router.mdc b/uniform-rules/rules/uniform-next-app-router.mdc
new file mode 100644
index 0000000..0341c62
--- /dev/null
+++ b/uniform-rules/rules/uniform-next-app-router.mdc
@@ -0,0 +1,32 @@
+---
+description: Rules for Uniform SDK for Next.js App Router
+globs: "**/*.{tsx,jsx}"
+alwaysApply: true
+---
+
+# Uniform React Next App Router
+
+See uniform.mdc for general Uniform principles and practices.
+See uniform-sdk.mdc for framework-agnostic developer principles.
+
+## Required npm packages
+
+- `@uniformdev/canvas-next-rsc`
+- `@uniformdev/canvas`
+
+## Config
+
+- Add `uniform.server.config.js` in project root (defaultConsent, evaluation, experimental).
+- Wrap Next config with `withUniformConfig()` from `@uniformdev/canvas-next-rsc/config`.
+
+## Fetching and rendering
+
+In `app/[[...path]]/page.{tsx|jsx}` use `retrieveRoute(props)` and render with `UniformComposition` from `@uniformdev/canvas-next-rsc` and `resolveComponent` for mapping. Use `mode="server"`.
+
+## Layout
+
+Wrap `{children}` in `UniformContext` from `@uniformdev/canvas-next-rsc` in `app/layout.tsx` for personalization and A/B testing.
+
+## Component registration
+
+Use `resolveComponent` (or equivalent) to map Uniform component types to React components. Create a component for every composition component in the Uniform project and add slots as in the definition.
diff --git a/uniform-rules/rules/uniform-next-page-router.mdc b/uniform-rules/rules/uniform-next-page-router.mdc
new file mode 100644
index 0000000..44bd030
--- /dev/null
+++ b/uniform-rules/rules/uniform-next-page-router.mdc
@@ -0,0 +1,25 @@
+---
+description: Rules for Uniform SDK for Next.js Page Router
+globs: "**/*.{tsx,jsx}"
+alwaysApply: true
+---
+
+# Uniform Next.js Page Router
+
+See uniform.mdc for general Uniform principles and practices.
+See uniform-sdk.mdc for framework-agnostic developer principles.
+
+## Required npm packages
+
+- `@uniformdev/canvas`
+- `@uniformdev/canvas-react`
+- `@uniformdev/canvas-next`
+- `@uniformdev/context-react`
+
+## Fetching and rendering
+
+In `pages/[[...path]].{tsx|jsx}` use `withUniformGetServerSideProps()` for SSR and pass `data` to `UniformComposition` from `@uniformdev/canvas-react`. Type the page with `UniformCompositionNextPage`.
+
+## Component registration
+
+Use `registerUniformComponent({ type, component })` from `@uniformdev/canvas-react`. Import registrations in `_app.tsx` so they run. Use `ComponentProps` for parameter typing; all parameter props optional. Use `UniformSlot` for child slots.
diff --git a/rules/uniform-sdk.mdc b/uniform-rules/rules/uniform-sdk.mdc
similarity index 96%
rename from rules/uniform-sdk.mdc
rename to uniform-rules/rules/uniform-sdk.mdc
index e2b62b3..da2dc41 100644
--- a/rules/uniform-sdk.mdc
+++ b/uniform-rules/rules/uniform-sdk.mdc
@@ -1,13 +1,13 @@
---
-description:
-globs:
+description: Uniform SDK developer reference - auth, routing, CLI, frontend integration
+globs:
alwaysApply: true
---
# Uniform SDK Developer Reference
This document details general information and practices about how Uniform works for developers writing frontend applications.
-[uniform.mdc](mdc:.cursor/rules/uniform.mdc) describes general Uniform principles and practices.
+See uniform.mdc for general Uniform principles and practices.
## Authenticating to Uniform
@@ -104,4 +104,4 @@ The Uniform CLI has a built-in help system. To get help on a command, run `unifo
## Must-have rules to follow when adding Uniform SDK
-1. Make sure to create a component in code for any composition component you find in the Uniform project automatically. Add any slots that you find in the definition. This will ensure the preview works as expected; otherwise, it won't know which front-end component should render the composition from Uniform and produce an error.
+1. Make sure to create a component in code for any composition component you find in the Uniform project automatically. Add any slots that you find in the definition. This will ensure the preview works as expected; otherwise, it won't know which front-end component should render the composition from Uniform and produce an error.
diff --git a/uniform-rules/rules/uniform-sveltekit.mdc b/uniform-rules/rules/uniform-sveltekit.mdc
new file mode 100644
index 0000000..19009db
--- /dev/null
+++ b/uniform-rules/rules/uniform-sveltekit.mdc
@@ -0,0 +1,76 @@
+---
+description: Uniform SDK integration guide for SvelteKit applications. Use when integrating Uniform Canvas, Context, and personalization into a SvelteKit project.
+globs:
+alwaysApply: true
+---
+
+See uniform.mdc for general Uniform principles and practices.
+See uniform-sdk.mdc for framework-agnostic developer principles.
+
+## Required npm packages
+
+The following npm packages must be installed to wire Uniform CMS to SvelteKit:
+
+### Core Canvas packages
+- `@uniformdev/canvas` - Core Canvas API client for fetching compositions
+- `@uniformdev/canvas-svelte` - Svelte components: `UniformComposition`, `UniformSlot`, `UniformText`, `UniformRichText`
+- `@uniformdev/canvas-sveltekit` - SvelteKit integrations: `createUniformLoad`, `createUniformHandle`, preview handler, ISR config
+
+### Core Context packages (for personalization)
+- `@uniformdev/context` - Personalization Context engine
+- `@uniformdev/context-svelte` - `UniformContext` provider component
+
+### Edge personalization packages (optional, for production)
+- `@uniformdev/context-edge` - Edge-side context processing
+- `@uniformdev/context-edge-sveltekit` - NESI response handler for edge personalization
+- `@vercel/functions` - Vercel edge functions support
+- `cookie` - Cookie parsing utility
+
+### Dev dependencies
+- `@uniformdev/cli` - CLI for pulling manifests and syncing content (IMPORTANT: must be installed as devDependency)
+
+## Configuring TypeScript Types
+
+Update `src/app.d.ts` to include Uniform preview data types:
+
+```typescript
+import type { UniformPreviewData } from '@uniformdev/canvas-sveltekit';
+
+declare global {
+ namespace App {
+ interface Locals {
+ uniformPreview?: UniformPreviewData;
+ }
+ }
+}
+
+export {};
+```
+
+## Component Mapping
+
+Create `src/lib/uniform/componentMap.ts` to map Uniform component types to Svelte components. Use `type__variant` format for variants. Register all composition components so preview works.
+
+## Server Hooks and Catch-All Route
+
+- Use `createUniformHandle` from `@uniformdev/canvas-sveltekit` in `src/hooks.server.ts` for preview cookies.
+- Use `createUniformLoad` in `src/routes/[...path]/+page.server.ts` with `RouteClient` to fetch compositions.
+- Render with `UniformComposition` and `UniformSlot` in `+page.svelte`.
+
+## Preview Handler
+
+Create `src/routes/preview/+server.ts` with `createPreviewHandler` from `@uniformdev/canvas-sveltekit/preview`.
+
+## Rendering Uniform Components with Svelte
+
+- Use `ComponentProps` for type-safe parameter access; all parameter props must be optional.
+- Use `UniformText` for editable text parameters, `UniformRichText` for rich text (Lexical JSON), `UniformSlot` for nested slots.
+- Use `flattenValues` from `@uniformdev/canvas` for asset parameters.
+
+## Environment Variables
+
+Required: `UNIFORM_API_KEY`, `UNIFORM_PROJECT_ID`, `UNIFORM_PROJECT_MAP_ID` (optional), `UNIFORM_PREVIEW_SECRET`.
+
+## CLI
+
+Use `uniform.config.ts` with `uniformConfig({ preset: 'all' })`. Add scripts: `uniform:pull`, `uniform:push`, `pull:manifest` for context manifest.
diff --git a/rules/uniform.mdc b/uniform-rules/rules/uniform.mdc
similarity index 98%
rename from rules/uniform.mdc
rename to uniform-rules/rules/uniform.mdc
index 0ae81f7..5efe101 100644
--- a/rules/uniform.mdc
+++ b/uniform-rules/rules/uniform.mdc
@@ -1,6 +1,6 @@
---
-description:
-globs:
+description: Uniform core concepts - compositions, components, patterns, entries, content types
+globs:
alwaysApply: true
---
@@ -10,10 +10,10 @@ Uniform is a modern, headless, component-based Content Management System (CMS).
### Uniform Compositions
-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.
+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).
Composition parameters should only be used for global content that will never need to be personalized.
@@ -77,11 +77,11 @@ Example:
`["hero", "callToAction", "$p:00000000-0000-0000-0000-000000000000"]`
3. `patternsInAllowedComponents` This controls how component patterns are validated against `allowedComponents`.
* If `true`: A pattern is only allowed if it is explicitly listed in allowedComponents (with the `$p:` prefix).
- Example:
+ Example:
`["hero", "$p:00000000-0000-0000-0000-000000000000"]`
Only the listed pattern and `hero` components are allowed - no other patterns based on `hero` are valid.
* If `false`: a pattern is allowed if its base component type is listed in `allowedComponents`.
- Example:
+ Example:
`["hero"]`
Only `hero` components and any pattern based on `hero` are allowed.
4. If you are editing a component pattern or composition pattern, the slot section component ($slotSection) is always allowed.
@@ -173,7 +173,7 @@ Media files that are used in Uniform compositions and entries are called _Assets
### Localization
-Uniform defines locales at a project level. These are locales that content can be written in.
+Uniform defines locales at a project level. These are locales that content can be written in.
Individual compositions, entries, and patterns must also _enable_ a locale to indicate that they have content in that locale. This allows for specific content to support a subset of locales.
Locales must be enabled on compositions, entries, or patterns before their parameters or fields can have values in that locale.