{"id":38667106,"url":"https://github.com/utachicodes/mafal-ia","last_synced_at":"2026-01-17T09:50:21.777Z","repository":{"id":311048054,"uuid":"1042216514","full_name":"utachicodes/mafal-ia","owner":"utachicodes","description":"Mafal-IA is a B2B, API-first platform for restaurants. You pay for the service, we provide the WhatsApp AI API and a simple dashboard. Plug it into your existing workflows to answer customers, share menus, and calculate orders automatically.","archived":false,"fork":false,"pushed_at":"2025-10-03T00:17:24.000Z","size":921,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-03T01:25:58.009Z","etag":null,"topics":["ai-agents","b2b-portal","chatbot","gemini-api","platform-services","rag-chatbot","whatsapp-api"],"latest_commit_sha":null,"homepage":"https://mafal-ia.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/utachicodes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-21T17:00:40.000Z","updated_at":"2025-10-03T00:17:27.000Z","dependencies_parsed_at":"2025-08-21T21:39:12.702Z","dependency_job_id":"15e279ad-ef4d-4bfb-8a68-79ea35f92275","html_url":"https://github.com/utachicodes/mafal-ia","commit_stats":null,"previous_names":["utachicodes/mafal-ia"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/utachicodes/mafal-ia","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utachicodes%2Fmafal-ia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utachicodes%2Fmafal-ia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utachicodes%2Fmafal-ia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utachicodes%2Fmafal-ia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/utachicodes","download_url":"https://codeload.github.com/utachicodes/mafal-ia/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/utachicodes%2Fmafal-ia/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28505565,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T06:57:29.758Z","status":"ssl_error","status_checked_at":"2026-01-17T06:56:03.931Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","b2b-portal","chatbot","gemini-api","platform-services","rag-chatbot","whatsapp-api"],"created_at":"2026-01-17T09:50:21.625Z","updated_at":"2026-01-17T09:50:21.749Z","avatar_url":"https://github.com/utachicodes.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mafal-IA - Agentic Whatsapp Platform\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://nextjs.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/Next.js-15-black?logo=next.js\" alt=\"Next.js\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.typescriptlang.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/TypeScript-5-blue?logo=typescript\" alt=\"TypeScript\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://tailwindcss.com/\"\u003e\u003cimg src=\"https://img.shields.io/badge/TailwindCSS-3-06B6D4?logo=tailwindcss\" alt=\"TailwindCSS\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://ui.shadcn.com/\"\u003e\u003cimg src=\"https://img.shields.io/badge/ShadCN-UI-000000?logo=react\" alt=\"ShadCN UI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/genkit-ai\"\u003e\u003cimg src=\"https://img.shields.io/badge/AI-Genkit-4285F4?logo=google\" alt=\"Google Genkit\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.prisma.io/\"\u003e\u003cimg src=\"https://img.shields.io/badge/ORM-Prisma-2D3748?logo=prisma\" alt=\"Prisma\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.postgresql.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/DB-PostgreSQL-4169E1?logo=postgresql\" alt=\"PostgreSQL\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-green.svg\" alt=\"MIT License\"\u003e\u003c/a\u003e\n  \u003ca href=\"../../issues\"\u003e\u003cimg src=\"https://img.shields.io/badge/Contributions-Welcome-brightgreen.svg?logo=github\" alt=\"Contributions Welcome\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nMafal-IA is a B2B, API-first platform for restaurants. You pay for the service, we provide the WhatsApp AI API and a simple dashboard. Plug it into your existing workflows to answer customers, share menus, and calculate orders automatically.\n\n\u003e Quickstart: see `docs/QUICKSTART.md` for setup, creating a restaurant, and calling your chatbot endpoint (RAG-based retrieval).\n\n## Webhook \u0026 LAM Quick Setup\n\nFollow these steps to connect your WhatsApp provider in under 2 minutes.\n\n1. Environment (.env)\n   - DEMO_MODE=true\n   - WHATSAPP_VERIFY_TOKEN=your_token\n   - Optional (LAM replies):\n     - LAM_API_BASE_URL=https://waba.lafricamobile.com/api\n     - LAM_API_KEY=your_bearer_token\n     - LAM_SENDER_ID=your_sender_or_number\n\n2. Webhook URL (provider/BSP)\n   - URL: https://YOUR_DOMAIN/webhook/whatsapp\n   - Verify Token: same as WHATSAPP_VERIFY_TOKEN\n\n3. Verify (GET)\n   - Visit: https://YOUR_DOMAIN/webhook/whatsapp?hub.mode=subscribe\u0026hub.verify_token=YOUR_TOKEN\u0026hub.challenge=123\n   - Expect HTTP 200 with body: 123\n\n4. Test (send a message to your WABA number)\n   - In DEMO_MODE: you receive “Echo: \u003cyour text\u003e”.\n   - If LAM_* envs set, reply is sent via LAM. Otherwise it uses WhatsApp Graph.\n\n5. Go production later\n   - Set DEMO_MODE=false, add WHATSAPP_APP_SECRET, WHATSAPP_ACCESS_TOKEN (or per-restaurant creds) to enable signature validation and full AI/order logic.\n\nEndpoints involved:\n- GET/POST `app/webhook/whatsapp/route.ts` → alias to `app/api/whatsapp/route.ts`.\n- Templates helper: `app/api/tools/whatsapp/templates/route.ts` (uses per-restaurant token or fallback to env token).\n\n## Features\n\n- **AI that understands your customers**: Built on Google Genkit (Gemini), detects language and intent.\n- **Speaks your customers’ language**: French, English, Wolof, Arabic (auto-detected).\n- **Menu-aware**: Keep your menu in sync; the AI answers from your data.\n- **Order math included**: Extracts items/quantities and computes totals.\n- **WhatsApp-native**: Works with the WhatsApp Business API you already use.\n- **Test and monitor**: Live testing and basic analytics in the dashboard.\n- **Multi-restaurant ready**: Manage multiple brands under one account.\n\n## Noo ngi fi pour jàppal !!\nYour intelligent WhatsApp assistant. Get started in minutes.\n\n1. **Create Your Restaurant**\n   Add your restaurant profile: name, short description, and plan.\n\n2. **Add Your Menu (No JSON required)**\n   Paste JSON, CSV, or simple text lines. We auto-detect the format and structure it for AI.\n3. **Connect WhatsApp**\n   Configure your WhatsApp Business credentials (phone_number_id, access token, app secret, verify token). Your assistant is ready to serve.\n\n## V2 Update (Aug 2025)\n\n- **New pages \u0026 flows**: `app/onboarding`, `app/playground`, `app/concierge`, `app/whatsapp/quick-connect`, and `app/legal/dpa`.\n- **Concierge mode**: `Restaurant.isConcierge` lets one number act as a global concierge across all restaurants.\n- **Browser-safe AI client**: Use `src/lib/ai-client-browser.ts` in client components; keep `src/lib/ai-client.ts` for server code only.\n- **Local dev DB**: Default to SQLite via `prisma/dev.db` (PostgreSQL recommended for production).\n\n## V3 Update (Dec 2025) - Production Readiness\n\n- **Persistent State**: Conversation history and metadata (orders, delivery info) are now stored in the database (PostgreSQL/SQLite). No more data loss on server restarts.\n- **Smart RAG (Fuse.js)**: Replaced full-menu context with fuzzy search. Handles large menus (1000+ items) efficiently by sending only relevant items to the AI.\n- **Robust Routing**: The webhook now intelligently routes messages based on `phone_number_id`, loading the correct restaurant context and API tokens for true multi-tenancy.\n- **Async Architecture**: Webhook returns `200 OK` immediately to Meta to prevent timeouts, processing logic in the background.\n\n## Technology Stack\n\n- **Framework**: Next.js 15 (App Router)\n- **Language**: TypeScript\n- **Styling**: Tailwind CSS\n- **UI Components**: ShadCN/UI\n- **AI Backend**: Google Genkit\n- **Search Engine**: Fuse.js (Fuzzy Search for RAG)\n- **State Management**: PostgreSQL (Persistent Conversations)\n- **Data Storage**: Prisma ORM + PostgreSQL (production), SQLite (local dev)\n\n## Getting Started\n\n### Prerequisites\n\n- Node.js 18+ \n- Google AI API Key (for Genkit)\n- WhatsApp Business API credentials\n\n### Environment Variables (Production)\n\nCreate environment variables with the following keys (locally and in your hosting provider):\n\n```env\n# Database (PostgreSQL in production)\nDATABASE_URL=postgres://USER:PASSWORD@HOST:PORT/DBNAME?sslmode=require\n\n# WhatsApp Business API (global fallbacks; per-restaurant overrides recommended)\n# For multi-tenant setups, set per-restaurant credentials in the dashboard after creating each restaurant.\n# These env vars are only used as fallbacks if a restaurant does not have its own credentials configured.\nWHATSAPP_ACCESS_TOKEN=\nWHATSAPP_APP_SECRET=\nWHATSAPP_VERIFY_TOKEN=\n\n# Genkit / Google AI\nGOOGLE_GENKIT_API_KEY=YOUR_GOOGLE_API_KEY\n\n# App mode\nDEMO_MODE=false\n```\n\n### Installation\n\n1. Clone the repository\n2. Install dependencies (React 19 peer-deps note):\n   - `npm install --legacy-peer-deps`\n   - Optionally set globally: `npm config set legacy-peer-deps true`\n3. Set up environment variables (`.env.local`)\n4. Initialize database with Prisma\n   - Local dev (SQLite, no DATABASE_URL needed):\n     - `npx prisma migrate dev --name add-isConcierge`\n     - `npx prisma generate`\n   - Production (PostgreSQL):\n     - Ensure `DATABASE_URL` is set\n     - `npx prisma migrate deploy`\n5. Run the development server: `npm run dev`\n6. Open [http://localhost:3000](http://localhost:3000)\n\n## Quick Start (No WhatsApp) — Create Restaurant, Issue API Key, Call Chatbot\n\nThis runbook gets you from zero to a working chatbot without connecting WhatsApp. It uses real database records and real API keys (no simulations).\n\n### 0) Configure admin token (protects key management routes)\n\nSet an admin token in your shell or `.env` file. If set, it is required for generating/revoking restaurant API keys and seeding.\n\nExample `.env` (local dev):\n\n```env\nADMIN_API_TOKEN=mafal_admin_sk_N3bGdXwG2qZr5u8Vh1Jk4Pq7Tt6Yw9_AeBdCfDhEjGlKmNoPqRsTuVwXyZ1a2b3\n```\n\nRestart `npm run dev` after editing `.env`.\n\n### 1) Seed a real sample restaurant (PowerShell on Windows)\n\nUse `curl.exe` (not the PowerShell alias) or `Invoke-WebRequest`.\n\n```powershell\ncurl.exe -X POST \"http://localhost:3000/api/restaurants/seed\" ^\n  -H \"Authorization: Bearer $env:ADMIN_API_TOKEN\"\n```\n\nResponse shows `{ ok: true, restaurant: { id, ... } }`. Copy the `restaurant.id`.\n\nAlternatively, with PowerShell-native:\n\n```powershell\n$seed = Invoke-WebRequest -Method POST `\n  -Uri \"http://localhost:3000/api/restaurants/seed\" `\n  -Headers @{ Authorization = \"Bearer $env:ADMIN_API_TOKEN\" }\n$rid = ($seed.Content | ConvertFrom-Json).restaurant.id\n$rid\n```\n\n### 2) Generate a per-restaurant API key\n\n```powershell\ncurl.exe -X POST \"http://localhost:3000/api/restaurants/$rid/api-key\" ^\n  -H \"x-admin-token: $env:ADMIN_API_TOKEN\"\n```\n\nSave the `apiKey` from the JSON response immediately (it is shown only once).\n\nPowerShell-native (captures the key):\n\n```powershell\n$gen = Invoke-WebRequest -Method POST `\n  -Uri \"http://localhost:3000/api/restaurants/$rid/api-key\" `\n  -Headers @{ \"x-admin-token\" = $env:ADMIN_API_TOKEN }\n$apiKey = ( $gen.Content | ConvertFrom-Json ).apiKey\n$apiKey\n```\n\n### 3) Call the chatbot API with your API key\n\nUsing PowerShell-native JSON to avoid quoting issues:\n\n```powershell\n$body = @{ restaurantId = $rid; message = \"Hello, what's on your menu?\" } | ConvertTo-Json\nInvoke-WebRequest -Method POST `\n  -Uri \"http://localhost:3000/api/ai/chat\" `\n  -Headers @{ \"Content-Type\" = \"application/json\"; \"x-api-key\" = $apiKey } `\n  -Body $body\n```\n\nOr with `curl.exe` and single-quoted JSON (escape apostrophes by doubling them):\n\n```powershell\ncurl.exe -X POST \"http://localhost:3000/api/ai/chat\" `\n  -H \"Content-Type: application/json\" `\n  -H \"x-api-key: $apiKey\" `\n  -d '{ \"restaurantId\": \"'$rid'\", \"message\": \"Hello, what''s on your menu?\" }'\n```\n\n### 4) (Optional) Validate or revoke API key\n\nValidate:\n\n```powershell\nInvoke-WebRequest -Method POST `\n  -Uri \"http://localhost:3000/api/ai/validate\" `\n  -Headers @{ \"x-api-key\" = $apiKey }\n```\n\nRevoke (admin-only):\n\n```powershell\ncurl.exe -X DELETE \"http://localhost:3000/api/restaurants/$rid/api-key\" ^\n  -H \"x-admin-token: $env:ADMIN_API_TOKEN\"\n```\n\n### HTTP Routes Involved\n\n- `POST /api/restaurants/seed` — Create a sample restaurant. Requires `ADMIN_API_TOKEN` if set.\n- `POST /api/restaurants/{id}/api-key` — Generate a new key (returns plaintext once). Requires `ADMIN_API_TOKEN` if set.\n- `DELETE /api/restaurants/{id}/api-key` — Revoke the current key. Requires `ADMIN_API_TOKEN` if set.\n- `POST /api/ai/validate` — Check if a key is valid; returns the `restaurantId` if so.\n- `POST /api/ai/chat` — Send a message for a specific restaurant; requires a valid API key.\n\n### Troubleshooting (Windows PowerShell)\n\n- **Missing API key**: ensure the header is exactly `Authorization: Bearer \u003ckey\u003e` or `x-api-key: \u003ckey\u003e`; avoid nested quotes.\n- **JSON parse error (500)**: build JSON with `ConvertTo-Json` or use `--data-binary @request.json`.\n- **Bad hostname / continuation (\u003e\u003e)**: avoid stray carets `^` in PowerShell; use backticks `` ` `` for line breaks or single-line commands.\n- **Unauthorized on key generation/revocation**: set `ADMIN_API_TOKEN` and include it via `Authorization: Bearer` or `x-admin-token`.\n\nNo WhatsApp is required for the above. You can add WhatsApp later.\n\n## Project Structure\n\n```text\n.\n├─ app/                             # Next.js App Router\n│  ├─ api/\n│  │  ├─ whatsapp/route.ts          # WhatsApp webhook (GET verify, POST messages)\n│  │  ├─ restaurants/[id]/route.ts  # Restaurant API\n│  │  └─ concierge/order/route.ts   # Concierge ordering endpoint\n│  ├─ analytics/page.tsx\n│  ├─ concierge/page.tsx\n│  ├─ onboarding/page.tsx\n│  ├─ playground/page.tsx\n│  ├─ restaurants/[id]/\n│  ├─ restaurants/page.tsx\n│  ├─ settings/page.tsx\n│  ├─ whatsapp/quick-connect/page.tsx\n│  ├─ legal/dpa/page.tsx\n│  ├─ page.tsx                      # Landing page\n│  └─ layout.tsx\n│\n├─ components/\n│  ├─ ui/                           # ShadCN UI components\n│  └─ theme-provider.tsx\n│\n├─ prisma/\n│  ├─ schema.prisma                 # Postgres models\n│  └─ dev.db                        # Local SQLite (dev only)\n│\n├─ public/                          # Static assets (logos, images)\n│  └─ ...\n│\n├─ src/\n│  ├─ ai/\n│  │  ├─ flows/                     # Genkit flows (generate, menu info, totals)\n│  │  ├─ config.ts\n│  │  └─ index.ts                   # Flow registry\n│  ├─ components/restaurant/        # Dashboard components\n│  ├─ hooks/\n│  │  └─ use-restaurants.tsx\n│  ├─ lib/\n│  │  ├─ ai-client.ts               # Server runner for flows (server-only)\n│  │  ├─ ai-client-browser.ts       # Browser-safe client for client components\n│  │  ├─ conversation-manager.ts    # In-memory conv + metadata (name/location/delivery)\n│  │  ├─ data-utils.ts\n│  │  ├─ delivery.ts                # Delivery zone fee/ETA estimator\n│  │  └─ ... other utils\n│  └─ ...\n│\n├─ styles/\n│  └─ globals.css\n│\n├─ package.json\n├─ next.config.mjs\n├─ tsconfig.json\n└─ README.md\n```\n\n## Key Components\n\n### AI Flows\n- **Generate Response**: Main conversational AI flow\n- **Menu Information**: RAG tool for menu queries\n- **Order Calculator**: Order total computation\n\n- **Menu Processor**: JSON menu parsing\n- **Smart RAG**: Fuse.js integration to filter menu items before AI generation\n\n### Dashboard Features\n- Restaurant management and configuration\n- Menu item management with JSON import\n- Live chat testing interface\n- API credentials management\n- Analytics and reporting\n\n### WhatsApp Integration\n- Webhook verification and message processing\n- Automatic AI response generation\n- Conversation history management\n- Multi-language support\n\n## API Endpoints\n\n- `GET /api/whatsapp` - Webhook verification\n- `POST /api/whatsapp` - Message processing\n\n## Quick API Usage\n\n- **Verify webhook (Meta setup)**\n\n```bash\ncurl -G \\\n  \"https://your-domain.com/api/whatsapp\" \\\n  --data-urlencode \"hub.mode=subscribe\" \\\n  --data-urlencode \"hub.verify_token=$WHATSAPP_VERIFY_TOKEN\" \\\n  --data-urlencode \"hub.challenge=12345\"\n```\n\n- **Send an inbound message (simulate WhatsApp event)**\n\n```bash\ncurl -X POST \"https://your-domain.com/api/whatsapp\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Authorization: Bearer $WHATSAPP_ACCESS_TOKEN\" \\\n  -d '{\n    \"entry\": [{\n      \"changes\": [{\n        \"value\": {\n          \"metadata\": { \"phone_number_id\": \"YOUR_META_PHONE_NUMBER_ID\" },\n          \"messages\": [{\n            \"from\": \"221771234567\",\n            \"id\": \"wamid.HBgNN...\",\n            \"timestamp\": \"1699999999\",\n            \"type\": \"text\",\n            \"text\": { \"body\": \"Bonjour, avez-vous du Thieb?\" }\n          }]\n        }\n      }]\n    }]\n  }'\n```\n\nIf `Restaurant.whatsappPhoneNumberId` matches the Meta `phone_number_id`, the request is routed to your restaurant. Mafal-IA generates a reply and sends it via the WhatsApp Business API.\n\n### Optional: Direct Chat API (non-WhatsApp simulation)\n\nFor simple HTTP tests without WhatsApp, call the Chat API with a restaurant ID:\n\n```bash\ncurl -X POST \"https://your-domain.com/api/ai/chat\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"restaurantId\": \"\u003cyour-restaurant-id\u003e\",\n    \"message\": \"Hello, I'd like to see your menu\",\n    \"language\": \"English\"\n  }'\n```\n\nNotes:\n- The `restaurantId` must exist in your DB.\n- No API key is required; the server’s configured AI key is used.\n\n### WhatsApp Integration - Step by Step\n\nFollow these steps to connect a restaurant to WhatsApp Business API and validate the webhook end to end.\n\n1) Prepare credentials\n- **From Meta**: WhatsApp Business `phone_number_id`, a long‑lived **Access Token**, and your app’s **App Secret**.\n- **Choose** a **Verify Token** (any string you control) to use during webhook verification.\n\n2) Configure the restaurant in the dashboard\n- Go to `Settings → API Credentials` for the restaurant.\n- Set the fields:\n  - `phone_number_id`: your Meta WhatsApp Business phone number ID\n  - `Access Token` (optional per restaurant): overrides the global token when sending messages\n  - `App Secret` (optional per restaurant): used to validate incoming webhook signatures\n  - `Webhook Verify Token`: exact token you’ll also supply in Meta for verification\n\n3) Provide per-restaurant WhatsApp credentials during creation\n- In onboarding step 3, enter: `phone_number_id`, Access Token, App Secret, and a Verify Token for this restaurant.\n\n4) Configure the webhook in Meta\n- Webhook URL: `https://YOUR_DOMAIN/api/whatsapp`\n- Verify Token: the exact value set above\n- Subscribe to the “messages” webhook event\n\n5) Verify the webhook (GET)\n\n```bash\ncurl -i -G \"https://YOUR_DOMAIN/api/whatsapp\" \\\n  --data-urlencode \"hub.mode=subscribe\" \\\n  --data-urlencode \"hub.verify_token=YOUR_VERIFY_TOKEN\" \\\n  --data-urlencode \"hub.challenge=123456\"\n```\n\nExpected: `HTTP/1.1 200` with body `123456`.\n\n6) Test a signed POST delivery locally (optional but recommended)\n\n- Save a minimal WhatsApp payload as `wa.json` (set `phone_number_id` to your restaurant’s `phone_number_id`):\n\n```json\n{\n  \"entry\": [\n    {\n      \"changes\": [\n        {\n          \"field\": \"messages\",\n          \"value\": {\n            \"metadata\": { \"phone_number_id\": \"123456789012345\" },\n            \"contacts\": [{ \"profile\": { \"name\": \"Test User\" }, \"wa_id\": \"15551234567\" }],\n            \"messages\": [\n              { \"from\": \"15551234567\", \"id\": \"wamid.TEST\", \"timestamp\": \"1736800000\", \"type\": \"text\", \"text\": { \"body\": \"Hi there\" } }\n            ]\n          }\n        }\n      ]\n    }\n  ],\n  \"object\": \"whatsapp_business_account\"\n}\n```\n\n- Compute the signature with your App Secret and send the request:\n\n```bash\nAPP_SECRET=\"YOUR_APP_SECRET\"\nSIG=\"sha256=$(cat wa.json | openssl sha256 -hmac \"$APP_SECRET\" -binary | xxd -p -c 256)\"\ncurl -i -X POST \"https://YOUR_DOMAIN/api/whatsapp\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-Hub-Signature-256: $SIG\" \\\n  --data-binary @wa.json\n```\n\nExpected: `HTTP/1.1 200` and server logs showing payload processing. If a per‑restaurant App Secret is set, unsigned POSTs will be rejected (`403`).\n\n7) Live test\n- Send a real WhatsApp message to your WABA number. The platform will route by `metadata.phone_number_id`, generate an AI response with your restaurant’s context/menu, and reply using your Access Token (per‑restaurant if set, otherwise global).\n\n8) Troubleshooting\n- 403 on GET: verify the exact Verify Token value.\n- 403 on POST: invalid/missing `X-Hub-Signature-256` for the configured App Secret.\n- No reply sent: check `phone_number_id` mapping, Access Token permissions, and logs.\n\n### Multi-tenant: Per-restaurant credentials (add after creating each restaurant)\n\nFor multiple restaurants, configure credentials per restaurant right after creation. Global env vars are optional fallbacks only.\n\n- In the dashboard: `Restaurants → [Select Restaurant] → Settings → API Credentials`\n  - WhatsApp Number (display/reference)\n  - phone_number_id (required for routing)\n  - Access Token (per restaurant; overrides global)\n  - App Secret (per restaurant; enables signature validation)\n  - Webhook Verify Token (used during Meta verification)\n\nRepeat for every restaurant you add.\n\n## Quick Start for Restaurants (what to send us)\n\nShare the following so we can set you up fast. You can send it by email or via the dashboard form.\n\n- **Restaurant basics**\n  - Name, short description, cuisine\n  - Business hours, delivery zones/fees, languages spoken\n  - Optional: welcome message, any special instructions or tone\n\n- **Menu (JSON / CSV / Text)**\n  - Preferred: JSON array of items with fields `name`, `description`, `price`, optional `category`, `isAvailable`\n  - Example JSON:\n\n```json\n[\n  { \"name\": \"Thieboudienne\", \"description\": \"Rice \u0026 fish\", \"price\": 3500, \"category\": \"Main\", \"isAvailable\": true },\n  { \"name\": \"Yassa Poulet\", \"description\": \"Lemon onion chicken\", \"price\": 3000 }\n]\n```\n\n  - If sending CSV, include columns: `name,description,price,category,isAvailable`\n  - If sending simple text, one item per line works: `Thieboudienne - Rice \u0026 fish - 3500`\n\n- **WhatsApp info**\n  - Your business WhatsApp phone number (E.164, e.g. +221771234567)\n  - If you already use WhatsApp Business API: your `phone_number_id` (optional; we can help retrieve it)\n  - If you manage your own Meta app/BSP: your preferred Verify Token (or we generate one)\n\nWhat you’ll get back\n- Webhook URL: `https://YOUR_DOMAIN/api/whatsapp`\n- Verify Token (if we generated it) and instructions to paste it in Meta\n- Guidance to set or confirm your `phone_number_id`\n- A quick test plan (GET verify and signed POST sample)\n\nTypical timeline\n- Day 0: You send info → we configure in dashboard and provision webhook\n- Day 0–1: You confirm Meta settings (URL + Verify Token) and we test live inbound\n- Day 1+: Go live; we monitor and adjust menu/answers as needed\n\n\n## B2B Model: What We Provide vs What You Handle\n\nWe provide the API and tools. You keep control of your operations.\n\n- __What we provide__\n  - A production-ready WhatsApp webhook: `GET/POST /api/whatsapp`\n  - AI conversation engine (intent, language, menu reasoning, order extraction)\n  - Secure storage for restaurant/menu data\n  - Basic analytics and a simple dashboard\n\n- __What you handle__\n  - Payments and refunds (outside the WhatsApp API scope)\n  - Delivery/pickup logistics and fulfillment\n  - Customer support escalation beyond the AI\n  - Menu accuracy, pricing, taxes, compliance\n\nIn short: you pay for Mafal-IA, we provide the WhatsApp AI API + dashboard. Incoming WhatsApp messages become smart, menu-aware replies. You keep control of fulfillment and payments.\n\n## Production Setup Checklist\n\n1. __Provision PostgreSQL__ (Neon/Supabase/AWS RDS) and set `DATABASE_URL`.\n2. __WhatsApp Business API__\n   - Get `WHATSAPP_ACCESS_TOKEN`, `WHATSAPP_APP_SECRET` from Meta.\n   - Choose a `WHATSAPP_VERIFY_TOKEN`.\n3. __Google Genkit__\n   - Set `GOOGLE_GENKIT_API_KEY`.\n4. __Run Prisma__\n   - `npx prisma generate`\n   - `npx prisma migrate dev --name init`\n5. __Set your restaurant’s WhatsApp phone_number_id__ in DB\n   - `npx prisma studio` → Restaurant → set `whatsappPhoneNumberId` to Meta phone_number_id\n6. __Deploy__ and set the same env vars in your hosting provider.\n\n## Webhook Contract (WhatsApp)\n\n- __Verification:__\n  - `GET /api/whatsapp?hub.mode=subscribe\u0026hub.verify_token=...\u0026hub.challenge=...`\n  - Returns `200` with `hub.challenge` if `hub.verify_token` matches `WHATSAPP_VERIFY_TOKEN`.\n\n- __Message handling:__\n  - `POST /api/whatsapp` with the standard WhatsApp inbound payload.\n  - The service reads `entry[0].changes[0].value.metadata.phone_number_id` to identify which restaurant to route to.\n  - It generates an AI reply and responds via WhatsApp Business API using your `WHATSAPP_ACCESS_TOKEN`.\n\nEnsure the database field `Restaurant.whatsappPhoneNumberId` matches your Meta `phone_number_id` for correct routing.\n\n## Menu JSON Schema (for AI reasoning)\n\nYour menu is stored as structured items. A minimal shape:\n\n```json\n[\n  {\n    \"id\": \"1\",\n    \"name\": \"Thieboudienne\",\n    \"description\": \"Traditional Senegalese rice and fish\",\n    \"price\": 3500,\n    \"category\": \"Main Course\",\n    \"isAvailable\": true\n  }\n]\n```\n\nYou can import or edit menus via the dashboard UI. The AI uses this data to answer questions and compute totals.\n\n## Security Notes\n\n- __Rotate keys__ if exposed and store secrets only in environment variables.\n- __Verify signatures:__ The webhook validates `X-Hub-Signature-256` using `WHATSAPP_APP_SECRET`.\n- __Least privilege:__ Use a dedicated Postgres user for this app.\n\n## Testing\n\nThe platform includes comprehensive integration testing:\n\n- Restaurant data validation\n- Menu item structure validation\n- AI response generation testing\n- WhatsApp message processing\n  - Webhook signature validation\n\nRun tests using the Integration Test Panel in the settings.\n\n## Troubleshooting \u0026 Debugging\n\nUse these targeted checks when things go wrong.\n\n### NPM install / build\n- __Peer deps (React 19 / Next 15)__: `npm install --legacy-peer-deps` (optionally `npm config set legacy-peer-deps true`).\n- __Corrupt install__: delete `node_modules` + `package-lock.json`, then reinstall.\n- __Node version__: use Node 18+ LTS. `node -v`.\n\n### Next.js runtime \u0026 bundling\n- __Edge vs Node mismatch__: API routes like `app/api/whatsapp/route.ts` should run on Node (don’t export `runtime = 'edge'`).\n- __ESM/CJS errors (ERR_REQUIRE_ESM / Unexpected token 'export')__: avoid mixing module systems; keep Next defaults. Ensure `package.json` `type` and TS config align.\n- __Client bundle pulling server deps__: don’t import `src/ai/flows/*`, `RestaurantService`, or other server libs in client components. Use `src/lib/ai-client-browser.ts` in client code and keep `src/lib/ai-client.ts` on the server.\n\n### Environment / .env\n- __Missing keys__: set `GOOGLE_GENKIT_API_KEY`, `WHATSAPP_ACCESS_TOKEN`, `WHATSAPP_APP_SECRET`, `WHATSAPP_VERIFY_TOKEN`, `DATABASE_URL` (when using DB). See `src/lib/env.ts`.\n- __Wrong values__: compare with your Meta app settings and Google API key. Restart dev server after changes.\n\n### WhatsApp webhook\n- __GET verify returns 403__: `WHATSAPP_VERIFY_TOKEN` must match Meta’s configured token. Endpoint: `GET /api/whatsapp`.\n- __403 signature mismatch__: `WHATSAPP_APP_SECRET` missing/incorrect; see `src/lib/webhook-validator.ts`.\n- __400/401 from Graph API__: check `WHATSAPP_ACCESS_TOKEN`, `businessPhoneNumberId`, and message payload structure in `src/lib/whatsapp-client.ts`.\n- __405/CORS issues locally__: use the exact GET or POST method as required; ensure correct `Content-Type: application/json`.\n\n### Genkit / AI\n- __Missing API key__: set `GOOGLE_GENKIT_API_KEY`.\n- __429 rate limit / 5xx__: retry with backoff; temporarily switch model in `src/ai/config.ts` (e.g., `gemini-1.5-flash`).\n- __Flow runtime errors (dynamic import)__: confirm flows are only executed server-side via `AIClient`.\n- __Timeouts__: reduce prompt size, or increase platform timeout where applicable.\n\n### AI response quality\n- __No menu context__: ensure your restaurant has menu items; update via dashboard.\n- __Missing business info__: verify `restaurantContext` passed in `app/api/whatsapp/route.ts` (hours, delivery, location, fees).\n- __Tone/behavior__: customize `chatbotContext` in your restaurant data to guide tone and content.\n\n### Prisma / Database\n- __Migration errors__: run `npx prisma generate` then `npx prisma migrate dev --name init`. Verify `DATABASE_URL`.\n- __SQLite lock on Windows__: close other processes touching the DB; delete `prisma/dev.db` for a clean dev reset if needed.\n\n### Firebase-related \"Module not found: Can't resolve 'net'\" during build\n- __Symptom__: import trace shows `firebase-admin` / `firebase-functions`; bundler complains about Node built-ins like `net`.\n- __Cause__: optional Firebase providers from a transitive dep end up in a client/edge bundle or are recorded in `package-lock.json`.\n- __Fixes__:\n  - Keep API routes on Node runtime; don’t import server-only code in client components.\n  - Avoid adding `@genkit-ai/firebase` or Firebase SDKs unless used server-side only.\n  - Clean reinstall: delete `node_modules` and `package-lock.json`, then `npm install --legacy-peer-deps`.\n  - Use `AIClient` to invoke flows; do not import `src/ai/flows/*` directly in client code.\n  - As a last resort, set `DEMO_MODE=true` to validate UI and routing only.\n\n### Dev server / OS\n- __EADDRINUSE: 3000__: another app uses the port. Stop it or run with `PORT=3001 npm run dev`.\n- __CERT_HAS_EXPIRED / TLS__: ensure system time is correct; use valid HTTPS certs in production.\n\n### Quick diagnostics\n- __Find who depends on X__: `npx why \u003cpkg\u003e`; tree: `npm ls \u003cpkg\u003e`.\n- __Verbose logs__: check terminal during `npm run dev`. Add targeted `console.log` in `app/api/whatsapp/route.ts` to trace payload and routing.\n\n## Deployment\n\n1. Deploy to Vercel or your preferred platform\n2. Configure environment variables\n3. Set up WhatsApp webhook URL: `https://your-domain.com/api/whatsapp`\n4. Configure WhatsApp Business API with your webhook\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests if applicable\n5. Submit a pull request\n\n## License\n\nThis project is licensed under the MIT License.\n\n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Futachicodes%2Fmafal-ia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Futachicodes%2Fmafal-ia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Futachicodes%2Fmafal-ia/lists"}