Correctness: - Resume AI now releases ANY assignment (not just the caller's own). A handoff-assigned thread previously stayed assigned after resume, so the eligibility gate silently kept the bot muted — Resume was a no-op. - GET /api/ai/usage: guard days >= 1 (Number(null)===0 is finite, so the 30-day default was unreachable and the window collapsed to 1 day). - GET /api/ai/usage: align the query cutoff to the start of the oldest charted local day so rows in the oldest partial day no longer count in totals while missing from the daily series (totals now match the bars). - ai-thread-banner: cache account AI-status per accountId and never cache a transient fetch failure — fixes cross-account leak and the banner staying hidden all session after one failed /api/ai/config call. - /api/ai/draft: construct the service-role client inside a guard and fire-and-forget the usage log, so a missing service-role key (or any log failure) can't 500 an already-generated, already-billed draft. Efficiency: - Don't await usage logging on the reply hot path (auto-reply + draft); logAiUsage swallows its own errors, so fire-and-forget is safe and removes a DB round-trip from the customer-facing send. Reuse / consistency: - usage route reuses date-utils (daysAgoStart/lastNDayKeys/localDayKey) and now buckets by LOCAL day like every other dashboard chart (was UTC). - extract formatCompactNumber (shared with formatCurrencyShort); drop the hand-rolled month table in favour of date-fns; extract fetchAccountMembers/memberLabel and use them in the AI settings picker. Resume still resets the per-conversation reply count (a deliberate, manual, rate-limited re-engagement — documented in the handler). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .github | ||
| docs | ||
| messages | ||
| public | ||
| src | ||
| supabase/migrations | ||
| .editorconfig | ||
| .env.local.example | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| components.json | ||
| CONTRIBUTING.md | ||
| eslint.config.mjs | ||
| LICENSE | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
wacrm — CRM Template for WhatsApp
Self-hostable CRM template for WhatsApp® — shared inbox, contacts, sales pipelines, broadcasts, and no-code automations. Fork it, brand it, host it.
The marketing site and self-host docs live in a separate repo: ArnasDon/wacrm-site (wacrm.tech). This repo is the product — clone or fork it to run your own CRM.
What you get out of the box
- Shared inbox on the official WhatsApp Business API — multiple agents working one number, per-conversation assignment, status, and notes.
- Contacts + tags + custom fields, CSV import, deduplication.
- Sales pipelines (Kanban) with deals linked to conversations.
- Broadcasts with Meta-approved templates, delivery + read tracking, per-recipient variable substitution.
- No-code automations — triggers on inbound messages, new contacts, keywords, or schedule; conditional branches, waits, tags, webhooks. Visual builder.
- AI reply assistant — bring your own OpenAI or Anthropic key (stored encrypted; no per-seat AI fee, your data stays yours). One-click AI-drafted replies in the inbox, plus an optional auto-reply bot with a per-conversation cap and clean human handoff. Add a knowledge base (FAQs, policies, product docs) and it answers from your own content — hybrid retrieval (Postgres full-text, or semantic pgvector when an embeddings key is set).
- Real-time dashboard — response times, daily volume, pipeline value, cross-module activity feed.
- Team accounts — invite teammates by link, role-based access (owner / admin / agent / viewer), ownership transfer. Every install is account-scoped, so one shared inbox can be staffed by a whole team. Solo use stays single-user with zero setup.
- Account management — email, password, avatar, global sign-out.
- Public REST API (
/api/v1) with scoped, revocable API keys — build your own automations on top of your CRM. See docs/public-api.md.
Why fork this?
This is a template, not a product. Forking means you get:
- Full ownership — your code, your Supabase project, your domain, your data. No SaaS lock-in, no seat pricing, no trust dance.
- Full customisation — add the fields your team needs, remove the modules you don't, redesign anything. The stack is boring on purpose (Next.js + Supabase + Tailwind) so the learning curve is short.
- Zero ops to start — Hostinger Managed Node.js deploys a fork in a few clicks. No Docker, no Kubernetes, no infra team needed. (See below ↓)
- Real security primitives — token encryption (AES-256-GCM), RLS on every table, HMAC-verified webhooks, CSP, rate limiting, CI typecheck/build on every PR.
Not a framework. Not an SDK. A concrete, working CRM you can stand up in an afternoon and make yours.
Quick start
# Fork on GitHub first: https://github.com/ArnasDon/wacrm → Fork
git clone https://github.com/<your-username>/wacrm.git
cd wacrm
npm install
cp .env.local.example .env.local # fill in Supabase + Meta creds
npm run dev
Open http://localhost:3000. You'll be redirected to /login (or
/dashboard if already signed in).
🚀 Deploy on Hostinger (recommended)
wacrm is built to run on Hostinger. It's the path we test, document, and recommend — and the fastest way to get a production-grade CRM live without owning a VPS or a Kubernetes cluster.
Why Hostinger?
| One-click Git deploy | Connect your fork, push to main, Hostinger builds and ships it. No SSH, no Docker, no CI to wire up — this repo's own main deploys this way. |
| Managed Node.js | Next.js 16 (App Router, server actions, ISR) runs out of the box on Premium, Business, and Cloud shared plans. You don't manage Node versions, processes, or reverse proxies. |
| Free SSL + free domain | Automatic Let's Encrypt on your custom domain (or a free one included with annual plans). HTTPS is on by default — required for the WhatsApp Business webhook. |
| Global CDN + LiteSpeed | Static assets cached at the edge, dynamic routes served from LiteSpeed. Snappy dashboards out of the box, no Cloudflare setup required. |
| Env vars + logs in hPanel | Set SUPABASE_*, WHATSAPP_*, and ENCRYPTION_KEY from the panel — no .env on the server. Live application logs in the same UI. |
| DDoS protection + daily backups | Built-in, no add-ons. The webhook endpoint is a public target — having protection at the edge matters. |
| Cheaper than a VPS | Plans start at a few dollars a month — order-of-magnitude less than a comparable managed Node.js host, and you don't pay extra for the database (that's Supabase). |
| 24/7 human support | Live chat support in 20+ languages — useful when your CRM is the thing your team relies on to talk to customers. |
The 60-second version
- Fork this repo on GitHub.
- In hPanel → Websites → Create, pick Node.js and connect your fork.
- Paste your Supabase + Meta env vars into hPanel.
- Push to
main. Hostinger builds and serves it. Done.
Full walkthrough with screenshots: wacrm.tech/docs/deployment-hostinger.
Note: wacrm is MIT-licensed and runs anywhere Node.js does (Vercel, Railway, your own VPS). Hostinger is recommended, not required.
Documentation
Full self-host documentation — Supabase migrations, WhatsApp Business API config, and production deploy — lives at wacrm.tech/docs (source: ArnasDon/wacrm-site).
Key pages:
- Getting started
- Supabase setup
- WhatsApp setup
- Environment variables
- Deploy on Hostinger
- Architecture
- Troubleshooting
Stack
- App — Next.js 16 (App Router), React 19, TypeScript, Tailwind v4.
- Data — Supabase (Postgres + Auth + Storage + RLS).
- WhatsApp — Meta Cloud API (official WhatsApp Business API).
Contributing
This is a template, not a collaborative product — the expected flow is
fork → customise → deploy, not upstream contribution. Bug reports
and security issues are welcome; feature PRs often belong in your fork
rather than here. Details in
CONTRIBUTING.md and
.github/SECURITY.md.
License
MIT. Fork it, brand it, host it.