The page your visitor sees
isn't the page you published.
OF1 Product turns a static site into a surface that adapts per visitor. This page explains how a page is generated, what signals drive it, what data is (and isn't) stored, and how to integrate the service into your own site. It describes the of1-gen-web-service — the runtime that produces personalized pages.
What of1 is
of1 is an AI service that assembles a web page in real time for the individual visitor in front of it. Instead of serving one page authored once by hand, it reads the visitor's context, works out what they're trying to do, retrieves the most relevant content from your own corpus, and composes a page that fits that intent — every time, with no rules to write and no segments to maintain.
The critical design decision is that the LLM never writes HTML. It decides what to show and in what order; your design system decides how it renders. That keeps output on-brand, accessible, and impossible to break — while still being fully personalized.
of1 runs on Adobe Edge Delivery Services — Adobe's edge-native web platform. Edge Delivery Services is a hard requirement: of1 assembles pages from the block-based content model that EDS provides and delivers them at the edge.
Per visitor, per intent
Every element is reconsidered for the person viewing it — not a segment they were bucketed into.
Blocks, not markup
The model selects from 30+ pre-built, CSS-styled blocks. It never invents new markup.
Your content, via RAG
Copy is filled from your products, features and FAQs — retrieved by vector search, not hallucinated.
Signals stay client-side
Behavioural context is gathered in the browser and sent per request. of1 stores no visitor profile.
The core idea
For decades, marketing meant shouting at categories and cohorts. Your visitors now spend all day with tools that respond to their intent — then land on your one static page.
Segments are a confession that you don't know your customer well enough.
of1 removes the segment. There are no rules to write, no content matrix to maintain, no A/B variants to fork. The page is generated for the one person viewing it — and it should feel authored, not targeted. As the deck puts it: most AI wants you to know it's there; ours wants you to forget.
Request lifecycle
A single call to POST /api/generate runs an ordered pipeline at the edge. Results stream back as newline-delimited JSON (NDJSON) so the page renders block-by-block as it's produced.
query, plus optional signals: browsing[] (URL, dwell time, scroll depth), interests[], a pre-classified intent, segment (device, region) and acquisition (UTM, referrer). A tenant id identifies the brand.comparison, recommendation, deep-dive, budget or discovery — by LLM (default) or keyword fallback. Personas and use-cases configured for the tenant are matched in parallel.section (one per block), suggestions (follow-up prompts), debug (timings, model, token usage) and done — so the client renders progressively.The two-phase LLM
When template routing is enabled for a tenant, the model runs twice: first it picks a layout that fits the intent, then it fills that layout with retrieved, on-brand content.
- Referrer & query
- Device & time of day
- Scroll & click history
- In-session intent
In Phase 1 the model classifies intent and picks one template from the tenant library (e.g. first-full-recommendation) — a template is just a fixed order of blocks, and the model never reorders it. In Phase 2 it fills each block's slots from RAG-retrieved content, shaped by the brand layer (voice, compliance, design tokens); image URLs are validated against an allow-list before render.
The output is a complete page — assembled from pre-styled blocks — that feels authored rather than generated. The default flow works the same way without a template step: the model composes hero / columns / cards sections directly.
Blocks & templates
Why the LLM picks blocks instead of writing HTML — and how templates map intent to a layout.
A typical web page is 10,000–50,000 tokens of HTML. Asking an LLM to emit that raw is slow, brittle, and unsafe: it hallucinates class names, breaks CSS and drops accessibility attributes, and every page would need validating. of1 sidesteps this by reusing the separation of concerns every CMS already has:
Styling
Design tokens + CSS. Owned by developers.
Structure
Blocks — which ones, and in what order.
Content
Copy, images and data, from your corpus.
In AEM Edge Delivery Services a block is simply a named table in a document — authors write them in Google Docs or Word, developers style them with CSS. of1 selects from 30+ of these pre-built blocks; it never invents markup. A template is a block order that fits a visitor's intent, grouped into families:
| Family | When it's used | Example templates |
|---|---|---|
| First recs | Visitor lands cold — surface a confident top pick | first-full-recommendation, first-discovery-broad, first-budget-focused |
| Follow-up | They're comparing — narrow the field, go head-to-head | followup-head-to-head, followup-narrow-field, followup-deep-compare |
| Quick answers | One specific question — answer it, nudge a next step | quick-yes-no, quick-with-recommendation, quick-feature-explain |
heroproduct-recommendationcomparison-tableverdict-cardrecipe-cardsSignals captured
Context is gathered client-side and passed on the request. It describes the current session — not a stored identity.
| Signal | Field | What it tells of1 |
|---|---|---|
| Referrer & query | acquisition, query | Where the visitor came from and what they asked |
| Device & region | segment | Form factor and locale for framing |
| Scroll & click history | browsing[] | URL, dwellTimeMs, scrollDepth per page — journey depth |
| Interests | interests[] | Pre-computed topic scores that bias retrieval |
| In-session intent | intent | A pre-classified goal, if the client has one |
| Prior queries | conversationHistory[] | Earlier turns, for de-duplication |
cf-connecting-ip) is used for rate-limiting only and is not written to storage.Beyond the browser. The context model is open-ended — anything that helps describe who the visitor is and what they need can be passed on the request. The client-side signals above are the zero-setup default, but an integrator can enrich them with consented, first-party data:
AEP & Real-Time CDP
The Real-Time Customer Profile from Adobe Experience Platform — audiences, computed attributes and edge-resolved identity.
CRM & account
Lifecycle stage, tier, entitlements and purchase history for a signed-in visitor.
Membership & rewards
Points balance, status and benefits that change what's worth surfacing.
Catalog & cart
Live stock, pricing, active promotions and the current cart or basket state.
Place & time
Geo, locale, weather or nearest-store inventory for context-aware framing.
Consented identity
A first-party identity graph that ties sessions together — with the visitor's consent.
What is stored
The service is stateless per request. It persists your content configuration — not visitor data.
| Store | Holds | Notes |
|---|---|---|
| R2 object storage | Tenant configs (products, personas, features, FAQs, templates, brand voice) | Static, brand-level — not request-specific |
| Vectorize index | Embeddings of your products / features / FAQs | Content only, scoped per tenant; no request metadata |
| KV cache | Loaded configs (300s), suggestions (300s), governance rules (3600s) | Short-lived caches, keyed by tenant |
/api/generate does not log individual requests or responses to persistent storage. Behavioural analysis is computed per request and discarded. Multi-turn personalization works because the caller tracks and re-sends the behaviour profile — of1 keeps nothing between calls. Each tenant's configs, vectors and cache keys are fully isolated.API endpoints
Public endpoints are CORS-enabled (Access-Control-Allow-Origin: *) and need no auth. Generation is rate-limited to 30 requests / 60s per IP. Admin endpoints require a token.
/api/generateGenerate a page — streams NDJSON/api/suggestFollow-up exploration prompts/api/personalizeRewrite existing page elements per behaviour/api/tenants/:id/syncPull & index tenant config from EDS (admin)A minimal generation request:
The response is a stream of NDJSON lines — section, suggestions, debug, done (default flow) or a single page event with full HTML + stylesheet (template-routing flow) — which the client consumes as it arrives. Per-request overrides such as ?device=mobile®ion=fr&provider=bedrock&model=claude-opus are supported.
Embed the SDK
The client SDK handles streaming, DOM injection and the debug widget so you don't have to.
?debug=1 to any page using the SDK to reveal a widget showing the model used, timings, intent classification, RAG match counts and token usage — plus a runtime model-override control (stored in sessionStorage).Tenant configuration
A tenant is your brand. Its content and behaviour are defined by JSON files authored in AEM / EDS and pulled into of1 via sync.
| File | Defines |
|---|---|
brand-voice.json | Personality, tone, vocabulary, words to avoid |
products.json | Products — id, name, category, price, keywords, highlights, images |
personas.json | Personas and their keywords / preferences |
use-cases.json | Use-cases matched against the query |
features.json, faqs.json | Feature descriptions and Q&A used in RAG |
templates.json / block-guide.json | Template routing definitions, or block layout rules |
suggestions.json, cta-template.json | UI strings and the CTA mustache template |
Publish these at https://<id>.aem.page/of1/config/<file>.json, then call POST /api/tenants/<id>/sync (with the admin token) to pull them into R2 and rebuild the vector index. Configs are cached in KV for 300 seconds.
Models & infrastructure
| Concern | What runs it |
|---|---|
| Page generation & intent classification | Cerebras gpt-oss-120b (default; model-agnostic — GPT, Claude, Llama, Mistral, Bedrock) |
| Template selection & suggestions | Cloudflare Workers AI @cf/meta/llama-3.1-8b-instruct |
| Embeddings for RAG | Cloudflare AI @cf/baai/bge-base-en-v1.5 |
| Compute | Cloudflare Workers at the edge |
| Storage | R2 (configs), Vectorize (embeddings), KV (cache) |
| Brand governance | Adobe Brand Governance agent (optional; colours, tone, guardrails per domain / segment) |
of1-gen-web-service). © 2026 Adobe — early-stage technology by the Adobe Experience Manager team.