Under the hood

How Spectare works

From the moment a visitor lands to the moment personalised content appears: intent classification, atom assembly, brand voice, multi-tier caching, image selection, and a presentation learning system that improves with every session.

Before any of this

Everything below runs on your atom library. Write atoms directly in the admin, or import them from an existing site: Spectare reads your published pages and drafts focused atoms for you to review, so personalisation starts from real content on day one, not a blank library. Nothing publishes without your approval.

Script tag

Client-side slots

spectare.js runs in the browser after page load. It reads UTM params, referrer, and localStorage, calls qualify, then assembles and fills data-spectare-slot divs. Works on any site that runs JavaScript. Visitors see a brief shimmer while the pipeline runs.

Browser → /api/qualify/your-org
Browser → /api/assemble/components
Browser → fills slot divs

WordPress plugin

Server-rendered zones

The PHP plugin calls /api/assemble/ssr on the server before the page is sent. Zone shortcodes or Gutenberg blocks mark where each content type renders: hero, body, proof, cta. Content is in the HTML at first paint. Page caching is bypassed automatically.

PHP → /api/assemble/ssr
Filters assembly by zone
HTML contains content at paint
No shimmer, no client JS required

Next.js SSR

React server components

Your server component reads signals from the HTTP request before the page is sent. It calls /api/assemble/ssr and passes the result to PersonalisedSection. Content is in the HTML at first paint with no shimmer. The client confirms intent and tracks conversions.

Server → /api/assemble/ssr
HTML contains content at paint
variantId seeded into sessionStorage
Client confirms + tracks conversions
Live on this page

This block was built for you before the page arrived

Your signals were classified into an intent, atoms were selected from the library, and the layout was composed and cached, all before the page reached you. Here is what that produced for this visit. The rest of this page explains each step.

See how Spectare assembles pages

Read visitor intent from signals. Watch the personalisation engine decide what content matters.

From: What is Spectare, Silent intent detection plus explicit visitor input

Silent intent detection plus explicit visitor input

Spectare works out who each visitor is the moment they arrive, without asking anything. It reads the referrer, UTM parameters, the page they landed on, and any prior visit patterns stored locally to build a signal picture and classify intent. That classification drives which atoms are selected and how the page is assembled.

When a visitor types a question through the ask surface, a different signal path activates. The question is explicit demand in the visitor's own words, and Spectare records it alongside the best atom similarity score the search returned. A high similarity means the library answered well. A low similarity, below 0.45, means the question went unanswered and the visitor's exact wording is flagged as a content gap.

These two signal types are treated separately in assembly. Inferred signals from referrers and UTM parameters feed the general intent summary. Typed questions get their own section in the gap detection prompt, and a weak similarity score on a typed question outweighs inferred-signal evidence when assessing what content is missing from your library.

The assembled_pages record captures source and top similarity for every page built from a typed question. This data feeds both the live unanswered questions feed in your admin and the nightly gap detection run, giving you a complete picture of where your library is strong and where it is not.

Weak match threshold

similarity below 0.45

Signal types tracked

inferred and explicit

Server-rendered personalisation on warm cache hits

Spectare solves the flash-of-default-content problem that plagues most personalisation platforms.

Read more →

See it for yourself: turn on the x-ray to outline every personalised block on this page and see exactly which signals were read.

01Intent classification

Reading the visitor

On the client-side path, spectare.js runs on every page load. It reads the referrer, UTM parameters, landing page URL, and any page visit history stored in localStorage from earlier in the session or from previous visits. These signals are sent to /api/qualify/your-org, where Claude classifies them into an audience, funnel stage, and confidence score. The result is a signed context token: not a user profile, not a cookie, not a segment. On the Next.js SSR path, signals come from the HTTP request headers and query string instead. The SSR qualify result is also cached by signal pattern for 7 days, and flushed the moment you change your audience segments or other settings, so repeat visitors with the same page, referrer, and UTM signature skip the Claude call entirely and receive a classification in under 50ms.

referrerUTM paramslanding page URLvisit history (localStorage)

spectare.js

collects signals and calls qualify

POST /api/qualify/your-org

sends context to the server

Claude: classify intent

audience · stage · confidence

Signed context token

carries audience, stage, and confidence. Valid for 1 hour.

spectare.js runs client-side on every page load

No training period

Claude is the model. Classification is accurate from visitor one without historical traffic data.

No cookies

Intent is classified fresh each session on the client-side path. On the SSR path, the classify result is cached by signal pattern, not by person. No visitor profile is ever stored.

Returning visitors

Visit history in localStorage means returning visitors are personalised even with no UTM params.

02Content assembly

Building the experience

On the client-side path, the context token is passed to /api/assemble/components. On the Next.js SSR path, /api/assemble/ssr handles qualify and assemble in a single server call with no token exchange needed. Either way, the core assembly logic runs: vector search, conversion history, and image selection in parallel, then Claude selecting from a registry of 10 component types. Claude sees which atoms have converted most for this audience and stage, and which atoms have appeared together in past converting sessions. Semantic similarity finds the candidates. Past performance decides between them. When atoms carry a rhetorical role, the page is ordered as an argument: the problem first, then how it works, then evidence, then the doubt answered, then the ask, and the server verifies that order rather than hoping for it. The result is a component list that renders in the browser (client path) or arrives pre-rendered in the HTML (SSR path).

Context token

audience · stage · confidence

Vector search

candidates by semantic similarity

Conversion history

atoms + arrangements that converted for this audience + stage

Image selection

best overlay image for audience + stage

Claude: assemble page

picks atoms, picks component types, writes Claude-owned slots in your brand voice

AnnouncementBar

HeroStatement

Claude writes

ImageCtaHero

Claude writes

AtomCard

StatGrid

FeatureList

TestimonialCard

ComparisonTable

CodeBlock

CtaStrip

Rendered page

personalised content in the browser

Claude writes (uses your brand voice)Drawn from your atoms, unchanged

Runs on the server after qualify returns a token

What Claude writes

Claude generates fresh copy for two component types: HeroStatement (headline and subheading) and ImageCtaHero (headline, subheading, and CTA label). Everything else (AtomCard prose, StatGrid numbers, TestimonialCard quotes) is drawn directly from your atoms and never rewritten.

Brand voice

Set a plain-English instruction in Settings and Claude writes every headline in your voice: "Direct and confident. Short sentences. No jargon." Brand voice only applies to Claude-written components. Your atom content is never rewritten regardless of what you set.

03Delivery speed

Two-tier caching

Personalisation runs through two caches, checked in turn, so most visits never call Claude at all. The first reuses the visitor’s classification (signals to audience, stage, and intent); the second reuses the assembled page for that intent. Both are pre-warmed for common patterns and kept for seven days, so even a first visitor usually lands on a warm result and the page is served in about 200ms. The image bandit still runs on every request, even on a hit, so image optimisation never stalls.

1. Qualify cachewho is this visitor

Signals to intent

Hit: a visitor with the same signals was classified before, so the audience, stage, and intent are reused with no Claude call. Miss: Claude Haiku reads the signals once, then the result is cached.

hit: 0 Claude callsmiss: one Haiku call
2. Assembly cachewhat page they get

Intent to page

Hit: that intent (type, audience, stage) was assembled recently, so the personalised layout is served in about 200ms with no Claude call. Image selection still runs every time. Miss: Claude assembles the components once for that pattern, then writes it back so the next visitor hits the cache.

hit: ~200msmiss: assembled once

Two caches, checked in turn. Both are pre-warmed for common patterns and kept for 7 days, so most visits skip Claude entirely.

Zero-flicker delivery for Next.js

Next.js customers can call /api/assemble/ssr from a server component before the page is sent to the browser. The shared Redis cache means warm intent patterns return a pre-assembled component list in under 50ms. PersonalisedSection accepts the pre-rendered assembly as a prop: if the client classify result matches the server result, no DOM update occurs and the visitor sees no content flash at any network speed.

04Image selection

The image bandit

Spectare selects a hero image for each assembled experience. It uses a multi-armed bandit: 90% of requests exploit the image with the highest observed conversion rate for the current audience and stage combination; 10% explore a random image to gather data on untested combinations. Every impression is recorded, and conversions update the conversion rate in real time. No manual A/B test setup required.

Visitor arrives

audience + stage known from qualify

Select image

exploit (90%) or explore (10%)

Record impression

image, audience, and stage recorded

Visitor converts?

Conversion recorded

linked to this image, audience, and stage

Next visitor

image with the best conversion rate for this audience + stage

10% of requests explore a random image. 90% exploit the best-converting image.

05Feedback loop

The co-conversion graph

Every conversion event records which atoms appeared together in that session. A graph tracks how often every pair of atoms appears together in converting sessions. When the assembly pipeline picks a primary atom, it reads the graph to surface supporting atoms that have actually worked alongside that primary, not just ones that are semantically similar. Claude also receives the top-converting atom IDs for the visitor's specific audience and stage combination, drawn from the last 30 days of conversions. Both signals are passed directly to Claude during assembly, on every path: client-side, SSR, and script tag. The graph is rebuilt nightly from all conversion data.

Visitor converts

session contained atoms A, B, and C

Co-conversion links updated

every pair of atoms in the session gets a stronger link

Next visitor: primary = A

assembly reads the strongest co-conversion links for A

B

weight 12

C

weight 7

D

weight 2

B is chosen. Not just semantically similar. Actually converted together.

The graph is rebuilt nightly from all conversion data. Atom selection reads it directly.

06Presentation learning

Testing what works, not just what fits

Vector search finds the right atoms. The co-conversion graph finds the right supporting atoms. But which component order converts best? A StatGrid before an AtomCard, or after? Spectare tests this automatically. Set an exploration rate in Settings and a configurable share of visitors see an experimental arrangement. The arrangement is labelled with a strategy tag: data-led, outcome-led, question-led, social-proof-led, or technical-led. Every arrangement is recorded with its impressions and conversions, on every path: client-side, SSR, and script tag, on cache hits as well as fresh assemblies.

Then the loop closes. Once an arrangement clears your signal threshold, Claude is told which arrangements convert best for this visitor’s audience and stage, with the rates that earned them. It prefers a proven arrangement when the atoms support one, and ignores it when they do not: a winning shape built from the wrong content converts worse than an honest one. Exploration runs blind to this, on purpose, so it keeps finding arrangements the data has not seen yet. The atom content never changes. Only the presentation is tested.

There is a discipline to when a winner counts. Ahead is not the same as winning: a 12% rate beating a 10% rate across a hundred visits each sits well inside the noise. So Spectare holds every arrangement’s rate as a confidence interval, not a single number, and only names a winner once that interval clears the runner-up, once its worst case still beats the other’s best case. The intervals are built to stay valid under constant watching, so refreshing the dashboard a hundred times cannot manufacture a winner, and the evidence is windowed: editing an atom restarts the count for every arrangement containing it, so a changed page re-proves itself. Until then the honest verdict is that it is still gathering data, and that is exactly what your analytics show, per audience and stage: a statistically real winner, or a clear not-yet, never a coin toss dressed up as a result.

And the biggest claim is measured, not asserted. A small slice of visitors, only if you opt a workspace in, sees your default page instead of a personalised one: a live control. Personalisation’s lift is computed against it as an interval, and no number is quoted until that interval clears zero. When the evidence supports a change to your rules or an atom’s targeting, Spectare does not apply it quietly: it shows you the with-and-without numbers and waits for your yes, and the accepted change re-proves itself from scratch.

Visitor arrives

intent known from qualify

Exploration check

is this visitor in the configured exploration share?

most visitors · exploit

Proven arrangement

served from Redis cache

exploration share · explore

New arrangement

bypasses cache; strategy tag assigned

Impression recorded

variantId · audience · stage · components

no conversion

Session ends

impression counted, no conversion

conversion

Conversion recorded

linked to this variant, audience, stage

What's working

variants ranked by conversion rate once signal threshold reached

Set exploration rate and signal threshold in Settings. Results appear in Analytics once a variant reaches your chosen impression threshold.

07The atom’s journey

Working from day one, better with every conversion

Everything above is one loop, and an atom rides it for its whole life. Nothing waits for a training period: the day you publish, an atom is chosen on how well it answers the visitor in front of it. From then on, every impression and conversion it takes part in is recorded, confidence builds until real winners separate from lucky streaks, and what has actually converted starts leading the page. That is why the personalisation you see in week six is sharper than week one, without you touching a thing.

Day one

Atom published

audience, stage and role set; embedded for retrieval

Serving from visitor one

chosen by how well it answers the visitor in front of it; no history needed

As traffic arrives

Exploration tries it

a small share of visitors see it in fresh arrangements

Every outcome recorded

impressions and conversions, per atom, arrangement, audience and stage

Once the evidence clears the noise

Confidence separates winners from streaks

rates held as intervals; a winner only when its worst case beats the rest

Proven content leads the page

conversion-ranked atoms and winning arrangements serve to most visitors

The loop never closes for good: exploration keeps testing challengers, so a better atom can always unseat a proven one.

08For AI agents

The same content, read by machines

More of your buyers research through AI, and the visitor is often an agent. The same atom library that personalises pages for people is also published as machine-readable data, so an assistant can read what you offer, accurately and current, without scraping a rendered page. And personalisation never escapes the spots you place: navigation, pricing, and your core claims read the same for every visitor, because Spectare varies the argument, not the facts.

  • →Entry point: your site serves an llms.txt that maps what you publish, so an agent needs a handful of fetches rather than a crawl of fifty pages. As metered crawling arrives, that curation is a cost control, not just a courtesy.
  • →Content: every published atom is available as clean JSON at /api/content, with a stable slug per item.
  • →Hand-off: an assistant can call the qualify endpoint with what its user wants and get back a link to a page personalised for that person, so the referral lands on a tailored experience, not a generic one.

See it running on a real site

The demo page runs the full qualify and assemble pipeline live. Describe your site and watch intent classification and content assembly happen in real time.