FFrameCraft Ops

QA

What to QA next

A page-by-page worklist for the QA reviewer (no technical background needed). Switch stores with the tabs. The developer testing guide below is the deeper method. Driven by docs/qa/*.md.

Testing guide for future work — Migration (developers)Show

What should be tested and verified. This is the reusable method behind the per-page checklists below.

SSR / body-content

  • Disable JavaScript in the browser, reload. The H1, body prose, product/price summary, and review content must still be visible. Blank with JS off = FAIL (invisible to AI crawlers).
  • View Source (Ctrl+U — the raw HTML, not the inspector): the main copy text is present in the served HTML.

Section parity vs the original — at desktop AND mobile

  • Every section in the original is present in the migration. Write the original's sections top-to-bottom (hero, trust row, each content block, specs, gallery, FAQ, related, CTA, footer) and tick each off on the migrated page. Nothing missing.
  • Section order matches the original, OR the difference is an approved redesign (e.g. split-hero standardization), not an accidental drop/reshuffle.
  • Per-section content matches — headings, body copy, images, links, and counts (gallery items, FAQ entries, related links, nav items) are equivalent. No truncated, placeholder, or lorem text.
  • No stray/orphan sections the migration introduced that don't belong.
  • Mobile (390px): repeat the whole section-by-section pass. Sections may stack/reflow, but all must be present and legible — no overlap, no horizontal overflow, hamburger nav opens and lists the expected items.
  • Spacing, colors, fonts, and component styling read as the same brand at both widths; tablet (768px) spot-check shows no broken layout between breakpoints.
  • All images load (no broken/placeholder), correct aspect ratio; the LCP hero is present and not shifted (CLS).

Content & copy compliance

  • H1 present, correct, single per page; heading order has no skips (H1 -> H2 -> H3).
  • No em dashes, no exclamation marks, no emoji in visible copy.
  • No banned words (discover, unlock, leverage, robust, seamless, transform, elevate, journey, dive into, embark, plethora, myriad, game-changing, revolutionary).
  • Glazing language is "frame shop grade acrylic" / "non-glare acrylic" only — no UV claims, no museum/conservation glazing.
  • Turnaround reads "3-5 business days" for in-cap sizes; over-32x40 shows freight/local-pickup language.
  • No star ratings / review counts in STATIC copy (only the dynamic widget shows them).
  • "picture framing" used as the lead descriptor (not "custom framing"); facility-anchored phrasing ("made at our Somerset production facility").

SEO (view-source + Rich Results Test)

  • <title> present and ends with | CustomPictureFrames.com.
  • <meta name=description> present, unique, ~150 chars.
  • <link rel=canonical> present, self-referential, points at www.custompictureframes.com (NOT localhost/preview host), clean path (no query params).
  • OG tags (og:title, og:description, og:image, og:url) present; og:image resolves.
  • JSON-LD present with the right @type for the page type; paste into Google Rich Results Test -> 0 errors.
  • Aggregate Rating node present only where a real rating exists; self-omitted when unavailable.

Links & navigation

  • Header/footer nav links work; breadcrumb correct.
  • In-body internal links resolve (no 404); page is not orphaned (>=1 inbound link from a hub/related block).
  • Designer CTA present where expected (size/color/style/specialty pages); deep-links to the designer with the right preset.

Functional

  • Any interactive element works (accordions, carousels, filters, forms).
  • Forms validate + submit (and are honeypot / rate-limit protected).

Console & network

  • Browser console: 0 errors, 0 warnings.
  • Network tab: no failed (4xx/5xx) requests; no 429s under a normal click-through.

Accessibility

  • Keyboard-only: tab order logical, focus ring visible, skip-link works, no keyboard trap.
  • Run axe DevTools (or the Playwright axe step): 0 violations.
  • Tap targets >=24px (target 44px) on mobile controls (carousel dots, option rows, info icons).

Cross-browser / device

  • Chrome + Safari + Firefox (desktop); Safari iOS + Chrome Android (real or emulated).

Redirect retention (once Epic H is live for that route)

  • The legacy .html URL 301s to this page (curl: 301 -> Location -> destination 200).

How to test

  1. 1.Run the AI-bot for testing — codebase level.
  2. 2.Manual testing across devices / browsers after dev deployment, in the order above.
  3. 3.Hand off to the QA team for the Framing Industry Standards logic check.

CustomPictureFrames.com

2 blocking gates open

Every page — verify these first

0/1Pending

On every page below, confirm: opens with no error; the big title at the top matches the topic; scrolling top-to-bottom shows real text and images (no blank gaps, no "lorem", no broken images); on a phone it stacks neatly with no sideways scroll and the menu opens; every link and button goes to a real page (no "page not found").

  • I've read these standard checks and will apply them to each page below

/canvas-prints

0/2Pending
  • Standard checks pass
  • The FAQ section opens and shows real questions and answers

/canvas-stretching

0/1Pending
  • Standard checks pass

/giclee-printing

0/1Pending
  • Standard checks pass

/large-format-printing

0/2Pending
  • Standard checks pass
  • Any prices shown read correctly

/custom-mats

0/1Pending
  • Standard checks pass

/photo-mats

0/1Pending
  • Standard checks pass

/framed-chalkboards

0/1Pending
  • Standard checks pass

/framed-cork-boards

0/1Pending
  • Standard checks pass

/framed-dry-erase-boards

0/1Pending
  • Standard checks pass

/framed-wall-art

0/1Pending
  • Standard checks pass

/magazine-sizes-guide

0/2Pending
  • Standard checks pass
  • The size tables/lists show real numbers (no blanks)

/photo-restoration

0/1Pending
  • Standard checks pass

/sports-photo-framing

0/1Pending
  • Standard checks pass

/puzzle-glue-sheets

0/1Pending
  • Standard checks pass

/floater-frame-for-panel-painting

0/1Pending
  • Standard checks pass

/scarf-and-sash-framing

0/2Pending
  • Standard checks pass
  • Glazing text reads "framer's grade acrylic" (a shadow box, so no non-glare/UV/museum wording)

After this batch — queued next

0/1Pending

Once the 16 pages above are signed off, the next batches are the 8 sports display cases, the 5 category landings (wood/large/ornate/rustic/vintage), the 9 flat specialty pages, and the 9 shadow-box/keepsake pages. (/metal-picture-frames and /designer are on hold — see Issues.)

  • Batch 1 (above) signed off, ready to load the next batch

Launch gate — pricing parity (Wave 10)

4/4GO

Prices must match the live site to the cent. Now verified by an automated harness rather than by hand: 252 golden values snapshotted from the LIVE CPF engine (original-cpf/shared/schema.ts) and asserted against the migrated one — every moulding SKU, the 4x4 minimum, 8.5x11 decimals, the 32x40 cap, both oversize bands, 40x60 freight, 80 mat and 12 print configs. All match. Re-run: `cd packages/core && npx vitest run pricing-parity`.

  • Designer built
  • Configs compared to the cent (252, automated)
  • Over-cap + oversize bands verified
  • Harness proven non-vacuous (perturb a lever, it fails)

FLAGSHIP_MIGRATION_PLAN.md · Wave 10

Launch gate — /designer and /cart

5/7In progress
  • /designer renders, prices live, and reaches the cart
  • Body + Product schema present with JavaScript OFF
  • Legacy size links land on the right size (`/designer?w=16&h=20` prefills 16x20)
  • Checkout payload proven: price in cents, packing block, storeCode CPF
  • Section order matches the source: designer above the fold on mobile, hero above it on desktop
  • A REAL test order lands in Shopify Admin (blocked on the variant id env — see variant-id-env)
  • Human side-by-side against the live site on a phone and a desktop

FLAGSHIP_MIGRATION_PLAN.md · Waves 10 + 13

Launch gate — the 39 specialty designers

3/6In progress

Every specialty landing page now embeds its real designer (the "being wired up" placeholder is gone everywhere). Automated sweep covers one page per distinct designer.

  • All 39 pages embed a real designer; zero placeholders
  • Pages still serve their prose with JavaScript off, and stay static
  • No landing page rewrites its own URL when you use the designer
  • Human pass: does each page's designer match the live CPF page (styling, sections, mobile)?
  • /custom-mats is currently the REDUCED mat designer, not CPF's v2 (see mat-v2-missing)
  • /heart-frames and the canvas traditional/unframed paths are not migrated yet

FLAGSHIP_MIGRATION_PLAN.md · Wave 11

CustomFrameSizes.com

/ (homepage)

0/2Pending
  • Standard checks pass
  • Single big title (H1); trust row + designer + sections all present

/designer

0/2Pending
  • Standard checks pass
  • The frame designer loads; changing size/mat/glazing updates the live preview and price

a frame product page (/frames/<any>)

0/2Pending
  • Standard checks pass
  • Designer present; price shows; add-to-cart works

a specialty page (e.g. /jersey, /diploma)

0/2Pending
  • Standard checks pass
  • The specialty designer loads and prices correctly

Learn + company pages (/learn, /about, /contact, policies)

0/2Pending
  • Standard checks pass
  • Contact form: submit it and confirm the message actually arrives (currently it does NOT — see issue cfs-contact-form)

Measured checks that have never been run

0/4Pending

Not page content — these tools must actually be run once before launch.

  • Lighthouse >=90 on /, /designer, a PDP, a category page
  • axe / WAVE accessibility scan: 0 violations
  • Screen-reader pass (designer -> cart)
  • Real-device mobile pass at 375px

Blocked until infra is wired (do last)

0/3Pending
  • Real Shopify checkout end-to-end (needs Cart Transform + BFF + prod env)
  • Cart line price == displayed price; packing-slip attributes correct
  • Preview deploys return noindex (needs the staging gate first)

ShadowboxFrames.com

Fix first (blocks most QA)

0/3Pending
  • Add the missing media API routes (upload/export/upscale/AI) or the flows will 404
  • Set the CDN env vars (or images will be broken across every page)
  • Provision Shopify (or checkout stays a mock)

/ (homepage) + hub pages

0/2Pending

Content/SEO QA — safe to do now.

  • Standard checks pass (opens, correct title, real text/images, phone-friendly, links resolve)
  • Replace the placeholder gallery/achievements content before sign-off

Shadow-box + picture-frame category pages

0/2Pending
  • Standard checks pass across a sample of gateway/category pages
  • Images load (confirms CDN env is set)

Blog + resources

0/1Pending
  • Standard checks pass on a sample of blog posts + resource articles

Once media + Shopify are fixed

0/3Pending
  • Designer -> upload artwork -> add to cart works
  • Real Shopify checkout end-to-end with the SBF store code
  • Fix the broken default social-share image

Platform & Shared

2 blocking gates open

Cart Transform — pricing to the cent

1/5In progress
  • Unit test present (_price_cents -> price, _line_title)
  • Configurator price == cart price == checkout price across sizes/styles/mats/glazing
  • 8-case matrix: single / multi / qty / over-cap / min / complex / persistence / mismatch
  • Tax + discount correct on overridden prices
  • An invalid/tampered price line is rejected (needs the signed-payload fix — see issue P-1-unsigned-price)

Checkout branding

1/3In progress
  • BFF sets brand attributes on cart create; the extension reads them
  • Matrix: each store shows its own logo; unknown -> fallback; image-fail -> safe state
  • Mobile/desktop; bundle under budget; no cross-brand contamination

API health

1/4In progress
  • /api/health + /api/health/db exist
  • /api/health/db green once the database URL is set
  • CORS allows every storefront origin — add the flagship origin (see issue P-6-cors-flagship)
  • orders/create webhook is signature-verified and idempotent

Customer accounts (per phase, when creds land)

0/4Pending
  • Sign in / out round-trip; account is created on first login
  • Save a design, reload, it restores exactly; soft-delete hides it
  • Logged-in photo upload attaches to the account
  • Security: signed webhooks, encrypted sessions, per-store data isolation