mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 17:29:45 +00:00
chore: rename product to "CRM Template for WhatsApp"
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>
This commit is contained in:
parent
ea0af2fe3e
commit
faee4eea44
4
.github/CODE_OF_CONDUCT.md
vendored
4
.github/CODE_OF_CONDUCT.md
vendored
@ -11,8 +11,8 @@ that standard.
|
|||||||
If you witness or experience behaviour that violates the Code, please
|
If you witness or experience behaviour that violates the Code, please
|
||||||
report it privately to the project maintainer:
|
report it privately to the project maintainer:
|
||||||
|
|
||||||
- Email: **a.donauskas@hostinger.com** with `[WaCRM conduct]` in the
|
- Email: **a.donauskas@hostinger.com** with `[CRM template conduct]` in
|
||||||
subject.
|
the subject.
|
||||||
|
|
||||||
Reports are handled confidentially. Expect an acknowledgement within
|
Reports are handled confidentially. Expect an acknowledgement within
|
||||||
72 hours and a decision on next steps within a week.
|
72 hours and a decision on next steps within a week.
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,5 +1,5 @@
|
|||||||
name: Bug report
|
name: Bug report
|
||||||
description: Something in WaCRM isn't working the way the docs say it should.
|
description: Something in the template isn't working the way the docs say it should.
|
||||||
title: "[bug] "
|
title: "[bug] "
|
||||||
labels: ["bug", "triage"]
|
labels: ["bug", "triage"]
|
||||||
body:
|
body:
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -6,6 +6,6 @@ contact_links:
|
|||||||
- name: Setup / "how do I..." questions
|
- name: Setup / "how do I..." questions
|
||||||
url: https://github.com/ArnasDon/wacrm/blob/main/docs/README.md
|
url: https://github.com/ArnasDon/wacrm/blob/main/docs/README.md
|
||||||
about: Check the docs first — setup, deploy, troubleshooting are all covered.
|
about: Check the docs first — setup, deploy, troubleshooting are all covered.
|
||||||
- name: Using WaCRM as a template (forking)
|
- name: Using this as a template (forking)
|
||||||
url: https://github.com/ArnasDon/wacrm/blob/main/CONTRIBUTING.md
|
url: https://github.com/ArnasDon/wacrm/blob/main/CONTRIBUTING.md
|
||||||
about: WaCRM is a template. Most changes belong in your fork, not an upstream issue — here's how that works.
|
about: This is a template. Most changes belong in your fork, not an upstream issue — here's how that works.
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
4
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -8,7 +8,7 @@ body:
|
|||||||
value: |
|
value: |
|
||||||
Thanks for the idea — but read this first.
|
Thanks for the idea — but read this first.
|
||||||
|
|
||||||
WaCRM is a **template**, not a collaborative product. The
|
This is a **template**, not a collaborative product. The
|
||||||
upstream scope is intentionally narrow, so most feature
|
upstream scope is intentionally narrow, so most feature
|
||||||
requests end up as *"build this in your fork"* rather than
|
requests end up as *"build this in your fork"* rather than
|
||||||
landing here. That's the point of a template.
|
landing here. That's the point of a template.
|
||||||
@ -29,7 +29,7 @@ body:
|
|||||||
id: problem
|
id: problem
|
||||||
attributes:
|
attributes:
|
||||||
label: What's the problem?
|
label: What's the problem?
|
||||||
description: What are you trying to do today that WaCRM makes harder than it should?
|
description: What are you trying to do today that the template makes harder than it should?
|
||||||
placeholder: |
|
placeholder: |
|
||||||
When a broadcast ends I have no way to see which recipients
|
When a broadcast ends I have no way to see which recipients
|
||||||
didn't reply so I can follow up manually.
|
didn't reply so I can follow up manually.
|
||||||
|
|||||||
6
.github/SECURITY.md
vendored
6
.github/SECURITY.md
vendored
@ -1,6 +1,6 @@
|
|||||||
# Security Policy
|
# Security Policy
|
||||||
|
|
||||||
Thanks for taking the time to look into WaCRM's security.
|
Thanks for taking the time to look into the security of this template.
|
||||||
|
|
||||||
## Reporting a vulnerability
|
## Reporting a vulnerability
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ Instead, please report privately via one of:
|
|||||||
|
|
||||||
- [GitHub Security Advisories](https://github.com/ArnasDon/wacrm/security/advisories/new)
|
- [GitHub Security Advisories](https://github.com/ArnasDon/wacrm/security/advisories/new)
|
||||||
(preferred — keeps the disclosure, fix, and CVE all in one place).
|
(preferred — keeps the disclosure, fix, and CVE all in one place).
|
||||||
- Email: `a.donauskas@hostinger.com` with `[WaCRM security]` in the subject.
|
- Email: `a.donauskas@hostinger.com` with `[CRM template security]` in the subject.
|
||||||
|
|
||||||
Include, if you can:
|
Include, if you can:
|
||||||
|
|
||||||
@ -59,4 +59,4 @@ action against anyone who:
|
|||||||
- Gives us reasonable time to respond before any public disclosure.
|
- Gives us reasonable time to respond before any public disclosure.
|
||||||
- Doesn't exploit the issue beyond what's necessary to demonstrate it.
|
- Doesn't exploit the issue beyond what's necessary to demonstrate it.
|
||||||
|
|
||||||
Thanks for helping keep WaCRM (and its forks) safe.
|
Thanks for helping keep this template (and its forks) safe.
|
||||||
|
|||||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
Heads up: WaCRM is a template, not a collaborative product. Most
|
Heads up: this is a template, not a collaborative product. Most
|
||||||
changes belong in your fork. See CONTRIBUTING.md for which kinds of
|
changes belong in your fork. See CONTRIBUTING.md for which kinds of
|
||||||
upstream PRs tend to land (security, correctness, docs) vs. which
|
upstream PRs tend to land (security, correctness, docs) vs. which
|
||||||
belong in a fork (new features, stack swaps, opinionated refactors).
|
belong in a fork (new features, stack swaps, opinionated refactors).
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Using WaCRM
|
# Using this template
|
||||||
|
|
||||||
WaCRM is a **template repository**, not a collaborative product. The
|
This is a **template repository**, not a collaborative product. The
|
||||||
expected flow is:
|
expected flow is:
|
||||||
|
|
||||||
1. **Fork** it to your own GitHub account or organisation.
|
1. **Fork** it to your own GitHub account or organisation.
|
||||||
@ -95,9 +95,9 @@ closed — open the issue first to align.
|
|||||||
|
|
||||||
## If you maintain a public fork
|
## If you maintain a public fork
|
||||||
|
|
||||||
- Rebrand. The WaCRM name, favicon, and `wacrm.tech` URL belong to the
|
- Rebrand. The "CRM Template for WhatsApp" name, favicon, and
|
||||||
upstream project; please swap them for your own before putting your
|
`wacrm.tech` URL belong to the upstream project; please swap them
|
||||||
deployment in front of users.
|
for your own before putting your deployment in front of users.
|
||||||
- Keep the MIT [`LICENSE`](./LICENSE) file — that's how the template's
|
- Keep the MIT [`LICENSE`](./LICENSE) file — that's how the template's
|
||||||
permissions travel with the code. Attribution in a `README` section
|
permissions travel with the code. Attribution in a `README` section
|
||||||
is appreciated but not required.
|
is appreciated but not required.
|
||||||
|
|||||||
10
README.md
10
README.md
@ -1,8 +1,8 @@
|
|||||||
# WaCRM
|
# CRM Template for WhatsApp
|
||||||
|
|
||||||
> Self-hostable WhatsApp CRM template — shared inbox, contacts, sales
|
> Self-hostable CRM template for WhatsApp — shared inbox, contacts,
|
||||||
> pipelines, broadcasts, and no-code automations. Fork it, brand it,
|
> sales pipelines, broadcasts, and no-code automations. Fork it, brand
|
||||||
> host it.
|
> it, host it.
|
||||||
|
|
||||||
[](./LICENSE)
|
[](./LICENSE)
|
||||||
[](https://github.com/ArnasDon/wacrm/actions/workflows/ci.yml)
|
[](https://github.com/ArnasDon/wacrm/actions/workflows/ci.yml)
|
||||||
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
## Why fork this?
|
## Why fork this?
|
||||||
|
|
||||||
WaCRM is a **template**, not a product. Forking means you get:
|
This is a **template**, not a product. Forking means you get:
|
||||||
|
|
||||||
- **Full ownership** — your code, your Supabase project, your domain,
|
- **Full ownership** — your code, your Supabase project, your domain,
|
||||||
your data. No SaaS lock-in, no seat pricing, no trust dance.
|
your data. No SaaS lock-in, no seat pricing, no trust dance.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# WaCRM documentation
|
# Documentation
|
||||||
|
|
||||||
WaCRM is a self-hostable WhatsApp CRM built on Next.js and Supabase. These
|
A self-hostable CRM template for WhatsApp built on Next.js and Supabase.
|
||||||
docs walk you from a freshly forked repo to a production deploy.
|
These docs walk you from a freshly forked repo to a production deploy.
|
||||||
|
|
||||||
## Reading order
|
## Reading order
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Automations cron
|
# Automations cron
|
||||||
|
|
||||||
WaCRM's **Automations** module lets you build flows that react to WhatsApp
|
The **Automations** module lets you build flows that react to WhatsApp
|
||||||
events (new message, new contact, keyword match, schedule, etc.). Most
|
events (new message, new contact, keyword match, schedule, etc.). Most
|
||||||
steps run inline — the exception is the **Wait** step, which parks the
|
steps run inline — the exception is the **Wait** step, which parks the
|
||||||
execution in `automation_pending_executions` until its due time.
|
execution in `automation_pending_executions` until its due time.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Deploy on Hostinger
|
# Deploy on Hostinger
|
||||||
|
|
||||||
Hostinger's **[Managed Node.js Hosting](https://www.hostinger.com/web-apps-hosting)**
|
Hostinger's **[Managed Node.js Hosting](https://www.hostinger.com/web-apps-hosting)**
|
||||||
is the recommended way to run WaCRM in production: Hostinger patches the
|
is the recommended way to run this template in production: Hostinger patches the
|
||||||
OS and the Node runtime, handles SSL, and gives you a Git-based deploy
|
OS and the Node runtime, handles SSL, and gives you a Git-based deploy
|
||||||
flow from hPanel. You deploy from your fork without ever opening an SSH
|
flow from hPanel. You deploy from your fork without ever opening an SSH
|
||||||
session if you don't want to.
|
session if you don't want to.
|
||||||
@ -93,7 +93,7 @@ baked into the client bundle.
|
|||||||
From the app page, click **Restart application** (or run the equivalent
|
From the app page, click **Restart application** (or run the equivalent
|
||||||
from the terminal). hPanel boots `npm start` behind its own reverse proxy
|
from the terminal). hPanel boots `npm start` behind its own reverse proxy
|
||||||
on the domain you configured. Hit the URL in a browser — you should land
|
on the domain you configured. Hit the URL in a browser — you should land
|
||||||
on the WaCRM marketing page.
|
on the marketing page.
|
||||||
|
|
||||||
SSL is provisioned automatically. If you used a subdomain, Hostinger's
|
SSL is provisioned automatically. If you used a subdomain, Hostinger's
|
||||||
AutoSSL usually takes a minute or two; until then the site may serve the
|
AutoSSL usually takes a minute or two; until then the site may serve the
|
||||||
@ -139,7 +139,7 @@ idempotent.
|
|||||||
|
|
||||||
## When to reach for a VPS instead
|
## When to reach for a VPS instead
|
||||||
|
|
||||||
Managed Node.js covers most WaCRM deploys. Consider
|
Managed Node.js covers most deploys of this template. Consider
|
||||||
[Hostinger VPS](https://www.hostinger.com/vps-hosting) if you need:
|
[Hostinger VPS](https://www.hostinger.com/vps-hosting) if you need:
|
||||||
|
|
||||||
- Long-running background workers beyond what the single Next.js process
|
- Long-running background workers beyond what the single Next.js process
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Getting started
|
# Getting started
|
||||||
|
|
||||||
Run WaCRM locally in about 15 minutes. This guide assumes Node.js 20+ and
|
Run the template locally in about 15 minutes. This guide assumes Node.js 20+ and
|
||||||
npm are already installed.
|
npm are already installed.
|
||||||
|
|
||||||
## 1. Fork and clone
|
## 1. Fork and clone
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
# Supabase setup
|
# Supabase setup
|
||||||
|
|
||||||
WaCRM uses Supabase for Postgres, authentication, row-level security (RLS),
|
This template uses Supabase for Postgres, authentication, row-level security (RLS),
|
||||||
and (optionally) storage. You need one Supabase project per WaCRM
|
and (optionally) storage. You need one Supabase project per deployment.
|
||||||
deployment.
|
|
||||||
|
|
||||||
## 1. Create the project
|
## 1. Create the project
|
||||||
|
|
||||||
@ -75,7 +74,7 @@ emails link back correctly.
|
|||||||
|
|
||||||
## 6. (Optional) Storage
|
## 6. (Optional) Storage
|
||||||
|
|
||||||
WaCRM downloads WhatsApp media through Meta's `/download` endpoint and
|
The app downloads WhatsApp media through Meta's `/download` endpoint and
|
||||||
currently relays it on demand rather than caching it in Supabase Storage.
|
currently relays it on demand rather than caching it in Supabase Storage.
|
||||||
No bucket setup is required for a default install.
|
No bucket setup is required for a default install.
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,7 @@ Set `NEXT_PUBLIC_SITE_URL` **and** add the same origin to Supabase →
|
|||||||
### Webhook verification fails in Meta
|
### Webhook verification fails in Meta
|
||||||
|
|
||||||
- The **verify token** in Meta must match exactly what you saved in
|
- The **verify token** in Meta must match exactly what you saved in
|
||||||
**Settings → WhatsApp** inside WaCRM.
|
**Settings → WhatsApp** inside the app.
|
||||||
- The callback URL must be reachable without auth. Test it yourself:
|
- The callback URL must be reachable without auth. Test it yourself:
|
||||||
`curl 'https://crm.example.com/api/whatsapp/webhook?hub.mode=subscribe&hub.verify_token=<token>&hub.challenge=test'`
|
`curl 'https://crm.example.com/api/whatsapp/webhook?hub.mode=subscribe&hub.verify_token=<token>&hub.challenge=test'`
|
||||||
should return `test`.
|
should return `test`.
|
||||||
@ -91,7 +91,7 @@ endpoint is fine and the problem is just the schedule.
|
|||||||
|
|
||||||
### An automation fires twice for the same message
|
### An automation fires twice for the same message
|
||||||
|
|
||||||
Most likely two WaCRM instances share one Supabase project and both
|
Most likely two app instances share one Supabase project and both
|
||||||
receive the same webhook. The webhook handler deduplicates by Meta's
|
receive the same webhook. The webhook handler deduplicates by Meta's
|
||||||
`wamid`, but only within a single deploy — split-brain setups can double
|
`wamid`, but only within a single deploy — split-brain setups can double
|
||||||
up. Either consolidate to one deploy or route the webhook to exactly one.
|
up. Either consolidate to one deploy or route the webhook to exactly one.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# WhatsApp setup
|
# WhatsApp setup
|
||||||
|
|
||||||
WaCRM talks to the official **WhatsApp Business Cloud API** (Meta). Each
|
This template talks to the official **WhatsApp Business Cloud API** (Meta). Each
|
||||||
account stores its own `phone_number_id`, `waba_id`, and encrypted
|
account stores its own `phone_number_id`, `waba_id`, and encrypted
|
||||||
`access_token` — there is no shared app-level token. This page walks
|
`access_token` — there is no shared app-level token. This page walks
|
||||||
through getting those values and wiring the webhook.
|
through getting those values and wiring the webhook.
|
||||||
@ -45,9 +45,9 @@ generate a **System User** access token:
|
|||||||
- `whatsapp_business_messaging`
|
- `whatsapp_business_messaging`
|
||||||
4. Copy the token. **This is shown only once.**
|
4. Copy the token. **This is shown only once.**
|
||||||
|
|
||||||
## 4. Connect it inside WaCRM
|
## 4. Connect it inside the app
|
||||||
|
|
||||||
1. Run WaCRM locally (or open your deployed instance).
|
1. Run the app locally (or open your deployed instance).
|
||||||
2. Sign in, then go to **Settings → WhatsApp**.
|
2. Sign in, then go to **Settings → WhatsApp**.
|
||||||
3. Fill in:
|
3. Fill in:
|
||||||
- **Phone number ID** — from step 3.
|
- **Phone number ID** — from step 3.
|
||||||
@ -55,7 +55,7 @@ generate a **System User** access token:
|
|||||||
- **Access token** — the System User token from step 3.
|
- **Access token** — the System User token from step 3.
|
||||||
- **Verify token** — any random string you make up; you will paste the
|
- **Verify token** — any random string you make up; you will paste the
|
||||||
same value into Meta in the next step.
|
same value into Meta in the next step.
|
||||||
4. Save. WaCRM encrypts the access token and verify token with your
|
4. Save. The app encrypts the access token and verify token with your
|
||||||
`ENCRYPTION_KEY` before writing them to Supabase.
|
`ENCRYPTION_KEY` before writing them to Supabase.
|
||||||
|
|
||||||
## 5. Configure the webhook in Meta
|
## 5. Configure the webhook in Meta
|
||||||
@ -68,7 +68,7 @@ Under **WhatsApp → Configuration → Webhook**:
|
|||||||
- Production: `https://<your-domain>/api/whatsapp/webhook`.
|
- Production: `https://<your-domain>/api/whatsapp/webhook`.
|
||||||
- **Verify token**: the same string you entered in step 4.
|
- **Verify token**: the same string you entered in step 4.
|
||||||
- Click **Verify and save**. Meta sends a GET with
|
- Click **Verify and save**. Meta sends a GET with
|
||||||
`hub.challenge` — WaCRM's webhook route decrypts stored verify tokens
|
`hub.challenge` — the app's webhook route decrypts stored verify tokens
|
||||||
and echoes the challenge back. If verification fails, double-check the
|
and echoes the challenge back. If verification fails, double-check the
|
||||||
verify token matches and the callback URL is publicly reachable.
|
verify token matches and the callback URL is publicly reachable.
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ sync on the broadcast UI.
|
|||||||
## 6. Signature verification (required)
|
## 6. Signature verification (required)
|
||||||
|
|
||||||
Set `META_APP_SECRET` to your app's **App Secret** (Meta for Developers →
|
Set `META_APP_SECRET` to your app's **App Secret** (Meta for Developers →
|
||||||
App Settings → Basic). WaCRM validates the `X-Hub-Signature-256` HMAC
|
App Settings → Basic). The app validates the `X-Hub-Signature-256` HMAC
|
||||||
on every inbound webhook and **rejects every request if the env var is
|
on every inbound webhook and **rejects every request if the env var is
|
||||||
not set** — anyone who knew the webhook URL could otherwise spoof
|
not set** — anyone who knew the webhook URL could otherwise spoof
|
||||||
messages and status updates. Configure it before pointing the webhook
|
messages and status updates. Configure it before pointing the webhook
|
||||||
@ -96,9 +96,8 @@ at a deployed instance.
|
|||||||
|
|
||||||
1. From Meta's **API Setup** page, send a test message to a number that is
|
1. From Meta's **API Setup** page, send a test message to a number that is
|
||||||
a registered tester.
|
a registered tester.
|
||||||
2. Watch the WaCRM Inbox — the message should appear within a second or
|
2. Watch the Inbox — the message should appear within a second or two.
|
||||||
two.
|
3. Reply from the app; the recipient gets a real WhatsApp message.
|
||||||
3. Reply from WaCRM; the recipient gets a real WhatsApp message.
|
|
||||||
|
|
||||||
If nothing shows up, see [troubleshooting.md](./troubleshooting.md).
|
If nothing shows up, see [troubleshooting.md](./troubleshooting.md).
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "wacrm",
|
"name": "wacrm",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Self-hostable WhatsApp CRM built on Next.js and Supabase — shared inbox, contacts, sales pipelines, broadcasts, and no-code automations.",
|
"description": "Self-hostable CRM template for WhatsApp built on Next.js and Supabase — shared inbox, contacts, sales pipelines, broadcasts, and no-code automations.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Arnas Donauskas",
|
"author": "Arnas Donauskas",
|
||||||
"homepage": "https://wacrm.tech",
|
"homepage": "https://wacrm.tech",
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export default function LoginPage() {
|
|||||||
</div>
|
</div>
|
||||||
<CardTitle className="text-xl text-white">Welcome back</CardTitle>
|
<CardTitle className="text-xl text-white">Welcome back</CardTitle>
|
||||||
<CardDescription className="text-slate-400">
|
<CardDescription className="text-slate-400">
|
||||||
Sign in to your WaCRM account
|
Sign in to your account
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export default function SignupPage() {
|
|||||||
</div>
|
</div>
|
||||||
<CardTitle className="text-xl text-white">Create account</CardTitle>
|
<CardTitle className="text-xl text-white">Create account</CardTitle>
|
||||||
<CardDescription className="text-slate-400">
|
<CardDescription className="text-slate-400">
|
||||||
Get started with WaCRM
|
Get started with CRM Template for WhatsApp
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|||||||
@ -11,11 +11,11 @@ import { decrypt } from '@/lib/whatsapp/encryption'
|
|||||||
* template locally, try to broadcast with it, and hit Meta's error
|
* template locally, try to broadcast with it, and hit Meta's error
|
||||||
* #132001 "Template name does not exist in the translation" — because
|
* #132001 "Template name does not exist in the translation" — because
|
||||||
* Meta had never seen the template, or had it approved under a
|
* Meta had never seen the template, or had it approved under a
|
||||||
* different language code than what WaCRM stored.
|
* different language code than what we stored locally.
|
||||||
*
|
*
|
||||||
* This route pulls the source of truth (Meta's approved templates)
|
* This route pulls the source of truth (Meta's approved templates)
|
||||||
* and upserts them into the local catalog by (user_id, name, language).
|
* and upserts them into the local catalog by (user_id, name, language).
|
||||||
* After a sync, every template row in WaCRM is guaranteed to match
|
* After a sync, every local template row is guaranteed to match
|
||||||
* something Meta will actually accept on send.
|
* something Meta will actually accept on send.
|
||||||
*
|
*
|
||||||
* Scope:
|
* Scope:
|
||||||
|
|||||||
@ -3,9 +3,12 @@ import { DocsShell } from '@/components/docs/shell'
|
|||||||
import { listDocs } from '@/lib/docs/content'
|
import { listDocs } from '@/lib/docs/content'
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: { template: '%s — WaCRM Docs', default: 'WaCRM Docs' },
|
title: {
|
||||||
|
template: '%s — CRM Template for WhatsApp Docs',
|
||||||
|
default: 'CRM Template for WhatsApp Docs',
|
||||||
|
},
|
||||||
description:
|
description:
|
||||||
'Setup, configuration, and deployment docs for the WaCRM template.',
|
'Setup, configuration, and deployment docs for the CRM Template for WhatsApp.',
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function DocsLayout({
|
export default async function DocsLayout({
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export default async function DocsIndexPage() {
|
|||||||
Documentation
|
Documentation
|
||||||
</p>
|
</p>
|
||||||
<h1 className="mt-2 text-3xl font-bold tracking-tight text-white sm:text-4xl">
|
<h1 className="mt-2 text-3xl font-bold tracking-tight text-white sm:text-4xl">
|
||||||
Self-host WaCRM end to end
|
Self-host the CRM template for WhatsApp end to end
|
||||||
</h1>
|
</h1>
|
||||||
<p className="mt-4 text-base leading-relaxed text-slate-400">
|
<p className="mt-4 text-base leading-relaxed text-slate-400">
|
||||||
Everything you need to take the template from a fresh fork to a
|
Everything you need to take the template from a fresh fork to a
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ImageResponse } from "next/og";
|
import { ImageResponse } from "next/og";
|
||||||
|
|
||||||
// Replaces the default Next.js favicon with the WaCRM mark — emerald
|
// Replaces the default Next.js favicon with the brand mark — emerald
|
||||||
// rounded square + white chat-bubble glyph — matching the sidebar
|
// rounded square + white chat-bubble glyph — matching the sidebar
|
||||||
// logo in `src/components/layout/sidebar.tsx`. Next.js renders this
|
// logo in `src/components/layout/sidebar.tsx`. Next.js renders this
|
||||||
// at build time and auto-injects <link rel="icon"> into <head>.
|
// at build time and auto-injects <link rel="icon"> into <head>.
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { SITE_URL } from '@/lib/seo/site-config'
|
|||||||
* robots.txt served at /robots.txt. We explicitly disallow every
|
* robots.txt served at /robots.txt. We explicitly disallow every
|
||||||
* gated area so crawlers don't spend their budget on pages they'll
|
* gated area so crawlers don't spend their budget on pages they'll
|
||||||
* bounce off. Auth pages are closed off too — no SEO value, and
|
* bounce off. Auth pages are closed off too — no SEO value, and
|
||||||
* we don't want "Sign in to WaCRM" competing with the landing page
|
* we don't want a "Sign in" page competing with the landing page
|
||||||
* in SERPs.
|
* in SERPs.
|
||||||
*/
|
*/
|
||||||
export default function robots(): MetadataRoute.Robots {
|
export default function robots(): MetadataRoute.Robots {
|
||||||
|
|||||||
@ -32,11 +32,17 @@ export function DocsShell({ pages, children }: DocsShellProps) {
|
|||||||
>
|
>
|
||||||
{mobileOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
|
{mobileOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
|
||||||
</button>
|
</button>
|
||||||
<Link href="/" className="flex items-center gap-2" aria-label="WaCRM home">
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
aria-label="CRM Template for WhatsApp home"
|
||||||
|
>
|
||||||
<span className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
<span className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
||||||
<MessageSquare className="h-4 w-4 text-white" />
|
<MessageSquare className="h-4 w-4 text-white" />
|
||||||
</span>
|
</span>
|
||||||
<span className="text-lg font-semibold text-white">WaCRM</span>
|
<span className="text-sm font-semibold text-white">
|
||||||
|
CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
<span className="hidden rounded-md border border-slate-700 bg-slate-900 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-slate-400 sm:inline-block">
|
<span className="hidden rounded-md border border-slate-700 bg-slate-900 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-slate-400 sm:inline-block">
|
||||||
Docs
|
Docs
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export function FeaturesGrid() {
|
|||||||
<SectionHeader
|
<SectionHeader
|
||||||
eyebrow="Everything you need"
|
eyebrow="Everything you need"
|
||||||
title="One toolkit for your WhatsApp business"
|
title="One toolkit for your WhatsApp business"
|
||||||
description="Stop stitching together an inbox, a spreadsheet, and a broadcast tool. WaCRM brings them together — and talks to WhatsApp natively."
|
description="Stop stitching together an inbox, a spreadsheet, and a broadcast tool. This CRM template for WhatsApp brings them together — and talks to WhatsApp natively."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
|||||||
@ -7,11 +7,17 @@ export function Footer() {
|
|||||||
<footer className="border-t border-slate-800 bg-slate-950">
|
<footer className="border-t border-slate-800 bg-slate-950">
|
||||||
<div className="mx-auto grid w-full max-w-7xl grid-cols-2 gap-8 px-6 py-12 sm:grid-cols-5">
|
<div className="mx-auto grid w-full max-w-7xl grid-cols-2 gap-8 px-6 py-12 sm:grid-cols-5">
|
||||||
<div className="col-span-2 sm:col-span-2">
|
<div className="col-span-2 sm:col-span-2">
|
||||||
<Link href="/" className="flex items-center gap-2" aria-label="WaCRM home">
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
aria-label="CRM Template for WhatsApp home"
|
||||||
|
>
|
||||||
<span className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
<span className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
||||||
<MessageSquare className="h-4 w-4 text-white" />
|
<MessageSquare className="h-4 w-4 text-white" />
|
||||||
</span>
|
</span>
|
||||||
<span className="text-lg font-semibold text-white">WaCRM</span>
|
<span className="text-sm font-semibold text-white">
|
||||||
|
CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
<p className="mt-3 max-w-sm text-sm text-slate-500">
|
<p className="mt-3 max-w-sm text-sm text-slate-500">
|
||||||
One toolkit for your WhatsApp business — shared inbox, pipelines,
|
One toolkit for your WhatsApp business — shared inbox, pipelines,
|
||||||
@ -58,7 +64,7 @@ export function Footer() {
|
|||||||
|
|
||||||
<div className="border-t border-slate-900">
|
<div className="border-t border-slate-900">
|
||||||
<div className="mx-auto flex w-full max-w-7xl flex-col items-start justify-between gap-3 px-6 py-5 text-xs text-slate-500 sm:flex-row sm:items-center">
|
<div className="mx-auto flex w-full max-w-7xl flex-col items-start justify-between gap-3 px-6 py-5 text-xs text-slate-500 sm:flex-row sm:items-center">
|
||||||
<span>© {year} WaCRM. All rights reserved.</span>
|
<span>© {year} CRM Template for WhatsApp. All rights reserved.</span>
|
||||||
<span>Built on the official WhatsApp Business API.</span>
|
<span>Built on the official WhatsApp Business API.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -27,7 +27,9 @@ export function AnalyticsMock() {
|
|||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="ml-3 text-[10px] text-slate-500">Dashboard — WaCRM</span>
|
<span className="ml-3 text-[10px] text-slate-500">
|
||||||
|
Dashboard — CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-3 p-4">
|
<div className="space-y-3 p-4">
|
||||||
|
|||||||
@ -47,7 +47,9 @@ export function AutomationMock() {
|
|||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="ml-3 text-[10px] text-slate-500">Automations — WaCRM</span>
|
<span className="ml-3 text-[10px] text-slate-500">
|
||||||
|
Automations — CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Dotted canvas — matches the real flow builder's background. */}
|
{/* Dotted canvas — matches the real flow builder's background. */}
|
||||||
|
|||||||
@ -14,7 +14,9 @@ export function InboxMock() {
|
|||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="ml-3 text-[10px] text-slate-500">Inbox — WaCRM</span>
|
<span className="ml-3 text-[10px] text-slate-500">
|
||||||
|
Inbox — CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-[180px_1fr] lg:grid-cols-[220px_1fr]">
|
<div className="grid grid-cols-[180px_1fr] lg:grid-cols-[220px_1fr]">
|
||||||
|
|||||||
@ -34,7 +34,9 @@ export function PipelineMock() {
|
|||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
<span className="h-2.5 w-2.5 rounded-full bg-slate-700" />
|
||||||
<span className="ml-3 text-[10px] text-slate-500">Pipelines — WaCRM</span>
|
<span className="ml-3 text-[10px] text-slate-500">
|
||||||
|
Pipelines — CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-3 gap-3 p-4">
|
<div className="grid grid-cols-3 gap-3 p-4">
|
||||||
|
|||||||
@ -60,11 +60,17 @@ export function LandingNav() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="mx-auto flex h-16 w-full max-w-7xl items-center justify-between px-6">
|
<div className="mx-auto flex h-16 w-full max-w-7xl items-center justify-between px-6">
|
||||||
<Link href="/" className="flex items-center gap-2" aria-label="WaCRM home">
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
aria-label="CRM Template for WhatsApp home"
|
||||||
|
>
|
||||||
<span className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
<span className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
||||||
<MessageSquare className="h-4 w-4 text-white" />
|
<MessageSquare className="h-4 w-4 text-white" />
|
||||||
</span>
|
</span>
|
||||||
<span className="text-lg font-semibold text-white">WaCRM</span>
|
<span className="text-sm font-semibold text-white">
|
||||||
|
CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<nav className="hidden items-center gap-8 md:flex">
|
<nav className="hidden items-center gap-8 md:flex">
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export function OpenSource() {
|
|||||||
<SectionHeader
|
<SectionHeader
|
||||||
eyebrow="Open source"
|
eyebrow="Open source"
|
||||||
title="Fork it, brand it, host it"
|
title="Fork it, brand it, host it"
|
||||||
description="WaCRM is a template you can take and make your own. Grab the source on GitHub and self-host — we recommend Hostinger Managed Node.js Hosting for a zero-ops deploy."
|
description="This CRM template for WhatsApp is a template you can take and make your own. Grab the source on GitHub and self-host — we recommend Hostinger Managed Node.js Hosting for a zero-ops deploy."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="mx-auto grid max-w-5xl grid-cols-1 gap-5 md:grid-cols-2">
|
<div className="mx-auto grid max-w-5xl grid-cols-1 gap-5 md:grid-cols-2">
|
||||||
@ -55,7 +55,7 @@ export function OpenSource() {
|
|||||||
</h3>
|
</h3>
|
||||||
<p className="mt-1.5 text-sm leading-relaxed text-slate-400">
|
<p className="mt-1.5 text-sm leading-relaxed text-slate-400">
|
||||||
Best fit for this template — connect your forked repo to
|
Best fit for this template — connect your forked repo to
|
||||||
Managed Node.js Hosting and WaCRM is live in a few minutes. No
|
Managed Node.js Hosting and your CRM is live in a few minutes. No
|
||||||
servers to patch.
|
servers to patch.
|
||||||
</p>
|
</p>
|
||||||
<span className="mt-5 inline-flex items-center gap-1.5 text-sm font-medium text-emerald-400 transition-colors group-hover:text-emerald-300">
|
<span className="mt-5 inline-flex items-center gap-1.5 text-sm font-medium text-emerald-400 transition-colors group-hover:text-emerald-300">
|
||||||
|
|||||||
@ -114,7 +114,9 @@ export function Sidebar({ open = false, onClose }: SidebarProps) {
|
|||||||
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-500">
|
||||||
<MessageSquare className="h-4 w-4 text-white" />
|
<MessageSquare className="h-4 w-4 text-white" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-lg font-semibold text-white">WaCRM</span>
|
<span className="text-sm font-semibold text-white">
|
||||||
|
CRM Template for WhatsApp
|
||||||
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@ -214,7 +214,7 @@ export function ProfileForm() {
|
|||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-white">Profile</CardTitle>
|
<CardTitle className="text-white">Profile</CardTitle>
|
||||||
<CardDescription className="text-slate-400">
|
<CardDescription className="text-slate-400">
|
||||||
How you show up across WaCRM. Your avatar and name appear in the
|
How you show up across the app. Your avatar and name appear in the
|
||||||
header, sidebar, and anywhere your teammates see you.
|
header, sidebar, and anywhere your teammates see you.
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|||||||
@ -56,9 +56,8 @@ export function SessionsCard() {
|
|||||||
Active sessions
|
Active sessions
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription className="text-slate-400">
|
<CardDescription className="text-slate-400">
|
||||||
Sign out of every device where you're logged in to WaCRM —
|
Sign out of every device where you're logged in — including
|
||||||
including this one. Useful if you lost a laptop or shared your
|
this one. Useful if you lost a laptop or shared your password.
|
||||||
password.
|
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const ORDER: Record<string, { order: number; section: string; description: strin
|
|||||||
'getting-started': {
|
'getting-started': {
|
||||||
order: 1,
|
order: 1,
|
||||||
section: 'Setup',
|
section: 'Setup',
|
||||||
description: 'Fork, install, run WaCRM locally in about 15 minutes.',
|
description: 'Fork, install, run the template locally in about 15 minutes.',
|
||||||
},
|
},
|
||||||
'supabase-setup': {
|
'supabase-setup': {
|
||||||
order: 2,
|
order: 2,
|
||||||
@ -37,12 +37,12 @@ const ORDER: Record<string, { order: number; section: string; description: strin
|
|||||||
'environment-variables': {
|
'environment-variables': {
|
||||||
order: 4,
|
order: 4,
|
||||||
section: 'Setup',
|
section: 'Setup',
|
||||||
description: 'Full reference for every env var WaCRM reads.',
|
description: 'Full reference for every env var the app reads.',
|
||||||
},
|
},
|
||||||
'deployment-hostinger': {
|
'deployment-hostinger': {
|
||||||
order: 5,
|
order: 5,
|
||||||
section: 'Deploy',
|
section: 'Deploy',
|
||||||
description: 'Ship WaCRM on Hostinger Managed Node.js Hosting.',
|
description: 'Ship the template on Hostinger Managed Node.js Hosting.',
|
||||||
},
|
},
|
||||||
'automations-and-cron': {
|
'automations-and-cron': {
|
||||||
order: 6,
|
order: 6,
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export interface FaqItem {
|
|||||||
export const FAQ_ITEMS: FaqItem[] = [
|
export const FAQ_ITEMS: FaqItem[] = [
|
||||||
{
|
{
|
||||||
q: 'Do I need my own WhatsApp Business API access?',
|
q: 'Do I need my own WhatsApp Business API access?',
|
||||||
a: 'Yes. WaCRM plugs into your existing Meta WhatsApp Business setup — you bring the phone number and access token, we provide the CRM tooling around it. Any Meta-approved BSP (Business Solution Provider) works.',
|
a: 'Yes. This CRM template for WhatsApp plugs into your existing Meta WhatsApp Business setup — you bring the phone number and access token, we provide the CRM tooling around it. Any Meta-approved BSP (Business Solution Provider) works.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
q: 'Can my whole team share one WhatsApp number?',
|
q: 'Can my whole team share one WhatsApp number?',
|
||||||
|
|||||||
@ -9,13 +9,13 @@
|
|||||||
export const SITE_URL =
|
export const SITE_URL =
|
||||||
process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, '') || 'https://wacrm.tech'
|
process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, '') || 'https://wacrm.tech'
|
||||||
|
|
||||||
export const SITE_NAME = 'WaCRM'
|
export const SITE_NAME = 'CRM Template for WhatsApp'
|
||||||
|
|
||||||
export const SITE_TAGLINE = 'Run your WhatsApp business from one inbox'
|
export const SITE_TAGLINE = 'Run your WhatsApp business from one inbox'
|
||||||
|
|
||||||
/** Default description — reused by layout metadata and structured data. */
|
/** Default description — reused by layout metadata and structured data. */
|
||||||
export const SITE_DESCRIPTION =
|
export const SITE_DESCRIPTION =
|
||||||
'WaCRM is a WhatsApp CRM for small teams: shared inbox, contact hub, sales pipelines, broadcasts, and no-code automations — built on the official WhatsApp Business API.'
|
'A CRM template for WhatsApp built for small teams: shared inbox, contact hub, sales pipelines, broadcasts, and no-code automations — built on the official WhatsApp Business API.'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keyword targets. Search engines largely ignore the meta keywords
|
* Keyword targets. Search engines largely ignore the meta keywords
|
||||||
@ -40,7 +40,7 @@ export const OG_IMAGE_ALT = `${SITE_NAME} — ${SITE_TAGLINE}`
|
|||||||
/** Organization info surfaced in JSON-LD. */
|
/** Organization info surfaced in JSON-LD. */
|
||||||
export const ORG_INFO = {
|
export const ORG_INFO = {
|
||||||
name: SITE_NAME,
|
name: SITE_NAME,
|
||||||
legalName: 'WaCRM',
|
legalName: 'CRM Template for WhatsApp',
|
||||||
url: SITE_URL,
|
url: SITE_URL,
|
||||||
logo: `${SITE_URL}/icon`,
|
logo: `${SITE_URL}/icon`,
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user