Ribbit.Deals — Functional Specification
v1.0 · August 13, 2026 · Maintained alongside development — updated every sprint · Companions: Architecture · Data Layer · App UI
0. Purpose of This Document
This is the single running reference for what Ribbit.Deals does and why. It travels alongside development: every speed bump, question, and resolution lands here so decisions are made once and remembered forever. Anything marked LOCKED is founder-approved; RECOMMENDED is the team's position awaiting sign-off; OPEN needs a decision.
1. System Overview
Ribbit.Deals is a performance-based local deals platform for Utah, delivered as a Progressive Web App (no app stores) with a public marketing website. Local businesses publish offers; consumers discover them nearby and redeem them in person; redemption is verified by a two-factor handshake (GPS presence + placard scan); businesses pay a performance fee only on verified redemptions, alongside a one-time activation and a per-location operations fee.
- Platform: PWA (installable from browser) + responsive website · MySQL 8 data layer (deployed, v1.1) · PHP application layer (Sprint 6+).
- Environments: staging at ribbit.pixrite.com (current), production domain at launch.
- Core loop: business posts offer → consumer discovers → in-store verified redemption ("RIBBIT") → consumer earns rewards → business pays on results → loop repeats.
2. Audiences & Experience Isolation LOCKED
Two audiences, two completely separate experiences, one door between them.
- Consumer UX (default): home, For Deal Hunters, How It Works, Locator, About, Get the App, and the consumer app screens. Playful "Vegas" register; Yellowtail script accents permitted.
- Business UX: landing, enrollment, pricing, login, dashboard, offer creation. Professional register; no script font; no sunburst.
- The single door: the "I'm a Business Owner" button on consumer pages. The business UX contains zero links back to the consumer UX; its logo homes to the business landing page.
- Voice: business-side copy never uses the word "user" — owners are addressed as beneficiaries and partners. Consumers are "deal hunters."
- Enforcement: an automated link audit runs on every site update; consumer pages may reference the business UX only via the door, business pages may reference the consumer UX never. Current status: PASS across all 16 pages/screens.
3. Consumer Journey
3.1 Sign-up LOCKED
- Exactly four fields: name, mobile, email, password. Nothing else at sign-up; enrichment happens in-app after value is delivered.
- SMS deal alerts: explicit opt-in checkbox, unchecked by default, consent timestamp recorded (
users.sms_opt_in_at), STOP/HELP honored.
- Privacy promise (founder language) displayed at sign-up: data used only by Ribbit.Deals to improve the service and by redeemed-at businesses to validate redemptions and improve offers; never sold.
3.2 Discovery
- Map-first with list toggle; offers sorted by distance; filters: category, distance radius. Featured placement slot exists (promotion rules: Phase 2).
- Website Locator mirrors discovery for pre-install visitors: A–Z, category, city filters + "Near Me" geolocation sort (haversine). Optionally reads live DB via read-only endpoint.
3.3 Redemption
See Section 5 — the verification handshake is the product's heart.
4. Business Journey
4.1 Enrollment LOCKED
- Five steps: Business → Locations → Pricing → Billing & Agreement → Confirmation. Progressive capture (each step saves; abandonment recoverable).
- Pricing is never published publicly; it is revealed at Step 3, computed from location count. (Gated-pricing rationale: pricing may evolve during early market entry; public numbers create anchor problems.)
- Step 4 records agreement acceptance: checkbox + typed legal name + timestamp + agreement version (
subscriptions).
- Live within 24–48 hours of verification; placard kit printed and delivered as part of activation.
4.2 Dashboard
- Daily glance: views, redemptions, fees accrued. Per-location filter on all reporting.
- Offer controls: pause (one tap, instant), edit, per-offer stats. Recent redemptions list with Void action (Section 7).
- Month-to-date fee strip (operations + performance) always visible; statement generated on the 1st.
5. Redemption Verification — the Placard Handshake LOCKED
Two independent factors, no business-side hardware or software:
| Factor | Mechanism | Defeats |
| 1. Presence | Consumer device GPS validated inside the offer's geofence at the moment Redeem is tapped (location captured only at that moment — no background tracking). | Couch redemptions, remote code sharing |
| 2. Physical token | Consumer scans the business's counter placard QR (per-location qr_token, rotatable if compromised). Manual fallback: printed POND-XXXX short code. | GPS spoofing alone, drive-by scans |
- Liveness screen ("RIBBIT"): animated frog + running real-time clock + word of the day — defeats screenshot reuse; a cashier verifies in two seconds by glancing at motion + clock.
- Trust valve: the business can void any redemption within 48 hours from the dashboard (Section 7); voided redemptions are never billed and reverse earned points.
- Failure paths: GPS unavailable → placard scan alone with elevated logging; camera unavailable → short code entry; both unavailable → redemption not possible (by design — verification is the product).
6. POS Integration — Decision Record RECOMMENDED: DO NOT INTEGRATE (v1)
Question raised (Aug 13 stakeholder meeting): should Ribbit.Deals integrate with common point-of-sale systems (Square, Clover, Toast, Lightspeed, …) to verify purchases at the register?
Team recommendation: no POS integration in v1. The placard handshake already delivers verified, in-person redemption without it. Integration would add:
| Cost Dimension | Placard Model (current) | POS Integration |
| Initial development | Complete (designed & prototyped) | Per-platform APIs, OAuth flows, webhooks — each POS is its own project; several add partner certification queues measured in weeks-to-months |
| Launch timeline | On track for Black Friday | Certification + per-platform QA realistically pushes launch into next year |
| Ongoing maintenance | None (a laminated card) | Every POS version change, API deprecation, and breaking update, forever — multiplied by the number of platforms |
| Support burden | Reprint a card | "My POS won't connect" tickets we cannot fix ourselves; failures blamed on Ribbit.Deals regardless of fault |
| Merchant onboarding | Zero technical steps — place card on counter | Per-merchant setup, permissions, staff training; excludes cash-only and legacy-register businesses entirely |
| Sales pitch impact | "Your entire equipment stack is a laminated card" | Pitch dies; we become "another system to install" |
What POS integration would buy: transaction-amount capture (basket size analytics) and marginally stronger purchase proof. Mitigations without it: the 48-hour void window handles no-purchase scans; basket analytics can be a Phase 2+ opt-in (e.g., receipt total entry or a single-platform pilot) if merchants demand it — decided from data, not speculation.
Status: Recommended, pending founder confirmation at the Aug 14 meeting. On confirmation this moves to LOCKED and the mitigation notes migrate to the Phase 2 backlog.
7. Offers, Caps & Void Rules LOCKED
- Offer anatomy: title, description, image, type (% / $ / BOGO / freebie), value, participating locations, geofence radius (100–2,000 m), schedule, max redemptions, budget cap.
- Caps are guarantees: enforced in the redemption write transaction (row-lock counter check); auto-pause the moment either cap is reached. The creation form shows the worst-case dollar figure live.
- One redemption per person per offer unless the offer states otherwise.
- Void window: 48 hours, dashboard action, reason optional; voids reverse points and are excluded from invoicing. Fee amounts are snapshotted per redemption (
redemptions.performance_fee_amount) so historical bills never shift.
8. Rewards, Badges & Referrals LOCKED
- Points: earned on verified redemptions; append-only ledger (
points_ledger) — balance is derived, adjustments are entries, history is immutable.
- Badges (v1 set, seeded): First Ribbit, Pond Hopper, Chorus Starter, Regular.
- Referrals: personal code; both parties rewarded when the referred person completes their first verified redemption; self-referral and duplicate-device abuse blocked.
- Earn rates and unlock thresholds: values OPEN — see Section 12.
9. Pricing & Billing Model LOCKED (structure) OPEN (amounts)
- Three components: one-time activation · per-location operations fee (monthly, or annual at a discount) · flat performance fee per verified redemption.
- Never published publicly; revealed at enrollment Step 3, computed from location count.
- Invoicing: monthly statement on the 1st; every performance line traces to a redemption record; one invoice line per redemption (unique constraint — double-billing is structurally impossible).
- Dollar amounts: required from founders before Sprint 7 billing work. Enrollment shows placeholders by design until then.
10. Privacy, Security & Non-Functional
- Location privacy: captured only at redemption moment; no background tracking. Stated in EULA §6 and Privacy Notice.
- Data promise: never sold; business sees a consumer's data only for redemptions at that business, for validation and offer improvement.
- Money handling: all currency stored as integer cents; payment card data never touches our servers (processor-hosted fields, Stripe planned).
- Auth: password hashing (bcrypt), rate-limited login, single shared auth for business web + dashboard (
business_users pivot).
- Legal: EULA v0.2 (23 sections), Business Participation Agreement, Privacy Notice — drafted, awaiting Utah counsel; arbitration-vs-courts decision flagged for counsel + founders.
- Accessibility & motion: reduced-motion honored on all animations; focus states on all interactive elements.
11. Decision Log
| Date | Decision | Status | Rationale (short) |
| Jul 2026 | Verification = GPS + placard scan (no hardware) | LOCKED | Two-factor proof, zero merchant cost, zero staff training |
| Jul 2026 | Pricing gated to enrollment Step 3; never public | LOCKED | Early-market flexibility; computed per location count |
| Jul 2026 | Consumer sign-up limited to four fields | LOCKED | Conversion; enrich later in-app |
| Jul 2026 | 48-hour business void window | LOCKED | Trust valve for no-purchase scans; billing integrity |
| Aug 2026 | Consumer & business experiences fully isolated; single door; "beneficiary" voice | LOCKED | Founder direction; each audience addressed in its own register |
| Aug 2026 | Charity/community giving deferred | LOCKED | Phase 2; keeps v1 story and billing simple |
| Aug 2026 | Sunburst design direction (Round 1 Option B), ticker under nav | LOCKED | Founder selection after two option rounds |
| Aug 13 | No POS integration in v1 — placard model stands alone | RECOMMENDED | Section 6 — cost, timeline, support, onboarding, pitch |
12. Open Questions
| # | Question | Needed By | Owner |
| 1 | Fee dollar amounts: activation, per-location monthly + annual, performance fee | Sprint 7 start (Aug 25) — blocks billing build | Founders |
| 2 | POS decision — confirm Section 6 recommendation | Aug 14 meeting | Founders |
| 3 | Points earn rate + unlock thresholds + referral reward values | Sprint 7 (rewards build) | Founders + team proposal |
| 4 | Dispute resolution: arbitration vs. courts (EULA §20) | Attorney review | Counsel + founders |
| 5 | Video scope: confirm list, lengths, and delivery dates for the added videos | Aug 14 meeting — affects sprint capacity | Founders + team |
13. Changelog
| Version | Date | Changes |
| v1.0 | Aug 13, 2026 | Initial living spec: consolidates all decisions and prototyped functionality through Sprint 5; adds POS integration decision record; opens questions register. |
How this document is used: updated every sprint (minimum) and whenever a decision lands. Speed bumps become Open Questions; answered questions become Decision Log entries; the changelog keeps the paper trail. If it isn't in here, it isn't decided.