npx skills add ...
npx skills add uniformdev/agent-skills --skill uniform-enrichment-recommendations
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.
npx skills add uniformdev/agent-skills --skill uniform-enrichment-recommendations
Add a feature that re-ranks a Uniform Content API query by the current visitor's enrichment scores (their interest profile from Uniform Context), so each visitor sees the same content pool ordered by what is most relevant to them. Works for any content type (products, articles, promotions, events, ...).
ufvd
cookie, keyed <categoryId>_<value> → number (e.g. int_internet: 50).orderBy: boost|fields.<field>:<value>:<weight>.EntryDeliveryClient.list({ orderBy: [clause] }) re-ranks the result set.Critical alignment rule: the enrichment value's suffix (after the first
_) must equal the value stored in the content field you boost on. Enrichment
int_internet only boosts entries whose target field holds internet. If they
don't match, nothing re-ranks. Validate this before writing code.
For the full conceptual reference, terminology, and troubleshooting, read references/reference.md.
Stop and confirm each. If one is missing, set it up or tell the user it's required first.
@uniformdev/context provides the scoring
engine. In Next.js App Router it ships bundled with
@uniformdev/next-app-router and the tracker/provider is wired by the SDK
(e.g. UniformComposition + clientContextComponent), so a separate
@uniformdev/context install or hand-rolled <UniformContext> is not
required — do not flag the feature as broken just because you can't find one.
The server-side boost reads the ufvd cookie directly and falls back to
default ordering when no scores are present, so the component works
regardless. (Live per-visitor re-ranking still needs scores to actually
accumulate — see the score-growth note below.)@uniformdev/canvas).UNIFORM_API_KEY,
UNIFORM_PROJECT_ID) with read-entries permission.cookies() from
next/headers). Adapt for other setups.Copy this checklist and track progress:
Run the prerequisite checklist. Inspect the repo to match its conventions:
where utilities live (e.g. src/utils), how Uniform components are registered
(the component resolver/mapping), and the cookie/SSR approach. Reuse existing
patterns; do not introduce a new structure.
Use the Uniform MCP tools (never edit uniform-data YAML/JSON directly) to:
getOptimizationData — list enrichment categories and value public IDs.getDefinition/searchEntries).Confirm the alignment rule for each enrichment you intend to use: enrichment
value suffix == stored content field value. If enrichments don't exist yet,
create them (mutateEnrichment) and tell the user content must be tagged so
scores actually accumulate (see references/reference.md §"make scores grow").
Adapt the templates in templates/ to the project's paths, naming, and content
type. Keep names generic unless the user specifies otherwise.
templates/search.ts — pure helpers (getEnrichmentAndFieldKey,
getEnrichmentKeysWithScore, getOrderByClause). No I/O.templates/getEnrichmentBoostedOrderBy.ts — reads ufvd from the request
cookie via CookieTransitionDataStore, builds the boost map, returns the
orderBy clause (or undefined).templates/getRecommendations.ts — calls the Content API with
orderBy: [clause], filtered to a single content type.Use templates/RecommendationsServerComponent.tsx. Because the fetch is async
and per-visitor, render as an async server component, or wrap in <Suspense>
with a skeleton so it doesn't block first paint. Map raw entries to your card UI.
Use the Uniform MCP tools to create the component definition and a component
pattern (follow project rules: always create a pattern, allow overridability,
configure new slots with allowAllComponents=true). Parameters:
contentType (select) — one option per recommendable content type.boostEnrichments (multi-select) — each option value is
"<enrichmentCategoryId>,<contentFieldId>", e.g. "int,category".maxRecommendations (number).Then register the code component in the project's component resolver/mapping and
run npm run uniform:pull (or pnpm) to sync serialized data to disk.
Pass boostEnrichments, contentType, maxRecommendations from the Uniform
component into getRecommendations. Then verify (see references/reference.md §Verifying):
simulate a visitor profile, log the generated orderBy, confirm matching
entries move to the top, change the profile, confirm ordering changes.
orderBy boost, not filters, so visitors still see a full set, just
re-ranked. Use filters only to hard-exclude.'use server' + cookies(); elsewhere pass the cookie explicitly.<categoryId>_<value> with no extra underscores
(the parser keeps only the segment after the first _).uniform-data files; use MCP, then uniform:pull.