Complete operational provenance for ScamCheck (scamcheck.asquaresolution.com) from concept through production. Build phases, infrastructure changes, Gemini rate limit incident, auth configuration, CSS architecture decisions, and deployment milestones — consolidated as a queryable operational record.
This is the consolidated operational record for ScamCheck — a complete timeline of every significant infrastructure event, failure, migration, and deployment from initial concept through current production state. It is the authoritative product memory document for this system.
Product concept defined — AI scam detector targeting non-technical users in Southeast Asia. Unstructured text/URL input, plain-language verdict output
Firestore data model defined before UI: users/{uid}/checks subcollection, quota document, verdict schema. Deliberate sequence to prevent UI-driving-schema mistakes
Data model first principle — learned from TrustSeal
Stack decision: plain CSS over Tailwind — ScamCheck UI has < 10 distinct component types, Tailwind overhead not justified. CSS custom properties for theming at :root
React + Vite scaffold, plain CSS structure, Firebase project reused (ass-youtube-agent shared project)
Firebase Auth implemented — email/password + Google OAuth, scamcheck.asquaresolution.com and github.io subdomain added to Authorized Domains during setup (preventing auth domain failure from TrustSeal incident)
Gemini Cloud Function first pass — basic prompt, unstructured output, inconsistent JSON format across calls
Prompt redesigned to three-part structure: (1) role + embedded JSON schema, (2) signal taxonomy (phishing, urgency, domain patterns, financial requests, impersonation, logical inconsistencies), (3) edge case handling for users describing scams
Schema in prompt = dramatically improved output reliability
FAILURE: CSS specificity conflict — probability bar class-based color system bleeding into verdict card border color. Multiple component instances conflicting on same class selectors
FIX: Probability bar color moved to inline style (computed from probability number). Verdict card color moved to CSS custom property on card root element (--verdict-color). Class-based color conflicts structurally impossible in this model
Firebase Functions Node 22 runtime set in firebase.json (proactive — TrustSeal had just resolved the Node 18 crash failure 2 days prior). All functions stable on first deploy
Learned from TrustSeal's Node 18 failure — applied fix before hitting the failure
FAILURE: GA4 cross-subdomain session bleed. Both ScamCheck and TrustSeal shared GA4 property, cookie_domain not scoped to subdomain. Sessions from scamcheck were counted under trustseal and vice versa in early reports
FIX: cookie_domain set explicitly to scamcheck.asquaresolution.com in ScamCheck's gtag config. Session bleed eliminated. Later superseded by ecosystem integration (cookie_domain set to root domain)
FAILURE: Gemini free tier rate limit (429) hit during rapid testing. No UX handling — client showed indefinite spinner. Firebase Functions logs showed 429 from Gemini API. User had no signal that waiting would fix the problem
FIX: Cloud Function catches 429, returns { rateLimited: true } as HTTP 200 structured response. Client checks rateLimited flag, renders 'Rate limit reached — please wait a few seconds and try again', re-enables submit button. Spinner-forever UX eliminated
Second UX hardening: submit button disabled during in-flight request to prevent rapid successive submissions that trigger rate limit
Multi-stage loading indicator added: 'Analyzing input...' → 'Checking patterns...' → 'Generating verdict...' — reduces perceived cold start latency from 2–4s indeterminate wait to active progress
JSON parse failure handling added: { parseError: true } returned from Cloud Function on SyntaxError during JSON.parse(). Client displays 'Could not parse analysis result' with retry button
Full flow working end-to-end: submit → Gemini analysis → verdict display → Firestore history write. All failure modes handled (429, parse failure, server error)
GitHub Pages dist/.git worktree initialized: dist/ configured as separate git repo pointing to gh-pages branch of scamcheck repository
First production deployment: dist/ built with Vite, committed to gh-pages branch, pushed to GitHub Pages
404.html SPA redirect script deployed — client-side routing works on direct URL access and browser refresh on GitHub Pages
Custom domain DNS: scamcheck.asquaresolution.com CNAME → GitHub Pages. 2-hour propagation window observed before announcing live
DNS propagation lesson from TrustSeal/ScamCheck domain deployment
scamcheck.asquaresolution.com live: HTTPS active, SPA routing working, Firebase Auth stable, Gemini analysis working
GA4 cross-domain measurement configured for ecosystem integration. cookie_domain changed from scamcheck.asquaresolution.com to asquaresolution.com (root domain) — enables session stitching across all four properties
ScamCheck header nav and footer ecosystem block added — main site link, TrustSeal link, AI Execution Lab link. Deployed to gh-pages
GA4 DebugView verification — cross-domain session stitching confirmed: navigation from scamcheck to main site shows as one continuous session
ScamCheck architecture build case study published — full build narrative, Gemini prompt architecture documented, CSS decision rationale documented
ScamCheck operations review log published — deployment health, Firebase free tier status, GA4 cross-domain status reviewed
ScamCheck system document published — canonical operational reference with CSS architecture, Gemini prompt structure, risk table, deployment commands
ScamCheck product memory log (this document) published — complete operational timeline consolidated
| Dimension | State |
|---|---|
| Deployment | GitHub Pages gh-pages branch, manual dist/ git push |
| Custom domain | scamcheck.asquaresolution.com — HTTPS active |
| Firebase Auth | Email/password + Google OAuth — session stable |
| Authorized domains | scamcheck.asquaresolution.com + github.io subdomain |
| Cloud Functions | Node 22 runtime (explicit) — all invocations stable |
| Gemini | Three-part prompt structure — structured output reliable |
| Rate limit UX | { rateLimited: true } structured response — spinner-forever eliminated |
| GA4 | Scoped to root domain — cross-domain session stitching active |
| Firestore | Check history + quota per user — monthly reset operational |
Three direct failures + two proactively avoided from TrustSeal experience:
Failures hit and resolved:
Proactively avoided (learned from TrustSeal):
| Risk | Status |
|---|---|
| Gemini free tier 429 | Mitigated — rate limit UX in place; upgrade to paid tier when usage warrants |
| Gemini free tier daily quota | Monitored — not yet hit at current user volumes |
| Firebase cold start (2–3s) | Mitigated — multi-stage loading indicator in place |
| JSON parse failure | Mitigated — { parseError: true } handled on client |