Skip to main content

Architecture & Codebase Overview

Welcome to the Roja developer documentation. Roja is a Nigerian peer-to-peer (P2P) lending fintech platform connecting borrowers and lenders through structured tickets (loan requests and offers), backed by multi-tier KYC verification, direct-debit repayment mandates, automated collections/dunning, credit scoring (the Roja Score), and optional credit insurance.

All platform interfaces—mobile, customer web, staff back-office, and developer portals—are powered by the unified Go backend API documented across this knowledge base.


System Topology

Roja is architected as an OpenAPI-first, container-free in local dev, GitOps-deployed in production system.

┌─────────────────────────────────────────────────────────────────────────────┐
│ CLIENT SURFACES │
│ │
│ Mobile App Customer Web App Staff Dashboard │
│ (Expo / React Native) (Next.js App Router / R19) (Next.js Pages) │
└──────────┬────────────────────────┬────────────────────────────┬────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SHARED CLIENT LAYER │
│ │
│ @roja/client ─── Generated OpenAPI TypeScript SDK (Strictly Typed) │
│ @roja/common ─── Axios client factory, CSRF, Token Refresh, React Query │
└─────────────────────────────────────┬───────────────────────────────────────┘
│ HTTPS / JSON API (/v1/...)

┌─────────────────────────────────────────────────────────────────────────────┐
│ BACKEND API │
│ │
│ Go 1.27 + net/http + oapi-codegen (Strict-Server Interface) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ CORE DOMAIN SERVICES │ │
│ │ • tickets • directpay • collections • score (Markov) │ │
│ │ • kyc • banking • wallet • insurance │ │
│ │ • support • superlender • staff • featureflags │ │
│ └──────────────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────┴──────────────────────┐ │
│ ▼ ▼ │
│ PostgreSQL 18 (sqlc + pgx) Redis 8 │
│ • Double-Entry Audit Mirror • Asynq Queues │
│ • Transactional Outbox • Distributed Caching │
│ • Declarative Atlas Migrations • Session Keyspaces │
└──────────────────────────────────────┬──────────────────────────────────────┘

┌──────────────────────────┴──────────────────────────┐
▼ ▼
┌──────────────────────────────────────┐ ┌───────────────────────────────────┐
│ ASYNC WORKERS │ │ EXTERNAL RAILS │
│ │ │ │
│ • asynq-worker (Task Consumers) │ │ • Banking / Mandates: │
│ • asynq-scheduler (Periodic Cron) │ │ Mono, Monnify, Providus │
│ • asynq-monitor (Prometheus/API) │ │ • Identity / KYC: │
│ • agent-worker (Liquidity Bots) │ │ Dojah, QoreID, Monnify │
│ │ │ • Insurance: Curacel, MyCover │
└──────────────────────────────────────┘ └───────────────────────────────────┘

Monorepo Layout

The repository is managed as a Bun workspace monorepo (bun@1.3.14).

Workspace / DirectoryTech StackResponsibility
backend/Go 1.27, net/http, sqlc, pgx/v5, Asynq, AtlasCore REST API, background workers, scheduled jobs, and platform liquidity bot agents.
apps/web/Next.js (App Router), React 19, Tailwind CSS v4Customer-facing web application for loan requests, marketplace browsing, offers, and KYC.
apps/staff/Next.js (Pages Router), React 19, Tailwind CSS v4Back-office dashboard for operations, risk reviews, manual disbursement approvals, and collections.
apps/docs/Docusaurus 3, MDX, TypeScriptThis documentation site (docs.roja.dev / docs.getroja.com), served via Cloudflare Workers.
apps/files/Cloudflare WorkerDocument attachment handler and media proxy.
apps/cdn/Cloudflare WorkerAsset caching and static delivery rail.
mobile/React Native, Expo SDK, expo-router, NativeWindiOS and Android mobile app distributed via Google Play Store and Apple App Store.
packages/common/TypeScript, @tanstack/react-query, AxiosShared frontend runtime: auth interceptors, CSRF handling, date/money formatters, and custom hooks.
packages/js-client/TypeScript (Auto-generated)Type-safe API client generated directly from backend/spec/gen/openapi.yaml.
tools/storybook-web/Storybook, Vite, Tailwind v4UI component preview for apps/web and apps/staff with Vitest smoke tests (storybook.roja.dev).
tools/storybook-mobile/Storybook, React Native WebUI component preview for mobile/ components (storybook-mobile.roja.dev).
tools/duckdb/DuckDB, dbt, PythonSynthetic, scrubbed OLAP data mart for financial analytics without exposing real customer PII.
devops/Nix, Cloudflare, Terraform, AnsibleInfrastructure configurations, Cloudflare tunnels, deployment pipelines, and Grafana dashboards.
service-registry/Kubernetes, Flux GitOps, KustomizeKubernetes manifests and GitOps deployment configs for cluster environments.

Technology Stack & Core Choices

Go 1.27 Backend

Built on the Go standard library net/http router wrapped by oapi-codegen strict-server interfaces. Zero heavyweight web framework overhead; high concurrency and deterministic memory management.

PostgreSQL 18 + sqlc

Declarative SQL schema in backend/db/schema/ managed by Atlas. sqlc compiles type-safe Go structs and queries from plain SQL in backend/db/query/.

Asynq & Redis 8

Distributed background task queue backed by Redis with priority queues, exponential retries, and transactional outbox event dispatching.

Next.js & React 19

Customer web app built with React 19, React Compiler, and Tailwind CSS v4. Staff back-office runs Pages Router with role-based view gating.

Expo / React Native

Cross-platform mobile application with typed routing (expo-router), biometrics, passkeys, and NativeWind styling.

Nix & Cloudflare Workers

Container-free local development via Nix flakes; frontend static sites and OpenNext instances deployed as Cloudflare Workers.


The OpenAPI-First Contract

Roja operates strictly on an OpenAPI-first contract. The OpenAPI specification is the single authoritative source of truth for the entire platform.

1. Author Spec in backend/spec/

The API specification is broken into modular YAML files under backend/spec/:

  • paths/ — Every route definition, request method, parameters, and response links.
  • schemas/ — Domain entity schemas, input payloads, and error objects.
  • parameters/ — Reusable query, header, and path parameters.
2. Bundle Spec

Running task backend:generate (or make generate) compiles modular specs into a single bundled file at backend/spec/gen/openapi.yaml.

3. Generate Go Strict-Server

oapi-codegen generates:

  • Go request/response structs.
  • Strict server interfaces (StrictServerInterface) in backend/internal/apiserver/router.go.
  • RBAC permissions and user role mappings in backend/spec/roles.gen.go.
4. Generate TypeScript Client

scripts/generate-js-client.sh consumes the bundled YAML and emits a fully typed TypeScript client into packages/js-client/. All web, staff, and mobile components consume this client through @roja/common.

CI Contract Gate: Continuous integration validates that all generated Go and TypeScript files match the OpenAPI specification. If a pull request modifies an API route without running task generate and committing the output, CI fails.


Regulatory & Compliance Principles

Roja operates in the Nigerian financial technology ecosystem under the jurisdiction of the Federal Competition and Consumer Protection Commission (FCCPC) and the Central Bank of Nigeria (CBN).

FCCPC Compliance Guardrail: Customer personally identifiable information (PII)—including National Identification Numbers (NIN), Bank Verification Numbers (BVN), home addresses, bank account credentials, and phone numbers—must never leave developer machines in plaintext logs, test fixtures, terminal outputs, or AI prompts.

Key Compliance Rules:

  1. PII Encryption at Rest: BVN and NIN fields stored on customer records are encrypted using AES-256-GCM (backend/internal/crypto) before database persistence.
  2. Deterministic Pseudonymization in Fixtures: All analytics and development fixtures in tools/duckdb use synthetic, scrubbed test data. Real production dumps are prohibited in local environments.
  3. Audit Trails & Evidence Durability: Financial operations require immutable audit evidence. Deleting financial transactions, settlement sagas, or outbox events before their retention window is prohibited by database foreign keys and trigger locks.
  4. App Store Lending Policy Compliance: Mobile app permissions on Android are strictly restricted to Camera and Microphone (for KYC verification). Requesting contacts, SMS, or precise location is banned to conform to Google Play's Personal Loans policy.

Money Discipline

Financial operations require absolute numerical accuracy. Floating-point math (float32, float64, or JavaScript number) is strictly forbidden across the codebase for monetary values.

  • Wire Representation: All monetary figures cross network boundaries as exact decimal strings formatted to two decimal places (e.g. {"amount": "50000.00", "currency": "NGN"}).
  • Backend Arithmetic: Handled exclusively using shopspring/decimal. Direct arithmetic using floating-point types fails static checks (backend/scripts/decimal-containment-check.sh).
  • Database Storage: Stored as PostgreSQL numeric(18,2) with check constraints prohibiting negative balances.
  • Frontend Formatting: Consumed only through @roja/common/money utilities which perform string-based normalization and formatting without loss of precision.

Next Steps