AFRAMP is a blockchain payment platform designed specifically for the African market, enabling seamless conversion between local currencies and digital assets. We specialize in onramp (fiat-to-crypto) and offramp (crypto-to-fiat) transactions using African stablecoins and provide essential services like bill payments.
Built on the Stellar network with multi-chain compatibility, AFRAMP connects traditional African financial systems (like mobile money and local banks) to global blockchain ecosystems. Our platform tackles the high costs and slow speeds of cross-border payments by leveraging blockchain for near-instant, low-fee settlements.
- African Users & Diaspora: Send remittances, pay bills, and manage finances with minimal fees.
- Businesses & Developers: Integrate pan-African payments and treasury solutions.
- Contributors: Help build the future of African fintech with open, verifiable systems.
The AFRAMP frontend repository is organized for clarity and scalability:
Aframp/
βββ public/ # Static assets
βββ app/ # Next.js App Router
β βββ (app)/ # Authenticated routes
β βββ layout.tsx # Root layout
β βββ page.tsx # Auth/login page
βββ components/ # Reusable UI components
βββ lib/ # Utilities, API client, types
βββ .env.example # Environment variables template
βββ package.json
βββ README.md
The client-side contract is documented in the repository root OpenAPI file:
This spec covers the backend endpoints used by the frontend in lib/api.ts.
Offline caching and installable PWA support are currently disabled. Web Push payment alerts remain available through a push-only service worker; the app does not cache pages or API data for offline use.
Get AFRAMP running locally in under 5 minutes with our automated setup script or manual installation.
β οΈ Port constraint β read this first. The backend binds port 3000 and itsCORS_ALLOWED_ORIGINSdefaults tohttp://localhost:3001. The frontend must therefore run on 3001, not Next.js's default 3000. If you start the app on 3000, every API request will fail with a silent CORS/network error. SetNEXT_PUBLIC_API_URLto point at the backend and run the frontend on 3001 (see.env.example).
Linux/Mac:
git clone https://github.com/your-org/Aframp.git
cd Aframp
chmod +x scripts/setup.sh
./scripts/setup.shWindows (PowerShell):
git clone https://github.com/your-org/Aframp.git
cd Aframp
.\scripts\setup.ps1The script will:
- β Check prerequisites (Node.js, Docker)
- β
Create
.env.localfrom template - β Let you choose Docker or Node.js setup
- β Install dependencies and start the app
Access the app at http://localhost:3001 β
Prerequisites: Docker & Docker Compose installed
# Clone and start
git clone https://github.com/your-org/Aframp.git
cd Aframp
cp .env.example .env.local
docker-compose -f docker-compose.dev.yml upAccess the app at http://localhost:3001 β
(the frontend is mapped to 3001 so it matches the backend's default CORS_ALLOWED_ORIGINS; see docker-compose.dev.yml).
Prerequisites: Node.js v20+ & npm
# Clone and install
git clone https://github.com/your-org/Aframp.git
cd Aframp
npm install
# Configure and run
cp .env.example .env.local
npm run dev -- -p 3001Access the app at http://localhost:3001 β
(run on 3001 so the backend's default CORS_ALLOWED_ORIGINS=http://localhost:3001 accepts your requests).
Copy .env.example to .env.local and configure the following. This table
is generated from .env.example β run npm run docs:env after editing that
file to regenerate it, rather than hand-editing the table below; CI fails if
the two ever drift apart.
| Variable | Type | Required | Default | Example |
|---|---|---|---|---|
NEXT_PUBLIC_API_URL |
string (URL) | Yes | β | http://127.0.0.1:3000 |
NEXT_PUBLIC_STELLAR_NETWORK |
string (enum: testnet | public) | No | testnet |
NEXT_PUBLIC_SENTRY_DSN |
string (Sentry DSN URL) | No | (unset β client-side error reporting disabled) |
https://examplePublicKey@o0.ingest.sentry.io/0 |
SENTRY_DSN |
string (Sentry DSN URL) | No | (falls back to NEXT_PUBLIC_SENTRY_DSN, then disabled) |
https://examplePrivateKey@o0.ingest.sentry.io/1 |
SENTRY_AUTH_TOKEN |
string (Sentry auth token) | No | (unset β source map upload skipped) |
sntrys_eyJpYXQiOjE3MDAwMDAwMDAuMCwidXJsIjoiaHR0cHM6Ly9zZW50cnkuaW8ifQ== |
SENTRY_ORG |
string | No | (unset β source map upload skipped) |
aframp |
SENTRY_PROJECT |
string | No | (unset β source map upload skipped) |
aframp-pay |
NEXT_PUBLIC_PAYSTACK_PUBLIC_KEY |
string (Paystack public key) | No | (unset β Paystack hidden from the onramp provider selector) |
pk_test_examplekey1234567890 |
NEXT_PUBLIC_FLUTTERWAVE_PUBLIC_KEY |
string (Flutterwave public key) | No | (unset β Flutterwave hidden from the onramp provider selector) |
FLWPUBK_TEST-1234567890abcdef1234567890abcdef-X |
NEXT_PUBLIC_CNGN_ISSUER |
string (Stellar account address, G...) | No | (unset β cNGN charges disabled, shown as "Coming soon") |
GCNGNEXAMPLE234567890234567890234567890234567890234 |
# Start with hot-reload
docker-compose up
# Rebuild after dependency changes
docker-compose up --build
# Run in background
docker-compose up -d
# View logs
docker-compose logs -f
# Stop containers
docker-compose down
β οΈ The dev compose file maps the frontend to port 3001 because the backend binds 3000 and only allowshttp://localhost:3001by default viaCORS_ALLOWED_ORIGINS. Seedocker-compose.dev.ymlfor the inline explanation.
# Build production image
docker build -t aframp:latest .
# Run production container
docker run -p 3001:3001 --env-file .env.local aframp:latest
# Or use docker-compose
docker-compose -f docker-compose.prod.yml up -dPass environment variables via:
.env.localfile (recommended)- Docker Compose
environmentsection docker run -eflags
-
Connect Repository
- Go to vercel.com
- Import your GitHub repository
- Select the
Aframpproject
-
Configure Environment Variables
- In Vercel dashboard β Settings β Environment Variables
- Add all variables from
.env.example - Set
NEXT_PUBLIC_DEMO_MODE=falsefor production
-
Deploy
- Vercel auto-deploys on push to
main - Preview deployments for PRs
- Production URL:
https://your-project.vercel.app
- Vercel auto-deploys on push to
# Install Railway CLI
npm i -g @railway/cli
# Login and deploy
railway login
railway init
railway up- Create new Web Service
- Connect GitHub repository
- Build Command:
npm run build - Start Command:
npm start - Add environment variables in dashboard
Use the provided Dockerfile for containerized deployment:
# Build and push to container registry
docker build -t aframp:latest .
docker tag aframp:latest your-registry/aframp:latest
docker push your-registry/aframp:latest
# Deploy using your platform's container service
# (ECS, Cloud Run, Container Apps, etc.)If every request to the backend fails (browser console shows CORS errors or net::ERR_FAILED), you are almost certainly running the frontend on the wrong port.
- The backend binds port 3000 and its
CORS_ALLOWED_ORIGINSdefaults tohttp://localhost:3001. - Next.js defaults to port 3000, which collides with the backend and is not in the allowed origins list.
Fix: run the frontend on 3001 and point it at the backend:
# Node.js
npm run dev -- -p 3001
# Docker (already configured in docker-compose.dev.yml)
docker-compose -f docker-compose.dev.yml upMake sure .env.local sets NEXT_PUBLIC_API_URL to the backend URL (e.g. http://localhost:3000) and that the backend's CORS_ALLOWED_ORIGINS includes your frontend origin (http://localhost:3001 by default). See .env.example for details.
| Command | Description |
|---|
Built for Africa, Verified by Blockchain. Onramp to the future. Offramp to opportunity. ππ