| name | wa-implement |
| description | Drive the end-to-end implementation of the WhatsApp/Uazapi module into a React + TypeScript + Supabase project, sprint by sprint, enforcing the acceptance gate of each phase before moving on. Use when starting a WhatsApp integration from scratch, resuming a partial one, or when the user asks to install, implement, port or set up WhatsApp, Uazapi, the chat inbox or the message webhook. |
| license | MIT |
| compatibility | Target project needs React 18+ with TypeScript, a Supabase project (Postgres, Edge Functions, Realtime) and the Supabase CLI. A Uazapi account with an admin token is required to pass the sprint 1 gate. |
| metadata | {"version":"1.0.0","part-of":"whatsapp-uazapi"} |
Implement the WhatsApp/Uazapi module
Executes a six-sprint plan. Each sprint ends in a gate — a concrete,
observable outcome. A failed gate stops the run; it does not become a TODO.
Source material is in the sibling skill directory:
../whatsapp-uazapi/references/ the plan (ORQUESTRADOR + sprint-N/fase-M)
../whatsapp-uazapi/assets/ migrations, edge functions, hooks, components
In Claude Code that resolves under ${CLAUDE_SKILL_DIR}/../whatsapp-uazapi/.
If the relative path fails:
find ~ -type d -path "*skills/whatsapp-uazapi/assets" 2>/dev/null | head -3
Copy the packaged artifacts. Never retype an edge function or a migration
from memory — they carry fixes for real failure modes that are invisible in a
rewrite.
Before sprint 0 — decide the three things that shape everything
Ask the user, and record the answers where the next session can find them
(the project's CLAUDE.md / AGENTS.md):
- Tenancy. The artifacts use
company_id + get_user_company_ids(uuid).
What is the equivalent here — org_id, workspace_id, account_id, or
single-tenant? Decide now: it renames a column across 39 tables, every RLS
policy and 34 edge functions. Single-tenant projects should keep one fixed
tenant row rather than dropping the column.
- Scope. Sprints 0–2 are the minimum useful product (connect + send +
receive + inbox). Sprints 3, 4 and 5 are independent add-ons — confirm which
ones are actually wanted before building them.
- Uazapi account. Endpoint URL and admin token must exist before sprint 1
can pass its gate. If the user does not have them yet, build sprints 0–1 and
stop at the gate rather than faking it.
Also confirm the host-app adapter points listed in
../whatsapp-uazapi/SKILL.md §4: auth hook, toast, active-tenant context,
cn().
How to run each phase
For every phase, in this order:
- Read the phase document — they live in
../whatsapp-uazapi/references/,
one folder per sprint (sprint-0 through sprint-5).
It lists prerequisites, tasks, artifacts and the gate. Do not skip it — the
tasks encode ordering constraints that are not obvious from the code.
- Check the prerequisites it names. Missing prerequisite → go back, do not
improvise a workaround.
- Copy the artifacts it references, adapting only:
- the tenancy column/function name,
- the
@/ import paths to the project's alias,
- the adapter hooks.
Nothing else. If you feel the urge to "improve" a function, note it and move on.
- Apply and deploy what the phase produces:
supabase db push
supabase functions deploy <function-name>
Deploying is a real, outward action against the user's project —
ask before the first deploy of a session, then proceed.
- Run the gate. Report the observed result, not the expected one.
- Report and continue. One short block per phase: what was created, what
was adapted, gate result.
The sprints
Sprint 0 — Foundation (no UI yet)
Phases: fase-1-schema-core, fase-2-rls-grants, fase-3-realtime-config.
Applies migrations 00–04 from assets/migrations/ (read its INDEX.md
first — it explains what each one creates and the FK order), sets up the
tenancy function, RLS policies, GRANTs, the Realtime publication and .env.
Gate: migrations apply cleanly; select * from whatsapp_configs returns an
empty result and not a permission error. An error here means the GRANT or
the tenancy function is wrong — fix it now, because every later sprint depends
on it.
Sprint 1 — Instances and connection
Phases: fase-1-edge-functions, fase-2-hooks, fase-3-ui-conexao.
Five edge functions (create-instance, qrcode, test-connection, manage-instance,
configure-webhook), three hooks, and the connection UI.
Gate: create an instance from the UI → the QR renders → scan it → the
instance's status becomes connected in the database. This is the first moment
the integration is real; do not proceed on a "should work".
Sprint 2 — Messaging (the core)
Phases: fase-1-webhook, fase-2-envio, fase-3-inbox-ui, fase-4-acoes-chat.
The public webhook, the send functions, the inbox, and the chat actions.
Two things to get right, both covered in the phase docs:
verify_jwt = false in config.toml for whatsapp-webhook only, and the
webhook URL actually registered on the instance;
- phone/JID normalization — read
../whatsapp-uazapi/assets/examples/formatacao-telefone.md before writing any
send path.
Gate: a message sent from the app arrives on a real phone, and a message
sent from that phone appears in the inbox without a refresh. If it only works
one way, the failing direction is webhook registration (inbound) or phone
normalization (outbound).
Sprint 3 — Organization
Phases: assignment/squad/transfer, labels + quick replies, notes + reminders.
Independent of sprints 4 and 5.
Gate: assign a conversation to a user, apply a label, add a note — all
persist and remain invisible to another tenant.
Sprint 4 — AI
Phases: _shared/ai-gateway.ts + model config, realtime analysis, copilot +
configurable agent.
Requires an AI provider key (OpenRouter or compatible). The gateway resolves
per-tenant model configuration and caches it.
Gate: the analysis card fills for a real conversation; the copilot suggests
a reply; the configurable agent answers in the playground.
Sprint 5 — Adjacent modules
Phases: API4Com voice calls, GroupOps, notification triggers. All three are
independent — build only what was asked for.
Gate (per module): place a call; manage a group; fire a notification trigger.
Rules for this run
- A failed gate stops the run. Report what failed, what you tried, and what
the user needs to decide. Do not carry a broken foundation forward.
- Never invent Uazapi endpoints or payload fields. If something is missing
from the contract in
../whatsapp-uazapi/SKILL.md §2 and the examples, say so
and check the provider's documentation.
- Never commit credentials. Uazapi endpoint and admin token go in the
database (
whatsapp_configs), entered through the UI — not in .env, not in
a migration seed, not in a test file.
- Deploys and
db push are outward actions. Ask before the first one.
- Keep the pt-BR UI strings as they are, or translate them consistently —
do not leave a half-translated inbox.
When the run finishes
- Run the project's checks:
npx tsc --noEmit, lint, build. Deno functions:
deno check supabase/functions/<name>/index.ts.
- Write the module's context into the project's
CLAUDE.md / AGENTS.md:
## WhatsApp module (Uazapi)
Integration through Uazapi: instances in `whatsapp_instances`, credentials in
`whatsapp_configs` (per tenant, in the database — never in secrets), inbound
events on the public `whatsapp-webhook` (`verify_jwt = false`), outbound through
`send-whatsapp-*`. The inbox is driven by Supabase Realtime.
Before changing anything here, load the `whatsapp-uazapi` skill. Non-negotiable:
`admintoken` only creates instances (everything else uses the instance `token`);
the webhook always answers 2xx; group JIDs never pass through `replace(/\D/g,"")`;
every new table needs a GRANT and a Realtime publication entry.
- Report: sprints completed, gates passed, what was deliberately skipped, and
the credentials the user still needs to provide.