TrustSeal (trustseal.asquaresolution.com) — AI-powered website trust verification tool. React/Vite/GitHub Pages frontend, Firebase Auth + Firestore backend, Firebase Functions v2 for Gemini AI analysis and Razorpay webhook handling. Subscription-based monetization via Razorpay (INR). Node 22 runtime required.
TrustSeal is an AI-powered website trust verifier at trustseal.asquaresolution.com. Users submit a URL and receive a structured trust verdict — trust score (0–100), verdict label (Verified / Caution / Suspicious / High Risk), detected signals, and a recommended action. The system is live on a zero-fixed-cost architecture: GitHub Pages for hosting, Firebase free tier for auth and database, Gemini free tier for AI analysis, and Razorpay pay-per-transaction for payments.
dist/.git worktree pointing at gh-pages branchtrustseal.asquaresolution.com via CNAME in dist/404.html redirect pattern (no URL rewrite capability on GitHub Pages)vite.config.ts base: '/' — required for custom domain at root pathusers/{uid}/
checks/ # subcollection
{checkId}/
url: string
signals: object # collected domain/SSL/WHOIS signals
verdict: {
score: number # 0–100
label: string # Verified | Caution | Suspicious | High Risk
signals: Array<{positive: boolean, category: string, description: string}>
action: string
}
createdAt: timestamp
quota/
current/
checksThisMonth: number
tier: 'free' | 'premium'
resetDate: timestamp
subscription/
{subId}/
razorpaySubscriptionId: string
status: string
currentPeriodEnd: timestamp
| Function | Trigger | Purpose |
|---|---|---|
analyzeTrust | HTTPS callable | Receives URL + signals from client, calls Gemini, writes result to Firestore, returns verdict |
createSubscription | HTTPS callable | Creates Razorpay subscription, returns subscription_id to client |
razorpayWebhook | HTTPS request | Receives Razorpay events, verifies signature, updates Firestore tier |
All functions run on Node 22 runtime. firebase.json:
{
"functions": {
"source": "functions",
"runtime": "nodejs22"
}
}
onAuthStateChanged listener manages client auth statetrustseal.asquaresolution.com is in Firebase Console → Authentication → Authorized Domainsusername.github.io subdomain also added during developmentDocumented failure: Omitting the custom domain from Firebase's Authorized Domains list causes session loss on every page refresh — UNAUTHORIZED_DOMAIN in the network layer, no visible UI error. Fix: add domain to Firebase Console → Authentication → Settings → Authorized Domains.
User clicks "Upgrade"
→ Client calls createSubscription Cloud Function
→ Cloud Function creates Razorpay subscription via Razorpay API (server key)
→ Cloud Function returns { subscriptionId }
→ Client opens Razorpay Checkout modal with subscriptionId + client key
→ User completes payment
→ Razorpay fires subscription.charged webhook
→ Webhook Cloud Function: verifies signature → updates Firestore tier: 'premium'
→ Client's onSnapshot listener picks up Firestore change
→ Premium features unlocked without page reload
Documented failure: Razorpay test client key + live server key causes silent failures — checkout modal opens but no webhook fires. Both keys must be from the same mode simultaneously.
Source branch: main (React + Vite source)
Deploy branch: gh-pages (built output only)
npm run build # Vite → dist/
cd dist
git add -A
git commit -m "deploy $(date +%Y-%m-%d)"
git push origin gh-pages
dist/ has its own .git pointing at gh-pages. dist/ is in main's .gitignore.
Cloud Functions:
firebase deploy --only functions
After any functions deploy: verify in Firebase Console → Functions → Logs that the first invocation completes without errors. Deploy success ≠ execution success.
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Gemini free tier quota exhaustion | Medium | High — all trust checks fail | Upgrade to paid tier; implement per-user rate limiting |
| Firebase Functions cold start | High | Low — 2–4s latency on first call | Multi-stage loading UX; acceptable for trust verification use case |
| Razorpay webhook delivery failure | Low | High — premium tier not activated | Webhook retry is automatic; add Firestore fallback reconciliation |
| Node runtime version gap | Low (mitigated) | High — all functions crash | Explicit nodejs22 in firebase.json; document in deployment checklist |
| Firebase Auth domain unauthorized | Low (mitigated) | Medium — session loss | Custom domain in Authorized Domains list; verify on each new domain |