Architecture & data model.

PerkUp is one shared data model rendered by a React app, served by TypeScript Cloud Functions, with a Go service in maintenance mode for payments. Here is how the pieces fit, in product terms.

Proto-first data model

Every core entity is defined once as a Protocol Buffers message in proto/ and generated into TypeScript (for the web app and Cloud Functions) and Go (for the backend service). One definition, one vocabulary, everywhere — the admin platform, the recipient experience, and the backend cannot drift out of sync on what an Individual or a Program is.

EntityRepresentsDefined in
OrganizationA customer company — billing, settings, brand, HRIS config.proto/perkup/v1/organization.proto
IndividualAn employee or recipient — identity, role, status, labels, manager.proto/perkup/v1/individual.proto
ProgramA reward, recognition, or perk send, with enrolled members.proto/perkup/v1/program.proto
ProductVariantA catalog item — swag, gift card, or curated gift.proto/perkup/v1/product_variant.proto
AccountA pool of funds an organization draws against.proto/perkup/v1/account.proto
BalanceTransactionA hold, capture, release, or refund against a balance.proto/perkup/v1/transaction.proto
Order / OrderFulfillmentA purchase and its shipment and tracking.proto/perkup/v1/order.proto
RuleAn automation trigger for birthdays, anniversaries, and leave.proto/perkup/v1/rules.proto
Production / WarehouseBulk-swag manufacturing state and inventory.proto/perkup/v1/production.proto, warehouses.proto

For the human-readable definition of each term and its states, see the Glossary.

The three codebases

CodebaseWhat it isWhere new code goes
Web appA single React + Vite + TypeScript SPA that renders both the admin platform and the recipient experience.apps/frontend/
Cloud FunctionsFirebase Functions (TypeScript) — the default home for new backend logic: RPC services, webhooks, Firestore triggers, scheduled jobs.functions/ — yes, default
Go serviceA Go API server on App Engine, in maintenance mode. Still owns Stripe payments, the account ledger, and a few integration clients.backend/app/ — maintenance only

New backend services are written in TypeScript in functions/. The Go service is maintained for what already lives there (payments, ledger, Printful/Plum/Shopify clients) but takes no new RPC services. See backend/AGENTS.md.

Data stores & infrastructure

The platform runs on Google Cloud. The product-relevant pieces:

  • Firestore — the primary database; every entity above is a Firestore document.
  • Cloud Storage + CDN — serves the web app and stores assets, designs, and proofs.
  • Pub/Sub — async work like member creation and balance updates.
  • Cloud Tasks — rate-limited outbound work such as order placement.
  • Cloud Scheduler — recurring jobs: approval reminders, digest emails, expiry alerts.
  • BigQuery — analytics and the bulk-swag supplier catalog.
  • Firebase Auth — identity, with custom claims binding a user to an organization and role.

Source: proto/ · CLAUDE.md · functions/AGENTS.md · backend/AGENTS.md · apps/frontend/src/services/{algolia,typesense}.ts