Skip to content

System Architecture

UberLotto v2 is a three-layer system: a PWA client layer, a Shopify Oxygen edge layer, and a multi-provider data layer.

Architecture Diagram

┌─────────────────────────────────────────────────────────────────┐
│                         CLIENT LAYER                            │
│  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐       │
│  │  Web Browser  │  │  Mobile PWA   │  │  Desktop PWA  │       │
│  └───────┬───────┘  └───────┬───────┘  └───────┬───────┘       │
└──────────┼──────────────────┼──────────────────┼────────────────┘
           └──────────────────┼──────────────────┘

┌─────────────────────────────▼───────────────────────────────────┐
│                    EDGE LAYER (Cloudflare)                       │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                 Shopify Oxygen Runtime                     │  │
│  │  ┌─────────────────────────────────────────────────────┐  │  │
│  │  │            Hydrogen SSR Application                  │  │  │
│  │  │  ┌──────────────┐ ┌──────────┐ ┌──────────┐        │  │  │
│  │  │  │ React Router │ │ Loaders  │ │ Actions  │        │  │  │
│  │  │  │    (v7)      │ │ (Server) │ │ (Server) │        │  │  │
│  │  │  └──────────────┘ └──────────┘ └──────────┘        │  │  │
│  │  └─────────────────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────────────────┘  │
└────────────┬──────────────┬──────────────┬──────────────┬───────┘
             │              │              │              │
             ▼              ▼              ▼              ▼
┌────────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│    Shopify     │ │  Supabase  │ │   Plisio   │ │  MoonPay   │
│ Storefront API │ │ PostgreSQL │ │ Payment API│ │  On-Ramp   │
│   (GraphQL)    │ │  REST API  │ │  Webhooks  │ │  Webhooks  │
└────────────────┘ └────────────┘ └────────────┘ └────────────┘

Client Layer

The application is a Progressive Web App (PWA) that runs across:

  • Web Browsers — full desktop experience
  • Mobile PWA — installable on iOS/Android
  • Desktop PWA — installable on Windows/macOS/Linux

Key capabilities:

FeatureImplementation
Service WorkerWorkbox via vite-plugin-pwa — offline caching, runtime caching strategies
App Manifestmanifest.webmanifest with icons, shortcuts, screenshots
Responsive UITailwind CSS v4
AnimationsMotion library
State ManagementZustand stores (cart, favorites, sidebar, global state)
Install PromptsCustom PWAProvider component with Safari-specific modal

Edge Layer (Shopify Oxygen)

The application runs on Shopify's Oxygen platform, which uses Cloudflare Workers.

Runtime characteristics:

  • Edge-deployed globally (low latency)
  • Serverless, stateless execution
  • 50ms CPU time limit per request
  • No persistent in-memory storage

Framework stack:

ComponentRole
HydrogenShopify's React framework for headless commerce
React Router v7File-based routing, server loaders/actions, SSR
ViteBuild tool, dev server, HMR
Mini OxygenLocal dev emulation of the Oxygen runtime

Entry Point

The server entry (server.ts) is an Oxygen worker that:

  1. Creates the Hydrogen context (storefront, customer account, cart, session)
  2. Passes context to React Router's request handler
  3. Handles session cookie commits
  4. Falls back to Shopify storefront redirects on 404s

Data Layer

Shopify Storefront API (GraphQL)

  • Product catalog and collections
  • Cart management
  • Customer accounts and authentication
  • Checkout creation
  • Shop analytics

Supabase (PostgreSQL)

  • Jackpot data (jackpots table)
  • Past drawing results (past_drawings table)
  • Wallet transactions
  • Security events and audit logging
  • Webhook nonces for replay protection

Plisio API

  • Cryptocurrency invoice creation
  • Webhook notifications for payment status
  • Transaction status polling

MoonPay API

  • Fiat-to-crypto on-ramp purchases
  • Widget integration via @moonpay/moonpay-react
  • Webhook notifications for transaction updates
  • HMAC-SHA256 signature verification

Shopify Checkout (Credit Loading)

  • "Load Credits" collection with UBL Point products
  • Cart creation via Storefront API cartCreate mutation
  • Redirect to Shopify checkout for payment processing
  • Authenticated endpoint — requires customer login

Key Architectural Decisions

1. Custom Fetch-based Supabase Client

Decision: Use native fetch API instead of @supabase/supabase-js SDK.

Rationale:

  • Avoids SSR compatibility issues in the edge runtime
  • Smaller bundle size (no SDK overhead)
  • Direct control over request/response handling
  • Better error handling for edge-specific constraints

Location: app/lib/supabase-client.server.ts

2. Server-Side Security Modules

Decision: All security-critical logic runs server-side only via .server.ts files.

Modules:

ModulePurpose
rate-limiter.server.tsIP and global request rate limiting
replay-protection.server.tsWebhook replay attack prevention
security-logger.server.tsSecurity event audit logging to Supabase
webhook-validator.server.tsHMAC signature verification

Rationale: Edge runtime provides isolation; secrets never exposed to client; centralized security logging.

3. Zustand for Client State

Decision: Use Zustand instead of Redux or React Context.

Rationale:

  • Minimal boilerplate
  • Works well with React 18 concurrent features
  • Easy integration with TanStack Query for server state
  • Good DevTools support

Stores: useCartLoadingStore, useCartPanelStore, useFavoritesStore, useGlobalStore, useSidebarStore

4. File-Based Routing with i18n Prefix

Decision: Use React Router v7's file-based routing with ($locale). prefix convention.

Rationale:

  • Convention over configuration
  • Automatic code splitting per route
  • Server-side loaders and actions per route
  • i18n support via optional locale URL segment

Performance Considerations

Edge Caching Strategy

Asset TypeStrategyCache Duration
Static imagesCacheFirst30 days
Google FontsCacheFirst365 days
API responsesNetworkFirst5 minutes
Shopify GraphQLNetworkFirst2 minutes

Bundle Optimization

  • Code Splitting — automatic per route via React Router
  • Tree Shaking — enabled via Vite
  • Asset Inlining — disabled (assetsInlineLimit: 0) for strict CSP compliance
  • SSR Optimization — specific packages pre-bundled for edge compatibility

Security Architecture

Key security layers:

  1. Network — Supabase network restrictions (Cloudflare IPs only)
  2. Application — Rate limiting, input validation, CSRF protection
  3. Data — Row Level Security (RLS) in PostgreSQL
  4. Webhooks — HMAC signature verification, replay protection, IP allowlisting

Scalability

ComponentScaling Model
OxygenAuto-scales based on traffic (Cloudflare Workers)
SupabasePro plan with connection pooling
PlisioRate limited by API tier
MoonPayRate limited by API tier

Bottlenecks to monitor:

  • Supabase connection pool exhaustion
  • Webhook processing throughput
  • Large GraphQL queries to Shopify Storefront API

UberLotto Technical Documentation