All projects LIVE PRODUCT · CHILE

PortalBeneficios.cl

A two-sided offers marketplace, designed and built solo: nine services on Google Cloud serving a web portal, an iOS app, and a conversational assistant — plus a publisher side where brands pay to reach users with verified attribution.

FastAPINext.js 15Cloud RunFirestoreMongoDBPlaywrightCompute EngineExpo / React Native

FROM SIDE PROJECT TO MARKETPLACE

One brand's promotions, then everyone's.

PortalBeneficios.cl started as a way to aggregate bank and retail promotions scattered across dozens of Chilean providers into one place. Scrapers and a geo-locked extractor pull raw offers; a normalization pipeline turns inconsistent brand names into a clean catalog; and that catalog is served through a web portal, an iOS app, and a chat assistant.

The second half of the platform is what turns it into a business: a publisher portal where each brand gets an account scoped to its own catalog entry, buys credits, and publishes its own offers — justified by verified proof of purchase (click tracking online, QR scans in physical stores) rather than just impressions.

Designed, built, and operated solo — architecture, backend, frontend, mobile, and infrastructure.

9services, one GCP project
3client surfaces: web, iOS, chat
2sides of the marketplace
Built forreal usage, not a demo.

SYSTEM DESIGN

Nine services, one Google Cloud project.

Scheduled extraction feeds Cloud Storage; a normalization service cleans the catalog into Firestore; a set of Cloud Run APIs serve it to three different client surfaces.

PortalBeneficios.cl architecture: extraction feeds Cloud Storage, admin-service normalizes into Firestore, Cloud Run APIs serve the web, iOS, and chat clients, and publisher-service handles brand monetization. EXTRACTION STORAGE CORE SERVICES CLIENTS DATA STORES offers-scraper Playwright scrapers claro_extractor GCE VM · Chile GCS — raw offers object storage handoff offers-consolidator merges raw files GCS — processed unified catalog JSON admin-service brand normalization + review backend-api serves catalog to clients agent-service semantic search + LLM chat auth-service JWT auth + roles publisher-service credits · QR · MercadoPago Firestore MongoDB frontend Next.js 15 web portal mobile iOS · Expo / React Native HTTPS
Extraction & storage
Cloud Run service
Managed datastore
Client surface

Not shown: publisher-service also calls admin-service's review-queue machinery to moderate brand-submitted edits, reusing the same moderation pattern built for catalog normalization.

WHAT EACH PIECE DOES

Six responsibilities, cleanly split.

01

Extraction

Playwright scrapers for bank promotions (BCI, Tenpo, Banco Security), plus a Compute Engine VM in Chile for a provider that only responds to a local IP.

PlaywrightCompute Engine
02

Normalization

admin-service resolves brand names through exact, accent-folded, and fuzzy matching, routes uncertain matches to a human review queue, and applies brand-level metadata overrides.

FastAPIrapidfuzzFirestore
03

Core API & auth

backend-api serves the processed catalog; auth-service issues JWTs and manages roles (admin / publisher / pro_user / user) against MongoDB.

FastAPIJWTMongoDB
04

Conversational agent

Hexagonal architecture; a tool-calling loop against backend-api so the LLM never invents an offer. Hybrid cosine + lexical semantic search, cached in GCS by catalog content hash.

Tool-callingSemantic search
05

Publisher platform

Brand accounts scoped to their catalog entry, credit purchases via MercadoPago, custom offer publishing, and QR-code proof-of-purchase for in-store attribution.

MercadoPagoQR codes
06

Client surfaces

A Next.js 15 web portal and an Expo/React Native iOS app, sharing the same backend, auth, and agent APIs.

Next.jsExpo

WHY IT'S BUILT THIS WAY

A few deliberate trade-offs.

  • Cloud Storage as the handoff layer between batch jobs and services avoids tight coupling, so a VM-only extractor can coexist with Cloud Run services without either side knowing the other's runtime.
  • Brand resolution is a three-tier fuzzy match with a human review queue above a confidence threshold — not full automation, not full manual curation.
  • The agent never trusts its own memory of the catalog — every fact comes from a tool call, so it can't hallucinate an offer that doesn't exist.
  • Every service's build/deploy scripts source one common.env file, so a config change in one place propagates everywhere instead of drifting per-service.