awali (Swahili) — the beginning; the origin; the very first step.
WhatsApp-native RSVP & M-Pesa payments platform for Kenya.
Guests never leave WhatsApp. Organisers never chase anyone manually. Payments flow through M-Pesa. Data lands in a clean dashboard in real time.
- Scan QR code or tap WhatsApp link
- Flow opens inside WhatsApp — native form UI (no typing, no confusion)
- Pay via M-Pesa STK Push — PIN prompt appears on their phone
- Receive confirmation in the same chat
- Create an event + configure RSVP questions
- Get a QR code + WhatsApp link
- Watch the dashboard — real-time RSVPs, payments, check-ins
┌─────────────────────────────────────────────────────────────┐
│ FRONTEND (Nuxt 4 on AWS Amplify) │
│ Pure API consumer — calls API Gateway endpoints │
│ Dashboard, event creation, analytics │
└────────────────────────┬────────────────────────────────────┘
│ HTTPS
┌────────────────────────▼────────────────────────────────────┐
│ AWS API GATEWAY (HTTP API) │
├──────────────────────────────────────────────────────────────┤
│ /webhook → webhook Lambda (Meta verification + msgs) │
│ /flow → flow_endpoint Lambda (encrypted Flows) │
│ /mpesa/callback → mpesa_callback Lambda (Safaricom) │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────────┐
│ LAMBDA FUNCTIONS (Python 3.12) │
│ ├── webhook — receives WhatsApp messages │
│ ├── flow_endpoint — handles Flow data_exchange │
│ ├── mpesa_callback — processes M-Pesa results │
│ └── send_message — sends outbound WhatsApp messages │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────────┐
│ AWS SERVICES │
│ ├── DynamoDB — events, RSVPs, payments │
│ ├── SQS — outbound message queue (decoupling) │
│ ├── S3 — event assets (posters, PDFs) │
│ ├── SSM — all secrets (Meta tokens, M-Pesa keys) │
│ └── Cognito — organiser authentication │
└──────────────────────────────────────────────────────────────┘
| Layer | Technology |
|---|---|
| Frontend | Nuxt 4 (Vue 3) + Tailwind CSS 4 + shadcn-vue |
| Hosting | AWS Amplify |
| Backend | AWS Lambda (Python 3.12) |
| Infrastructure | AWS CDK (TypeScript) |
| Database | DynamoDB (single-table design) |
| Auth | Cognito |
| Messaging | WhatsApp Cloud API + WhatsApp Flows |
| Payments | M-Pesa Daraja API (STK Push) |
| Queue | SQS (outbound messages) |
| Secrets | SSM Parameter Store |
| Storage | S3 |
awali/
├── app/ # Nuxt 4 frontend
│ ├── components/ui/ # shadcn-vue components
│ ├── layouts/ # Dashboard + default layouts
│ ├── pages/ # Routes
│ └── app.vue # Root component
├── infra/ # AWS CDK (TypeScript)
│ ├── bin/app.ts # CDK app entry point
│ ├── lib/ # Stack definitions
│ │ ├── api-stack.ts # API Gateway + Lambda
│ │ ├── database-stack.ts
│ │ ├── storage-stack.ts
│ │ ├── auth-stack.ts
│ │ └── messaging-stack.ts
│ └── lambda/ # Python Lambda functions
│ ├── webhook/ # WhatsApp webhook handler
│ ├── flow_endpoint/ # WhatsApp Flow data_exchange
│ ├── mpesa_callback/ # M-Pesa STK Push callback
│ ├── send_message/ # Outbound message sender (SQS consumer)
│ └── shared/ # Shared utilities
├── WHATSAPP-FLOWS.md # Flow architecture documentation
├── WEBHOOKS.md # Webhook systems documentation
└── README.md
- AWS CLI configured (
aws configure) - Node.js 20+ and Python 3.12+
- CDK CLI (
npm install -g aws-cdk)
cd infra
cp .env.example .env
# Fill in CDK_DEFAULT_ACCOUNT and CDK_DEFAULT_REGION
npm install
npx cdk bootstrap # first time only
npx cdk deploy --allCDK outputs the API Gateway URL. Use it for Meta webhook config and M-Pesa callback.
aws ssm put-parameter --name "/awali/whatsapp/access-token" --value "YOUR_TOKEN" --type SecureString
aws ssm put-parameter --name "/awali/whatsapp/phone-number-id" --value "YOUR_ID" --type SecureString
aws ssm put-parameter --name "/awali/whatsapp/flow-id" --value "YOUR_FLOW_ID" --type SecureString
aws ssm put-parameter --name "/awali/whatsapp/flow-private-key" --value "$(cat flow_private.pem)" --type SecureString
aws ssm put-parameter --name "/awali/whatsapp/flow-passphrase" --value "YOUR_PASSPHRASE" --type SecureString
aws ssm put-parameter --name "/awali/mpesa/consumer-key" --value "YOUR_KEY" --type SecureString
aws ssm put-parameter --name "/awali/mpesa/consumer-secret" --value "YOUR_SECRET" --type SecureString
aws ssm put-parameter --name "/awali/mpesa/shortcode" --value "174379" --type String
aws ssm put-parameter --name "/awali/mpesa/passkey" --value "YOUR_PASSKEY" --type SecureString
aws ssm put-parameter --name "/awali/mpesa/callback-url" --value "https://YOUR_API_URL/mpesa/callback" --type String
aws ssm put-parameter --name "/awali/mpesa/env" --value "sandbox" --type String# Push to GitHub → Amplify auto-deploys
# Or manually:
bun run build- Send a message to your WhatsApp test number:
RSVP-test123 - Bot replies with a Flow interactive message
- Tap "RSVP Now" → Flow opens with form
- Fill in details → submit
- M-Pesa STK Push appears on your phone (sandbox)
- Enter PIN → confirmation message arrives
- WHATSAPP-FLOWS.md — How WhatsApp Flows work, Flow JSON structure, encryption
- WEBHOOKS.md — All three webhook systems, payloads, SQS decoupling
Private. All rights reserved.
AWALI — kila tukio linaanza hapa. Every gathering starts here.