After v2 — landing page migration & model-switcher
Two workstreams queued after the v2 OCR rollout lands: (1) migrate the marketing site
from flashcopy.app to zapcopy.app using a design-brief prompt
pipeline, and (2) introduce a model/Lambda switcher + per-scan provenance so we can A/B
providers and audit after any upstream model change. Both are captured here as the
brief — formal specs follow via the brainstorming → writing-plans loop.
E · flashcopy.app → zapcopy.app landing page
brief
The Flash Copy landing page at /Users/oscar/Desktop/dev/flash-copy-landing
predates the ZapCopy rename and is stylistically conservative. We want to replace it with
a Zapcopy-branded site that leverages cutting-edge interactive design while keeping the
core narrative (what the app does, social proof, pricing, CTA).
E1 — Asset + content inventory (first step)
- Catalog every piece of existing copy and imagery under
flash-copy-landing/(index.html, privacy, terms, company, claw) — export into a singlebrief/content.md. - Catalog usable visuals from
/Users/oscar/Desktop/dev/FlashCopyAssets/andZapCopyAssets(demo videos, app screenshots, output examples, seed inputs). - Pull the current pricing story from
UsageTrackingService.swift(Free / Premium / Ultra) and the feature matrix from the in-app Subscription variants so landing-page claims line up with what the app actually does.
E2 — Design-brief prompt pipeline
- Assemble a prompt bundle that includes: the inventory above, our in-app visual language (neon-accent cyan, Outfit typography, dark UI, subtle bolt motifs), competitor landing pages we admire (for inspiration / anti-inspiration callouts), and explicit "must-have" sections.
- Feed the bundle into Claude's design capability and request 3 distinct directions (playful-editorial, command-center dense, hero-marquee cinematic) — each as interactive HTML mockups we can host locally and A/B.
- IP-safety call: evaluate whether Claude's design mode needs the same Stitch-style hard-gate we apply to Google Stitch prompts. Since Claude is our primary model we're more tolerant, but the final prompts should still avoid "make it look like [brand]" patterns. Save the resolved stance as a feedback memory.
E3 — Pick a direction, implement, deploy
- Side-by-side review the three mockups (screenshot → voting HTML pattern we already use for subscription variants).
- Scaffold the chosen direction as the new
zapcopy-landingrepo under/dev; reuse the Cloudflare Pages deploy config fromflash-copy-landing/CLOUDFLARE_PAGES_SETUP.md. - Point
zapcopy.appDNS at the new Pages project; keepflashcopy.appalive with a 301 to the new domain for at least 6 months.
E4 — Decision points to raise during brainstorming
- Does the site get its own blog / release-notes surface, or do we keep change logs inside the app?
- How much interactive "try it" content? (A drop-in image → live OCR demo is technically feasible with a public demo Lambda, but adds ongoing cost.)
- Do we replicate
/claw(the SteelHub subsidiary page) or quietly sunset it?
F · Model/Lambda switcher + per-scan provenance
brief
Today, if Gemini changes behavior overnight (silent model nudge, safety-tuning shift), we
find out because users report bad scans — we have no fast path to swap providers or
compare the new output to the old one. The v2 rollout proved that a per-run
lambdaVariant field is the seed we need; F builds out the full infrastructure
to make switching routine.
F1 — Provenance fields on every scan
Add the following to the existing OCR result envelope (photo + collection + video):
Persist on Photo / Collection / Video and forward to
the dashboard ingest. Back-fill nulls for pre-F1 scans (label as
provenance: "pre-F1" so charts can exclude them).
F2 — Lambda/model swap without a deploy
- Move the current static
OCRLambdaEndpointsinto a remote config fetched from a cheap Lambda at cold start (with on-disk cache + 1 hour TTL). - Config shape:
{ flow, route: { primary, fallback, canary }, rolloutPct }so we can dial a canary at 5% → 25% → 100% without pushing a new iOS build. - iOS emits telemetry per scan (success, latency, parse-rate) back to a lightweight stats Lambda so the dashboard can render canary deltas in real time.
F3 — A/B harness in zapcopy-qa
- Extend
scripts/run_full_sweep.shwith a--providerarg that injects the relevant launch-arg override per run. - New dashboard page
/model-compare/[batchA]/[batchB]: paired seed-by-seed word-delta, latency, cost, and polish-notes concerns side-by-side. - Add a "provider" facet to the existing flow pages so a user can filter
/flow/videoby Gemini vs Claude with one click.
F4 — Provider adapters
- Write a single
OCRProviderPython interface and implement it for: Gemini 2.5 Flash (current), Claude Haiku 4.5, GPT-4o-mini. - Each adapter takes
{image, prompt, mode}→{text, rawEnvelope, tokens, elapsed}. The v2 Lambdas become thin callers of an adapter chosen by config. - Parallel canary: at 1% of calls, run both primary and canary providers, record the diff for offline analysis, return the primary's result to the user.
F5 — Alerting on provider drift
- Nightly cron: rerun the regression sweep against the current primary provider, store stats in
data/drift/<date>.json. - If parse-rate, fence-leak rate, or mean-latency shifts by > 2σ from a 30-day rolling baseline, open an issue and post to the #zapcopy-ops Slack channel.
- On alert, the runbook is: flip canary config → 0% primary, 100% backup; regression sweep the new primary; file follow-up with the drifted vendor.
Sequencing & dependencies
- F1 (provenance fields) lands first — cheap, unlocks F3/F5 and gives the landing-page page pricing data one source of truth.
- F2 (remote config) + F3 (A/B harness) can run in parallel; F3 needs F1 complete.
- E (landing page) is independent and can run in parallel with any F item.
- F4 (provider adapters) needs F2 complete so we have somewhere to toggle them to.
- F5 (drift alerts) last — needs the 30-day baseline from F1 to exist.
Each workstream gets its own brainstorming → spec → implementation-plan cycle before any code lands. This page is the pre-brainstorm brief only.