← UniformCONTENT HISTORY

Update to Uniform

Snapshot Sep 30, 2026 · 23:15 UTC · version 1.0.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Add personalized, relevance-ranked content recommendations to a Uniform + React/Next.js project by boosting Content API results with Uniform Context enrichment scores. Use when a user wants visitor-personalized recommendations, dynamic product/article/promotion lists ranked by interest, enrichment-based content ranking, or mentions enrichment boosting, boost orderBy, or the `ufvd` cookie with Uniform.",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 196
    },
    {
      "relative_path": "references/reference.md",
      "size_in_bytes": 5452
    },
    {
      "relative_path": "templates/RecommendationsServerComponent.tsx",
      "size_in_bytes": 1635
    },
    {
      "relative_path": "templates/getEnrichmentBoostedOrderBy.ts",
      "size_in_bytes": 1904
    },
    {
      "relative_path": "templates/getRecommendations.ts",
      "size_in_bytes": 1497
    },
    {
      "relative_path": "templates/search.ts",
      "size_in_bytes": 1304
    }
  ],
  "name": "uniform-enrichment-recommendations",
  "skill_md_contents": "---\nname: uniform-enrichment-recommendations\ndescription: >-\n  Add personalized, relevance-ranked content recommendations to a Uniform +\n  React/Next.js project by boosting Content API results with Uniform Context\n  enrichment scores. Use when a user wants visitor-personalized recommendations,\n  dynamic product/article/promotion lists ranked by interest, enrichment-based\n  content ranking, or mentions enrichment boosting, boost orderBy, or the `ufvd`\n  cookie with Uniform.\nlicense: MIT\n---\n\n# Uniform Enrichment-Boosted Recommendations\n\nAdd a feature that re-ranks a Uniform Content API query by the current visitor's\n**enrichment scores** (their interest profile from Uniform Context), so each\nvisitor sees the same content pool ordered by what is most relevant to them.\nWorks for any content type (products, articles, promotions, events, ...).\n\n## How it works (read first)\n\n1. Uniform Context accumulates visitor **enrichment scores** in the `ufvd`\n   cookie, keyed `<categoryId>_<value>` → number (e.g. `int_internet: 50`).\n2. On the server, those scores are converted into a Content API **boost clause**\n   passed to `orderBy`: `boost|fields.<field>:<value>:<weight>`.\n3. `EntryDeliveryClient.list({ orderBy: [clause] })` re-ranks the result set.\n4. No scores → no clause → graceful fallback to default ordering.\n\n**Critical alignment rule:** the enrichment value's suffix (after the first\n`_`) must equal the value stored in the content field you boost on. Enrichment\n`int_internet` only boosts entries whose target field holds `internet`. If they\ndon't match, nothing re-ranks. Validate this before writing code.\n\nFor the full conceptual reference, terminology, and troubleshooting, read\n[references/reference.md](references/reference.md).\n\n## Prerequisites — verify before implementing\n\nStop and confirm each. If one is missing, set it up or tell the user it's\nrequired first.\n\n- [ ] **Uniform Context available.** `@uniformdev/context` provides the scoring\n      engine. In Next.js App Router it ships bundled with\n      `@uniformdev/next-app-router` and the tracker/provider is wired by the SDK\n      (e.g. `UniformComposition` + `clientContextComponent`), so a separate\n      `@uniformdev/context` install or hand-rolled `<UniformContext>` is **not**\n      required — do not flag the feature as broken just because you can't find one.\n      The server-side boost reads the `ufvd` cookie directly and falls back to\n      default ordering when no scores are present, so the component works\n      regardless. (Live per-visitor re-ranking still needs scores to actually\n      accumulate — see the score-growth note below.)\n- [ ] **Content client deps available** (`@uniformdev/canvas`).\n- [ ] **API key + project ID** in env (commonly `UNIFORM_API_KEY`,\n      `UNIFORM_PROJECT_ID`) with read-entries permission.\n- [ ] **A target content type** exists with a field whose values can match\n      enrichment value suffixes (the alignment rule above).\n- [ ] Detect the framework (Next.js App Router vs Pages vs other React). The\n      cookie read differs; templates assume Next.js App Router (`cookies()` from\n      `next/headers`). Adapt for other setups.\n\n## Workflow\n\nCopy this checklist and track progress:\n\n```\n- [ ] Step 1: Confirm prerequisites + detect framework/conventions\n- [ ] Step 2: Confirm enrichment categories + content field alignment in Uniform\n- [ ] Step 3: Add the three frontend layers (helpers, score reader, fetch)\n- [ ] Step 4: Build/render the component (async server component or Suspense)\n- [ ] Step 5: Register the Uniform component definition + component pattern (MCP)\n- [ ] Step 6: Wire boostEnrichments param, then verify re-ranking\n```\n\n### Step 1 — Confirm prerequisites and conventions\n\nRun the prerequisite checklist. Inspect the repo to match its conventions:\nwhere utilities live (e.g. `src/utils`), how Uniform components are registered\n(the component resolver/mapping), and the cookie/SSR approach. Reuse existing\npatterns; do not introduce a new structure.\n\n### Step 2 — Confirm enrichments and content alignment in Uniform\n\nUse the **Uniform MCP tools** (never edit `uniform-data` YAML/JSON directly) to:\n\n- `getOptimizationData` — list enrichment categories and value public IDs.\n- Inspect the target content type's fields (`getDefinition`/`searchEntries`).\n\nConfirm the alignment rule for each enrichment you intend to use: enrichment\nvalue suffix == stored content field value. If enrichments don't exist yet,\ncreate them (`mutateEnrichment`) and tell the user content must be tagged so\nscores actually accumulate (see references/reference.md §\"make scores grow\").\n\n### Step 3 — Add the three frontend layers\n\nAdapt the templates in `templates/` to the project's paths, naming, and content\ntype. Keep names generic unless the user specifies otherwise.\n\n1. `templates/search.ts` — pure helpers (`getEnrichmentAndFieldKey`,\n   `getEnrichmentKeysWithScore`, `getOrderByClause`). No I/O.\n2. `templates/getEnrichmentBoostedOrderBy.ts` — reads `ufvd` from the request\n   cookie via `CookieTransitionDataStore`, builds the boost map, returns the\n   `orderBy` clause (or `undefined`).\n3. `templates/getRecommendations.ts` — calls the Content API with\n   `orderBy: [clause]`, filtered to a single content type.\n\n### Step 4 — Build and render the component\n\nUse `templates/RecommendationsServerComponent.tsx`. Because the fetch is async\nand per-visitor, render as an async server component, or wrap in `<Suspense>`\nwith a skeleton so it doesn't block first paint. Map raw entries to your card UI.\n\n### Step 5 — Register the Uniform component (MCP)\n\nUse the Uniform MCP tools to create the component definition and a component\npattern (follow project rules: always create a pattern, allow overridability,\nconfigure new slots with `allowAllComponents=true`). Parameters:\n\n- `contentType` (select) — one option per recommendable content type.\n- `boostEnrichments` (multi-select) — each option value is\n  `\"<enrichmentCategoryId>,<contentFieldId>\"`, e.g. `\"int,category\"`.\n- `maxRecommendations` (number).\n- presentation params + a title slot as needed.\n\nThen register the code component in the project's component resolver/mapping and\nrun `npm run uniform:pull` (or `pnpm`) to sync serialized data to disk.\n\n### Step 6 — Wire params and verify\n\nPass `boostEnrichments`, `contentType`, `maxRecommendations` from the Uniform\ncomponent into `getRecommendations`. Then verify (see references/reference.md §Verifying):\nsimulate a visitor profile, log the generated `orderBy`, confirm matching\nentries move to the top, change the profile, confirm ordering changes.\n\n## Guardrails\n\n- Use `orderBy` boost, not `filters`, so visitors still see a full set, just\n  re-ranked. Use `filters` only to hard-exclude.\n- The score reader must run server-side (it reads cookies). In Next.js App\n  Router use `'use server'` + `cookies()`; elsewhere pass the cookie explicitly.\n- Enrichment value public IDs: `<categoryId>_<value>` with no extra underscores\n  (the parser keeps only the segment after the first `_`).\n- Never hand-edit Uniform `uniform-data` files; use MCP, then `uniform:pull`.\n- Always create a code component for the Uniform component definition (incl.\n  matching slots) or the visual editor preview breaks.\n"
}

SHA-256 of public snapshot: b67b45e8b7f0f788cf63f4cb0553c067a39c473793d237db316ed44fd4c59a58