Creative ideas + design notes
Commits with substantial prose (≥120 chars) — the rationale behind each move.
c1fd206 · 2026-07-27 · Admin: persistent live-view <-> admin-view toggle
Admin page sets a pcw.admin browser flag + shows a 'Live view' pill (-> /). Live customer
pages (via decorate) show a 'Admin view' pill (-> /admin) ONLY when that flag is set, so the
logged-in admin can always flip both ways while real customers never see it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5ff3476 · 2026-07-27 · Activate Google review CTA: set verified place_id (looked up via Places API)
Looked up the REAL place_id via the Places API (GOOGLE_PLACES_API_KEY, $0.017): returned
name 'Prestige Car Wash' + addr '7601 Reseda Blvd, Reseda, CA 91335' — verified match, not a
guess. Set places.json place_id=ChIJ5Wj7RtKbwoAR-3obIxcKE1g, which activates the honest
'Leave us a review on Google' CTA (writereview deep-link) in the trust block.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4937b3b · 2026-07-27 · Drop non-existent apex: prestige.agentabrams.com is the permanent home
Steve 2026-07-27: prestigehandcarwash.com does not exist — keep the *.agentabrams build only.
Purge stale apex references: places.json website + robots.txt Sitemap -> prestige.agentabrams.com,
and rewrite the SITE_ORIGIN comment (no longer an interim 'flip after cutover' — it's permanent).
All served canonical/og/sitemap/JSON-LD already resolved to agentabrams; this cleans the data.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
e694e62 · 2026-07-27 · Analytics-lite: first-party, cookie-free conversion tracking + admin card
Self-hosted aggregate counters (pageview / form_start / form_submit) -> honest view→book
conversion, surfaced on the admin Overview. No cookies, no IP, no PII, no consent banner, no
GA. sendBeacon pageview (all customer pages via decorate), funnel events on the contact form.
Contrarian FIX-FIRST: added rateLimit(60/min) to the public /api/track (was an unauthenticated
unrated disk-write), atomic temp+rename write (no corruption), and the conversion shows as
~X% (est.) so its approximation is visible, not buried. Bounded to last 120 day-buckets.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
acd004a · 2026-07-26 · A11y + perf pass: focus-visible, reduced-motion, aria labels, font preconnect
DTD unanimous 5/5 (A). pcw.css: visible :focus-visible outlines on all controls, .sr-only
utility, prefers-reduced-motion block. Hamburger buttons: aria-label + real aria-expanded
toggle (all 4 page types). FAQ decorative +/- marker aria-hidden. decorate(): gstatic font
preconnect (crossorigin, deduped) on every page. Contrarian GO; applied its fix — the JS
form-success scrollTo now honors prefers-reduced-motion (CSS scroll-behavior didn't cover it).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2062a31 · 2026-07-26 · Admin: lead worklist (click-to-call/email + follow-up-first order) + CSV export
DTD unanimous 5/5 (A). Leads tab: click-to-call (tel:) + click-to-email (mailto:) on each
card, a 'Needs follow-up' default sort (oldest-cold first, then new, contacted, done), and a
GET /api/admin/leads.csv export (behind requireAdmin, CSV/formula-injection neutralized) with
an Export button. Contrarian GO; applied its two quality fixes: telDigits returns '' for
non-valid lengths (garbage phone renders as plain text, not a dead tel: link) and the worklist
tiebreak surfaces the longest-waiting cold lead first. (Known minor, logged: leads localStorage
sort-index shifts once post-deploy — self-corrects on next pick.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7c66f9d · 2026-07-26 · Harden booking form: honeypot + validation + dupe-guard + resilient client
DTD unanimous 5/5 (B). POST /api/contact: honeypot (non-demographic field name so autofill
can't false-drop a real lead; drops are logged for audit), human-readable validation
(name/phone/email), and a 120s duplicate-submit guard. contact.html: double-submit lock,
client validation mirror, network-failure handling, consistent red/green result states.
Contrarian FIX-FIRST resolved: renamed honeypot company->b_confirm (autofill-safe),
console.warn on drop (observability), fixed error-state background tint.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
61afb84 · 2026-07-26 · Path B: self-canonicalize to prestige.agentabrams.com (stop feeding GoDaddy) + ship guides
Steve chose B. New SITE_ORIGIN constant drives all self-referential SEO (canonical, og:url,
sitemap, article URLs, AutoWash.url) to prestige.agentabrams.com — the domain this app is
actually served from — instead of the apex prestigehandcarwash.com, which serves a SEPARATE
GoDaddy site. Resolves the contrarian NO-GO by its own stated A-grade bar. Also: og:type=article
on individual guide pages. Unblocks the held /guides deploy. Flip SITE_ORIGIN to the apex once
its DNS is cut over to Kamatera. (publisher.logo intentionally omitted — no real logo asset.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2cec353 · 2026-07-26 · Guides: evergreen car-care articles (/guides + 3 posts) — BUILT, DEPLOY HELD
DTD A (3/2). 3 honest server-rendered guides w/ BlogPosting+BreadcrumbList schema,
internal links to services/booking, sitemap + homepage-footer link. Head-injection
refactored into shared decorate(). Locally verified (200s, schema, 404, sitemap, no
fabricated stats). DEPLOY HELD: contrarian NO-GO — site-wide canonical points at
prestigehandcarwash.com which serves a SEPARATE GoDaddy site, so shipping SEO pages
hands authority to GoDaddy. Domain-identity/DNS decision surfaced to Steve (gated).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d13f501 · 2026-07-26 · Discovery: honest 'find us & review' trust block (real off-site profiles)
DTD A (4/4 valid). Server-renders REAL Google Maps + Yelp + Instagram links from places()
into the homepage; no star number reproduced on-page (routes to live profile — no drift).
Contrarian FIX-FIRST: (1) review-solicitation CTA gated on a verified Google place_id and
routes to Google's writereview dialog — NOT Yelp (Yelp filters solicited reviews); currently
place_id is empty so the CTA is inert until set. (2) whole section stripped server-side if no
real profiles (no floating heading). rel=noopener (follow, for sameAs authority).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9d17487 · 2026-07-26 · Services: per-service 'Book this' deep-links pre-select the service on /contact
DTD A (3/5). Service cards link to /contact?service=<name>; contact form pre-selects
the matching real option (exact-match, never DOM-injected). Contrarian FIX-FIRST:
escape option name/price (quote/angle-bracket corruption), suppress service pre-select
under ?intent=membership (no contradictory form state). Canonical verified: ?service=
variants already canonicalize to clean /contact (no duplicate-URL risk).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0760139 · 2026-07-26 · Mobile: persistent Book + click-to-call action bar on customer pages
DTD unanimous (5/5) A. Server-injected via pageHtml, CSS-only <=640px, no JS.
tel: from real places().phone (single source, no fabrication). Contrarian FIX-FIRST:
Book button is page-aware — scrolls to #f on /contact instead of self-linking to top.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cc20300 · 2026-07-26 · FAQ: booking-objection accordion + FAQPage JSON-LD, single-source & server-rendered
DTD panel picked A (3/2 over friction-reducers); dissent folded in — answers ARE
the booking objections. faqs() is one source for both the visible <details> accordion
(server-rendered into #faqList, native <details>, zero JS) and the FAQPage schema, so
visible content matches structured data. Contrarian FIX-FIRST resolved: was client-only
render (Google manual-action risk) -> now server-rendered in crawler HTML.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
557b5cd · 2026-07-22 · Add HyperFrames promo videos to the growth-center backend
New 🎬 Promos admin tab surfacing the four HyperFrames-generated brand films
(full tour, story cut, 30s motion promo, backend demo) staged under
media/promos/. Backed by data/promos.json + /api/admin/promos (normalized URLs,
mm:ss, on-disk ready flag). Each promo streams on demand (preload=none) and can
be handed to Compose & Post as an attachable asset in one click. Large .mp4s
gitignored (regenerable from the sibling video pipelines); posters + manifest
tracked. Health/Overview now counts promos.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
e65a96d · 2026-07-19 · admin: Compose & Post tab — create socials + post from assets in one place
Local scaffold only (live build owned by another session; NOT deployed).
Feature — a new '✨ Compose & Post' command-center tab that turns the existing
media library + best-times into a one-screen social workflow:
- asset picker over /media (real photos + service videos, videos auto-paired
to their poster stills)
- one-click caption templates (data/social-templates.json) with {service}/{blurb}
fill-in from the real services, + click-to-add hashtag sets
- pick platforms (IG/FB/Google/TikTok/Nextdoor/Yelp) → best-time hint per platform
from best-times.json + one-click 'Open <network>' into each native composer
(auto-copies the caption), Copy caption, Download asset, Save draft
- DRAFT-ONLY by rule: never auto-posts; drafts persist to reports/social-drafts.jsonl
and list back as a mini content calendar
New APIs: GET /api/admin/media, /api/admin/social/templates, /api/admin/social/drafts,
POST /api/admin/social/draft (all admin-gated, read-only media scan, append-only drafts).
Refactor / fixes:
- sortServices 'featured' NaN bug (undefined-featured → unstable sort) → boolean coerce
- enc() now escapes & > " (not just <) — hardens the lead-render surface
- Overview 'Google Places' tag now reflects real credential presence, not a hardcoded 'mock'
Verified locally on :9911: syntax OK, all 4 APIs return correct data (18 assets,
6 platforms/5 templates, draft save+list), admin page serves with the tab, auth gate 401s.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>