The Doozer Brainlive from the knowledge bundle · v2.2.618 · 2026-09-13 17:15 ETall pages · one page

AI Postcards — Factory, Theme Studio, and Campaigns

systems/ai-postcards.md · System · postcards, factory, theme-studio, campaigns, claim, thanksio, direct-mail, vision-gate, audience, ai-image

unverified: no trust signals recorded yet

How Doozer builds and mails postcards. The Factory assembles accurate cards deterministically (real screenshot/code/QR, no per-card AI cost); the AI Theme Studio designs vision-gated backgrounds; campaigns give each card a purpose + audience. Claim Your Site is the first campaign.

AI Postcards + the Postcard Factory

v2.2.381 — the Factory is now the default, accurate path. Generating the
whole card with AI every time was expensive AND inaccurate (it approximated the
claim code, invented the short URL, hallucinated the domain in the screenshot's
address bar). The Postcard Factory (includes/postcard-factory.php) flips
it: AI designs backgrounds/layouts; every ACTUAL card is composed
deterministically from REAL values and flattened to a print-ready 1800x1200 PNG
via Cloudflare Browser Rendering (postcardFactoryFlatten posts html +
viewport to the same CF endpoint used for screenshots). Real screenshot in a
browser chrome showing the ACTUAL Doozer domain, real minted claim code, real
doozer.link short URL, a real scannable QR, real logo, Machi copy. No per-card AI
cost, nothing to proofread. postcardFactoryCompose($bizId,$opts) files it in
the same review queue (no gate — values are deterministic). Themes: paper / navy.
Admin: AI Postcards page "Build card" panel; Machi defaults to engine='factory'.
v2.2.395 — Multi-campaign system. Postcards are no longer claim-only. A
campaign = purpose + audience + copy/offer (postcard_campaigns,
includes/postcard-campaigns.php). The seeded, locked claim_your_site
campaign (audience=unclaimed) IS the old behavior, now named. campaign already
threaded through postcard_designs/thanksio_sends/claim_codes/machi_touches as a
string; this formalizes the keys. Audiences (hard-coded): all / unclaimed
(admin_email empty) / claimed (admin_email set) / premium (owner lb_user on a
premium-class tier), each + niche (primary_niche) + location (state_code/city);
base = live Doozer site + mailable address. `postcardCampaignAudienceWhere/Count/
Sample. Purpose seeds generation: postcardCampaignThemePromptSeed` feeds the
Theme Studio background prompt (postcardThemeCreate opt campaign);
postcardCampaignMessage resolves the BACK copy (claim → warm/leads/curious
variants; else message_template with tokens {name}{city}{code}{offer_code}
{short_url}). Admin: Campaigns cards + Create/Edit modal (live audience count),
Campaign selector on Factory + Studio, review queue pagination + finder (search +
campaign filter). dz campaign do=list|show|save. NEXT phase: campaign-specific
FRONT copy + audience-gated sending (don't mail a claimed business a claim card).
v2.2.392 — Two-score gate + back copy + Thanks.io levers. The theme gate
(postcardThemeGateCard) now returns TWO independent real scores because there is
no in-admin way to tweak a theme after the fact: accuracy (every required
element present, uncropped, legible — an explicit checklist is passed to the vision
model) and design (aesthetics + theme match only). A theme goes ACTIVE only
when BOTH clear postcard_theme.gate_pass_score (default 78); else draft. Stored
in postcard_themes.design_score / accuracy_score (idempotent ALTER); shown in
the Studio result and gallery tiles. Card template fix: .left scrim is full grid
height (grid-template-rows:100%) so the "doozer." wordmark is always inside the
legibility box. Back-of-card copy (thanksIoClaimMessageVariants in
thanksio.php): warm / leads / curious variants, personalized with the town + a
typed doozer.link fallback, no em-dashes. Thanks.io best practice: the FRONT
is the Factory image; the BACK is message + qrcode_url + return address. Turn
on thanksio.handwriting_style_id (handwritten back lifts response), set
thanksio.size (4x6 default; 6x9/6x11 stand out but need a matching front aspect),
thanksio.message_variant. Rules that win direct mail: personal, specific to them,
ONE clear action (scan), readable in three seconds, honest, warmly signed.
v2.2.390 — AI Theme Studio. The untrustworthy full-AI card painter is
repurposed into a theme/background designer only; the Factory still does the real
assembly. includes/postcard-theme-ai.php: postcardThemeCreate($style,$opts)
takes a plain-words style ("beach vacation", "Thanksgiving warm orange",
"Bronx blue/white pinstripe") + optional business_id/match_site for niche
style cues, builds a LAYOUT-AWARE background prompt (calm left third for text,
calm bottom-right ~1.5in for QR, right half supporting the screenshot, NO
text/letters/logos), generates the bg via the configured image provider
(postcardAiImageProvider), then a **vision pass reads the palette BACK from the
pixels** (postcardThemeReviewBg → accent/ink/dark, reads raw_text). It then
composes a REAL sample card (live screenshot + demo code/QR) and runs a second
vision gate (postcardThemeGateCard) for legibility/layout/design; score
>= postcard_theme.gate_pass_score (default 78) saves status=active, else
draft. Themes are data in postcard_themes (theme_key, source
seed/ai/operator, style_prompt, bg_type color|image, bg_value, accent/ink/dark,
status, gate_score/reasons, preview_url); postcardFactoryThemes() merges seeds
(paper/navy/kraft) + active DB rows so a passing theme is instantly pickable in
the Factory. Image backgrounds get an auto legibility scrim behind the left text
column (postcardFactoryHtml $bgIsImage). postcardFactoryHtml(...,$themeSpec)
takes a candidate spec so the Studio can preview before saving.
Dev API: dz factorytheme do=create style="..." [b=<id>] [match=1],
do=status key= set=active|rejected, do=list. Admin: AI Postcards page has the
AI Theme Studio card (style + business picker + match-site) and a theme gallery
(activate/retire). The AI Postcards business picker uses the same
admin_business_search autocomplete and its dropdown is opaque. First run:
"beach vacation" scored 92, shipped a genuinely good card ("Tropical Escape").
dz factory compose b= [theme=] [angle=]. The old full-AI painter (below) is the
fallback (engine='ai'), kept for background-art experiments.
Themes (v2.2.382): paper (light editorial), navy (bold dark), kraft (warm
local). Theme colors derive from a dark flag + optional panel/muted/chrome
overrides — adding a theme is a few lines in postcardFactoryThemes(). Layout:
local eyebrow + headline that auto-sizes to its length (any Machi angle fits
the fixed 6x4 card) + screenshot as a real <img> in a overflow:hidden crop
box (full nav, no white gap) inside browser chrome showing the real domain.
Render notes: QR inlined as a data URI (external QR service timed out the
browser); networkidle2 + paint delay; 429 backoff-retry.
Load-bearing bugfix shipped here: claimCodeCreate() validated the DEFAULTED
intent but assigned the RAW $opts['intent'], so any caller not passing intent
(every postcard) failed with "Column 'intent' cannot be null" and got no code.
The AI cards hid it by inventing a code; the Factory surfaced it. Real codes now
mint network-wide.

Sent & performance tracking + independent resend (v2.2.407)

Every send already mints its OWN claim code + doozer.link shortlink + Thanks.io order_id, so each touch is independently trackable — the schema never limited a business to one card. The admin Sent section (v2.2.409) is bounded so it never runs wild at scale: three last-5 glances (Sent / Delivered / Touched = scan·visit·claim) plus a full All sends table with search (business/code), campaign + status (delivered/scanned/claimed) filters, sort-by-date, pagination, and a Doozer+ column = full conversion (claimed + owner on a premium tier).

Roadmap (the Marketing Engine this seeds)


AI Postcards — fully-generated claim mail with a quality gate (fallback painter)

What: The physical arm of the observed-world flywheel. When a business has no email on file (unclaimable via implicit verification), we mail a real postcard carrying the site's own screenshot, a claim code, and a scannable QR. The card DESIGN is AI-generated end to end and passes a vision-model quality/accuracy gate before any human sees it. No templated fallback — if the AI can't produce a good card in 3 tries, it fails loudly for review instead of mailing slop.

Engine — includes/postcard-ai.php

Table: postcard_designs (business_id, claim_code_id, screenshot_url, logo_url, qr_url, redeem_url, prompt, image_url, model, attempts, gate_score, gate_verdict, gate_reasons, status ENUM('generating','pending_review','failed','approved','sent', 'rejected'), failures JSON, thanksio_send_id, sent_at, tracking JSON).

Admin — includes/admin-postcards-ai.php (Admin -> Infrastructure -> AI Postcards, route postcards-ai). Human-in-the-loop: ready designs show the card + gate score with a Send button (live checkbox); sent designs show live tracking; failed designs show 3 attempts + Retry. Generation runs as a background postcard_ai job (dispatcher case), so the screen never blocks.

Dev API: dz postcard gen b=<id> (queue+run), list, show id=, send id= [live=1], retry id=, track id=.

The claim loop: sending sets sent and starts the state machine; a QR scan or code redemption sets the owner's businesses.admin_email — the postcard IS proof of claim (implicit verification, no claims table). See [[claim-codes]], [[thanksio]], [[the-observed-world]].

State: shipped v2.2.379 (Jul 7 2026). Blocker for first real run: an image-capable Gemini key must be in api_keys; vision gate keys (openai/anthropic) already present. First target = Powell Flooring (business id 1, West Milford NJ, email NULL, screenshot already captured to Spaces).

AI Discoverability — being the local layer AI agents citeBest AI for the Job — value-aware model selection