Architecture
Setula uses a two-tier deployment architecture with a Next.js frontend on Vercel and a Node.js backend on Railway. The frontend proxies all API and payment-demo requests to the backend through Next.js rewrites, keeping the browser on a single origin.
Deployment architecture
text
Browser ──→ Vercel (Next.js landing page)
│ /pay/* ──→ Railway backend (Node.js HTTP server)
│ /api/* ──→ Railway backend
│
└── Next.js rewrites proxy to DEMO_BACKEND_ORIGINData flow
text
Next.js frontend → Setula backend → Circle Wallets → Arc Testnet → simulated payout provider
Frontend (Vercel)
- Framework: Next.js 16 (App Router, Turbopack)
- UI: React 19 with CSS custom properties
- Routing: Landing page at
/, payment demo proxied at/pay - API proxy: Next.js
rewrites()forwards/api/*and/pay/*to the backend - Deployment: Vercel, with
DEMO_BACKEND_ORIGINas the only sensitive env var
Backend (Railway)
- Runtime: Node.js 22 with TypeScript (run via
tsx) - HTTP server: Raw
node:http— no Express or framework - Validation: Zod 4 for request schemas and env parsing
- Persistence: Atomic JSON file (
.setula-data.json) - State machine: Enforces valid payment status transitions
- Idempotency: All POST endpoints require an
Idempotency-Keyheader - CORS: Configurable via
CORS_ORIGINenv var; not needed in normal flow due to the proxy - Deployment: Railway, with all Circle credentials and secrets server-side
Settlement layer
- Circle SDK:
@circle-fin/developer-controlled-walletsv10.8 - Wallet type: Developer-controlled EOAs on Arc Testnet
- Transfer: USDC transfer from sender wallet to recipient wallet
- Polling: Circle transaction status polled until
COMPLETE - Evidence: Transaction hash stored and linked to ArcScan
- Balance check: Sender balance verified before transfer submission
Simulated fiat rails
- AED funding: Simulated — no real fiat collected
- Quote: Fixed sandbox rate of 22.75 INR/AED
- INR payout: Simulated callback — no real INR bank transfer
Production note: Licensed UAE funding and India payout partners would replace the simulated fiat rails in production. KYC/KYB controls and legal approval would be required in both jurisdictions.
Diagram
Security model
- Circle API keys and entity secret are stored only on Railway (server-side env vars).
- The payout callback secret (
PAYOUT_CALLBACK_SECRET) is shared only between the backend and the payout provider. - The Vercel frontend receives only
DEMO_BACKEND_ORIGIN— the backend URL. - No personal data or invoice details are written to the blockchain.
- The Arc transaction hash is the only on-chain artifact — used solely for settlement proof.
- Fiat payout confirmation is independent of chain settlement — a callback with a shared secret is required for
DELIVERED.
Technology stack
| Category | Technology |
|---|---|
| Language | TypeScript 7 |
| Runtime | Node.js 22 |
| Frontend | Next.js 16 (App Router), React 19, CSS |
| Backend HTTP | node:http (no framework) |
| Validation | Zod 4 |
| Build (browser) | esbuild |
| Runtime (TS) | tsx |
| Blockchain SDK | Circle Developer-Controlled Wallets 10.8 |
| Network | Arc Testnet |
| Settlement asset | USDC |
| Hosting (frontend) | Vercel |
| Hosting (backend) | Railway |
| Testing | Vitest 4 (16 tests) |