Give forkers who self-host on their own infra a first-class container
path instead of hand-rolling a Dockerfile and guessing the Next.js
standalone wiring.
- Multi-stage Dockerfile (deps -> build -> runtime) using Next.js
output: "standalone"; runs as a non-root user.
- Single-service docker-compose.yml — Supabase stays external, so no
database container is included.
- .dockerignore and docs/docker.md documenting the setup, including the
build-time (NEXT_PUBLIC_*, inlined into the client bundle) vs runtime
(server secrets via env_file) split.
- Set output: "standalone" in next.config.ts. This is a no-op for
next start and the Hostinger path; only the Docker build consumes it.
Purely additive: no dependency or stack changes, existing deploy paths
are unaffected. Database migrations remain out of scope for the
container (applied via the Supabase CLI, matching the external-Supabase
model).
Introduce mcp-server/ — a stdio Model Context Protocol server that
wraps the /api/v1 public API so MCP clients (Claude, Cursor, etc.) can
drive a self-hosted wacrm instance in natural language.
- Thin wrapper over the existing REST API; all auth, scoping, and rate
limiting stay server-side. No new backend surface.
- Read-only by default: write and broadcast tools are only registered
when WACRM_ENABLE_WRITES / WACRM_ENABLE_BROADCASTS are set, layered
on top of the API key's own scopes. send_broadcast also requires an
explicit confirm and is marked destructive.
- Registry-ready: server.json manifest, package.json mcpName linked to
it (io.github.arnasdon/wacrm-mcp), and glama.json for discovery.
- Docs: docs/mcp.md + README bullet + mcp-server/README.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Grounds the AI assistant (0.5.0) in the account's own content so it can
answer instead of handing off.
- Hybrid retrieval: Postgres full-text search for every account; optional
semantic search (pgvector + OpenAI text-embedding-3-small) when an
embeddings key is set. Semantic-primary, topped up with FTS.
- src/lib/ai: chunk, embeddings, knowledge (ingest + retrieve), query;
buildSystemPrompt gains a knowledge block; config carries an
(optional) embeddings key.
- Wired into /api/ai/draft and the auto-reply bot (best-effort — never
blocks a reply).
- KB API (/api/ai/knowledge CRUD + /reindex) and a Settings → AI
Assistant knowledge-base manager + embeddings-key field.
- Migration 030: pgvector, ai_knowledge_documents, ai_knowledge_chunks
(fts + embedding), match RPCs, ai_configs.embeddings_api_key.
Migration required: supabase/migrations/030_ai_knowledge.sql.
Stacked on feat/ai-reply-assistant (#329).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds an AI reply assistant powered by the account's own OpenAI or
Anthropic key (stored AES-256-GCM-encrypted; no per-seat AI fee).
- AI-drafted replies in the inbox composer (✨ button, agent+), via
read-only POST /api/ai/draft.
- Optional auto-reply bot on inbound messages that no Flow consumed and
no agent owns, with a per-conversation cap and clean [[HANDOFF]] to a
human. Stands down when a message-level automation would also reply.
- Settings → AI Assistant (admin+): provider/model, key, business
context, toggles, and a Test-key button that verifies before saving.
- Provider layer (src/lib/ai) with OpenAI + Anthropic adapters behind
one interface; migration 029 (ai_configs + per-conversation columns +
atomic claim_ai_reply_slot RPC).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the machine-to-machine auth layer the public REST API needs so
external scripts and automations can drive wacrm (issue #245). This is
the groundwork release; data endpoints land one at a time on top of it.
- Migration 026: account-scoped `api_keys` table. SHA-256 hash at rest
(plaintext shown once), display `key_prefix`, `scopes[]`, RLS via
`is_account_member` (members read, admin+ manage).
- `src/lib/api-keys/`: key gen/hash (wacrm_live_ prefix, timing-safe),
scope vocabulary, service-role auth-path store.
- `requireApiKey(request, scope?)` (src/lib/auth/api-context.ts):
bearer parse -> hash lookup -> liveness -> per-key rate limit ->
scopes-only authz. Returns a service-role-scoped account context.
- `/api/v1` envelope ({data} / {error:{code,message}}) + GET /api/v1/me
reference endpoint that exercises the whole stack.
- Dashboard: admin+ key management routes + Settings -> API keys tab.
- Docs (docs/public-api.md), CHANGELOG, README, .env note.
Checks: typecheck clean, lint 0 errors, full suite green (+27 tests).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The multi-user account-sharing surface (Members tab + invite/role
management APIs + /join redeem flow) is complete, so drop the
`account_sharing` beta flag that hid it during development. Mirrors
the Flows soft-GA in 0.2.0.
- settings: Members tab is now always rendered (no beta_features
check, no stale-link fallback). The `profiles.beta_features`
column itself stays for future betas.
- sidebar: the active-account strip no longer keys off the flag.
It now shows whenever the account name differs from the user's
own name — i.e. once you've renamed the account or joined a
shared one — preserving the original "don't duplicate a solo
user's name" behaviour without the flag.
- CHANGELOG/README: document Members as a shipped, all-users
feature.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the generic Hostinger brand banner with a purpose-built
"Ship your Node.js app in one click — Deploy to Hostinger" banner
designed from the Hostinger design system (signature purple,
DM Sans Black, real Hostinger logo lockup, Node.js green hexagon
mark). Sized 1200×400 at 2× DPR for retina, ~122 KB PNG.
Implements the V1 "Purple baseline" variation from the design
package "Node.js Deploy Banner.html". Drops the small text caption
under the top banner and the redundant "Deploy your fork" shields.io
companion (the new banner has its own embedded CTA pill); keeps the
"Step-by-step guide" link since that still goes to docs, not
Hostinger.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Swap the shields.io text badges for the Hostinger logo banner — a real
brand image makes the deploy CTA the visual anchor of the README and
of the dedicated section. Add a small "→ Deploy wacrm on Hostinger"
caption under the top banner for clarity, and keep the small
shields.io companion buttons under the section banner so the
step-by-step guide stays one click away.
Asset committed to .github/assets/hostinger-deploy.webp (21 KB).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Make the Hostinger CTA the visual anchor of the README and add a
dedicated "Deploy on Hostinger (recommended)" section with concrete
reasons (one-click Git deploy, Managed Node.js, free SSL, CDN, env
vars in hPanel, DDoS + backups, pricing, support) and a 60-second
deploy walkthrough. Bigger, centered HTML-scaled badges at the top
and in the section. Linked from the "Why fork this?" bullet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Self-host docs already point to Hostinger Managed Node.js as the
fastest path, but the README had no clickable starting point for that
journey. Adds a CTA button (shields.io + SimpleIcons Hostinger logo +
brand purple) right under the tagline, linking to Hostinger's web-apps
hosting landing page.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Forks of this repo no longer inherit the wacrm.tech landing page
and docs — those move to the dedicated marketing-site repo at
https://github.com/ArnasDon/wacrm-site (deployed to wacrm.tech).
Changes here:
- Replace src/app/page.tsx with a redirect to /dashboard.
Middleware already handles the unauth → /login bounce, so this
works for both auth states.
- Drop src/app/{docs,opengraph-image.tsx,robots.ts,sitemap.ts}.
- Drop src/components/{landing,docs,seo} and src/lib/{seo,docs}.
- Drop the top-level docs/ markdown — moved to wacrm-site/docs.
- Slim src/app/layout.tsx metadata down to product chrome
(no public OG cards, robots: noindex).
- Drop `marked` from dependencies; refresh package-lock.
- Refocus README on self-hosting; point readers at wacrm.tech/docs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per Meta's brand-use guidance for third-party products, the registered
trademark symbol (®) should appear on the FIRST mention of "WhatsApp"
on each user-facing page. Subsequent mentions on the same page are
left plain.
Surfaces touched (one-per-page first mention):
- Landing hero badge ("Built on the official WhatsApp® Business API").
- src/lib/seo/site-config.ts: SITE_TAGLINE and SITE_DESCRIPTION
(rendered into <title> and <meta description> on every page).
- src/app/opengraph-image.tsx: hero text in social-share image.
- Settings, Inbox connection banner, Automations page subtitle.
- README.md tagline.
- All public docs pages (docs/README.md, docs/whatsapp-setup.md,
docs/getting-started.md, docs/supabase-setup.md,
docs/environment-variables.md, docs/deployment-hostinger.md,
docs/automations-and-cron.md, docs/architecture.md,
docs/troubleshooting.md).
Out of scope: SITE_KEYWORDS (the meta-keywords array isn't
user-rendered text — putting ® on every keyword would look broken in
the meta tag).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The legal brief on third-party trademark use says: avoid the WhatsApp
teal/green palette and any visual treatment that could read as a
WhatsApp/Meta product. Emerald-500 was used as the primary brand colour
across hero, CTAs, sidebar, charts, badges, and the favicon — close
enough in hue to WhatsApp's signature green to muddy the line.
Swapping to Tailwind violet (which matches the Hostinger brand purple
#7c3aed) makes the visual identity unambiguously ours.
Scope:
- Mechanical Tailwind class swap: emerald-* → violet-* across src/.
- src/app/globals.css: --primary, --ring, --sidebar-primary, --sidebar-ring,
--chart-1 oklch tokens swapped from emerald (oklch 0.696 0.17 162) to
Hostinger-aligned violet (oklch 0.526 0.247 293).
- src/app/icon.tsx: favicon background #10b981 → #7c3aed.
- src/app/opengraph-image.tsx: badge bg, accent text, gradient.
- src/components/landing/hero.tsx + cta-banner.tsx: radial-gradient hex.
- src/components/landing/mock/analytics-mock.tsx: marketing chart line.
- src/components/dashboard/conversations-chart.tsx + response-time-chart.tsx:
"Outgoing" series colour. Distinguishable from "Incoming" blue at a
glance; we can revisit the chart pair later for stronger colourblind
contrast (separate concern).
- README.md: license badge colour parameter.
Out of scope:
- src/components/settings/tag-manager.tsx still offers "Emerald" as one
of the user-pickable contact-tag colours alongside Blue / Yellow / Red
/ etc. — that's a user data choice, not a brand mark.
Contrast check: white text on #7c3aed measures ~4.78:1 (WCAG AA passing
for normal body text). Violet-400 (#a78bfa) on slate-950 measures ~10:1
for accent text, well clear of AA.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops the "WaCRM" branded name across user-facing surfaces in favour
of a descriptive name. Branded names that imply WhatsApp ownership or
sponsorship are a trademark fair-use risk; a relationship-based name
("CRM Template for WhatsApp") sidesteps that.
Scope:
- Brand text in nav, sidebar, footer, docs shell, mock window chrome.
- SITE_NAME / SITE_DESCRIPTION / legalName in src/lib/seo/site-config.ts.
- README, CONTRIBUTING, docs/, .github/ templates and policies.
- package.json description.
- Auth pages, settings copy, FAQ, code comments.
Out of scope (intentionally — these are infra renames the project
owner should drive separately so links and the package lockfile stay
consistent):
- The github.com/ArnasDon/wacrm repo URL.
- The wacrm.tech domain / homepage field.
- The package.json "name" field.
- The Hostinger application name and Meta system-user name in deploy
docs (existing-deployment instructions).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The template is about shipping on Hostinger. Offering Vercel / Railway
/ raw VPS / Docker alongside it blurs that story and creates support
surface for hosts we don't actually test against.
- Delete docs/deployment-alternatives.md.
- README Deploy list drops the "Alternative hosts" bullet.
- docs/README.md reading-order drops step 6 and renumbers.
- docs/architecture.md drops its trailing "Next step" pointer to
the removed page.
- src/lib/docs/content.ts drops the deployment-alternatives entry;
remaining pages renumbered to 5..8.
Verified: /docs sidebar now lists 8 pages,
/docs/deployment-alternatives → 404.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Finishes the template-readiness sequence. All docs — nothing runtime.
README.md
Rewrites the landing page of the repo to actually sell what it is
to someone finding the repo cold on GitHub search.
- Shields.io badges: MIT, CI status, Next.js 16, Supabase, GitHub
stars.
- "What you get out of the box" bullet list — inbox, contacts,
pipelines, broadcasts, automations, dashboard, account
management — so the feature surface is visible before the reader
scrolls.
- "Why fork this?" section: full ownership, full customisation,
zero ops to start, real security primitives. Frames WaCRM as a
template, not an SDK.
- Docs section reorganised into Setup / Deploy / Reference to
match the in-app /docs viewer and docs/README.md.
- Contributing section rewrites the stale "Pull requests welcome"
line to match the fork-first framing from PR #73.
docs/architecture.md (new)
One-page tour for forkers: stack table, full folder layout,
two ASCII request-lifecycle diagrams (inbound webhook + outbound
send), security primitives rundown, and a "where to change things"
index that maps common customisation tasks to source files. This
is the thing I wish I'd had the first time I opened a forked
template.
docs/deployment-alternatives.md (new)
Short blocks for Vercel, Railway, raw VPS, and Docker. Each covers
env-var setup, cron strategy (Vercel cron without custom headers
is a footgun worth calling out), and trade-offs. Keeps Hostinger
as the primary recommendation — this page is for people whose
constraints rule it out.
docs/README.md
- Reading order grouped as Setup / Deploy / Reference, adding the
two new pages.
- Stack-at-a-glance updated: encryption is AES-256-GCM, not CBC
(the PR #71 change that earlier docs hadn't caught up to).
src/lib/docs/content.ts
Registers the two new markdown files in the ORDER map so they
appear in the in-app /docs sidebar under the Reference section,
with prev/next pagination wiring.
Verified: /docs, /docs/architecture, /docs/deployment-alternatives,
and /docs/getting-started all return 200 from the dev server.
Sidebar shows 9 pages grouped Setup / Deploy / Reference with the
new entries. Typecheck clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds docs/ with a reading-order flow that covers:
- getting started (fork, install, run locally)
- supabase setup + migrations
- whatsapp business api + webhook wiring
- environment variable reference
- hostinger vps deploy walkthrough
- automations cron scheduling
- troubleshooting for the common issues
Rewrites the top-level README as a pointer into docs/ instead of the
create-next-app boilerplate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>