
PEACEBINFLOWVillageLink AI — Bringing Tswana AI to Makuta via WhatsApp An AI voice & chat app for community...
VillageLink AI — Bringing Tswana AI to Makuta via WhatsApp
An AI voice & chat app for community information in Botswana’s Makuta Village
Makuta is a small village in the Central District of Botswana located about 70 km northwest of Francistown, along the road to Tutume. It had ~907 residents in the 2022 census, and like many rural communities, access to information is patchy — especially when literacy, data costs, and low-end phones are real constraints.
🧠 The Problem
In Makuta and surrounding areas:
Many people speak Setswana (Tswana) more fluently than English.
A significant portion can’t easily read or write complex text.
WhatsApp is the communication platform everyone already uses.
Data costs are high and unreliable connectivity is common.
Traditional news channels and apps don’t serve this reality — most tools assume:
keyboards
stable Internet
English proficiency
That’s not Makuta.
So I built something for us.
🛠️ What I Built — VillageLink AI
VillageLink AI is a WhatsApp-powered AI assistant that:
📱 Speaks Tswana
You can talk to it in Setswana — voice or text — and it responds in Setswana (or English if needed).
No complex apps — just WhatsApp.
🔊 Voice-First Interaction
Users send a voice clip or message like:
“Ka ntlha yang ga re kopane ka kgotla gompieno?”
(Why are we meeting at the kgotla today?)
VillageLink AI replies with:
Voice reply in Setswana
Short text summary
Optional offline shareable files
This makes it accessible even to people who don’t type or read well.
🌍 Information Sync for the Whole Community
It can:
Share announcements (village meetings, health info, events)
Summarize important news
Answer local questions
Generate short, low-data audio & text updates
📦 Offline & Low-Data Support
We optimized:
File sizes for low-end devices
Offline info packs (tiny audio/text bundles)
Summaries that can be saved and shared
Because data is expensive.
💥 Why This Matters
This isn’t just another bot — it’s:
Culturally grounded: Designed for Setswana speakers in Botswana, starting with Makuta.
Practical: Uses WhatsApp, which people already use daily.
Inclusive: Works for non-readers, elders, farmers, students.
Low-barrier: No new apps, no new accounts, low data.
It’s information justice — not tech for tech’s sake.
📊 Demo Walkthrough
Open WhatsApp → send a voice message in Setswana.
VillageLink AI transcribes & understands it.
AI responds with:
Tswana voice reply
Short text summary
Optional downloadable info file
We show this in the demo video and screenshots in the post.
🧪 Tech Stack (in brief)
WhatsApp Cloud API (Meta)
GPT-powered NLP tuned for Setswana
Speech-to-text + text-to-speech
Node.js backend
Minimal offline file generator
💬 Community Impact (Makuta & Beyond)
This tool is a social connector for a village where:
People often learn everything via word of mouth
Outsiders (family in towns) are cut off from daily life
Elders might miss crucial updates because they can’t read
VillageLink AI bridges that gap — making Makuta smarter, more connected, and more empowered.
This section documents how VillageLink AI is built, how it works, and how it can scale.
[ User (WhatsApp) ]
|
v
[ WhatsApp Cloud API ]
|
v
[ Node.js API Server ]
|
+--> Speech-to-Text (Whisper)
|
+--> Prompt System (Setswana)
|
+--> GPT AI Core
|
+--> Text-to-Speech
|
v
[ Response Formatter ]
|
v
[ WhatsApp Reply (Voice + Text + Files) ]
User sends voice/text
|
v
Detect type (voice or text)
|
+--> If voice:
| Transcribe to text
|
v
Normalize Setswana input
|
v
Send to Prompt System
|
v
GPT processes request
|
v
Generate:
- Setswana text reply
- Optional audio reply
- Optional info pack
|
v
Send back via WhatsApp
You are VillageLink AI.
You assist people in Makuta village in Botswana.
You must:
- Prefer Setswana language
- Use simple words
- Be short and clear
- Prioritize voice-friendly responses
- Assume users may not read well
- Avoid technical or complex terms
User said (in Setswana):
"{transcribed_text}"
Reply in Setswana.
Keep response under 4 sentences.
If useful, summarize clearly.
village-link-ai/
│
├── server/
│ ├── index.js
│ ├── routes/
│ │ └── whatsapp.js
│ ├── services/
│ │ ├── ai.js
│ │ ├── speech.js
│ │ └── formatter.js
│ └── prompts/
│ └── system.txt
│
├── offline-packs/
│ └── generator.js
│
├── public/
│ └── demo.mp4
│
├── .env
├── package.json
└── README.md
server/index.js
import express from "express";
import whatsappRouter from "./routes/whatsapp.js";
const app = express();
app.use(express.json());
app.use("/webhook", whatsappRouter);
app.listen(3000, () => {
console.log("VillageLink AI running...");
});
routes/whatsapp.js
import express from "express";
import { handleMessage } from "../services/ai.js";
const router = express.Router();
router.post("/", async (req, res) => {
const message = req.body.message;
const reply = await handleMessage(message);
res.json(reply);
});
export default router;
services/ai.js
import { transcribeAudio, speakText } from "./speech.js";
import { formatResponse } from "./formatter.js";
import fs from "fs";
export async function handleMessage(message) {
let text = message.text;
if (message.audio) {
text = await transcribeAudio(message.audio);
}
const prompt = fs.readFileSync("./prompts/system.txt", "utf8");
const aiReply = await callGPT(prompt, text);
const audioReply = await speakText(aiReply);
return formatResponse(aiReply, audioReply);
}
services/speech.js
export async function transcribeAudio(audioFile) {
return "Transcribed Setswana text here";
}
export async function speakText(text) {
return "audio-file.mp3";
}
services/formatter.js
export function formatResponse(text, audio) {
return {
text: text,
audio: audio
};
}
export function generateOfflinePack(content) {
return {
audio: "compressed.mp3",
text: content,
size: "small"
};
}
Focus on:
AI as a utility, not surveillance.
✔ WhatsApp = UI
✔ Voice-first
✔ Low data
✔ Modular
✔ Language-driven
✔ Scalable
[ WhatsApp User ]
|
v
[ WhatsApp Cloud API ]
|
v
[ Express API Server ]
|
+--> Speech-to-Text (Whisper)
|
+--> Prompt Engine (Setswana rules)
|
+--> GPT AI Core
|
+--> Text-to-Speech
|
v
[ Response Formatter ]
|
v
[ WhatsApp Reply (Text + Voice + File) ]
User sends message
|
v
Check message type
|
+----+-----+
| |
Voice Text
| |
Transcribe |
| |
+----+-----+
|
Normalize Setswana input
|
Send to Prompt Engine
|
Send to GPT
|
Generate response
|
Convert to audio
|
Send via WhatsApp
prompts/system.txt
You are VillageLink AI.
You serve the village of Makuta in Botswana.
Your job:
- Prefer Setswana language
- Use very simple words
- Speak like a helpful local assistant
- Keep responses under 4 sentences
- Assume user may not read well
- Prioritize clarity over detail
- Avoid technical language
User said (Setswana):
"{input}"
Reply in Setswana.
Keep response short and voice-friendly.
village-link-ai/
│
├── server/
│ ├── index.js
│ ├── routes/
│ │ └── whatsapp.js
│ ├── services/
│ │ ├── ai.js
│ │ ├── speech.js
│ │ └── formatter.js
│ └── prompts/
│ └── system.txt
│
├── offline-packs/
│ └── generator.js
│
├── public/
│ └── demo.mp4
│
├── .env
├── package.json
└── README.md
server/index.js
import express from "express";
import whatsappRouter from "./routes/whatsapp.js";
const app = express();
app.use(express.json());
app.use("/webhook", whatsappRouter);
app.listen(3000, () => {
console.log("VillageLink AI running");
});
routes/whatsapp.js
import express from "express";
import { handleMessage } from "../services/ai.js";
const router = express.Router();
router.post("/", async (req, res) => {
const message = req.body;
const reply = await handleMessage(message);
res.json(reply);
});
export default router;
services/ai.js
import fs from "fs";
import { transcribeAudio, speakText } from "./speech.js";
import { formatResponse } from "./formatter.js";
export async function handleMessage(message) {
let text = message.text;
if (message.audio) {
text = await transcribeAudio(message.audio);
}
const systemPrompt = fs.readFileSync("./prompts/system.txt", "utf8");
const aiReply = await callGPT(systemPrompt, text);
const audioReply = await speakText(aiReply);
return formatResponse(aiReply, audioReply);
}
services/speech.js
export async function transcribeAudio(file) {
return "Transcribed Setswana text";
}
export async function speakText(text) {
return "voice.mp3";
}
services/formatter.js
export function formatResponse(text, audio) {
return {
text,
audio
};
}
export function generateOfflinePack(content) {
return {
text: content,
audio: "compressed.mp3",
size: "small"
};
}
# VillageLink AI
An AI-powered WhatsApp assistant for Setswana-speaking village communities in Botswana.
## Features
- Setswana voice interaction
- WhatsApp interface
- Low-data optimization
- Offline info packs
- Community announcements
## Run locally
npm install
node server/index.js
## Environment Variables
OPENAI_KEY
WHATSAPP_TOKEN
WHATSAPP_PHONE_ID
## Usage
Send a WhatsApp message to the bot number.
Receive voice and text replies in Setswana.
Host on:
OPENAI_KEY=xxx
WHATSAPP_TOKEN=xxx
POST /webhook