Feedback reporter (embed, Slack, Plutio)
Guide for developers who need to embed the bottom-right feedback button, wire Slack notifications, and create Plutio QA tasks when users submit bug / feature / improvement reports.
Security: Never commit webhook URLs, Plutio secrets, or Slack tokens to git. Store them only in
.env.local(gitignored) and Vercel Sensitive environment variables.
1. How the flow works
sequenceDiagram participant User participant Widget as BugFeedbackWidget participant API as POST /api/feedback participant DB as Supabase feedback_reports participant Storage as Supabase Storage participant Plutio as Plutio API participant Slack as Slack Incoming Webhook User->>Widget: Submit form (ES UI) Widget->>API: multipart/form-data API->>DB: insert report (if service role configured) API->>Storage: optional screenshot upload API->>Plutio: POST /tasks (if PLUTIO_* configured) API->>DB: store plutio_task_id API->>Slack: POST webhook JSON (if SLACK_FEEDBACK_WEBHOOK_URL) API->>Widget: { ok: true, reportId }
Code map:
Piece | Location |
|---|---|
Floating button + modal (Spanish UI) |
|
Mount in app shell |
|
Styles (fixed bottom-right FAB) |
|
API handler |
|
Slack Block Kit payload |
|
Plutio task create |
|
Plutio HTTP + OAuth |
|
Deep Plutio notes |
|
2. Bottom-right embed (feedback FAB)
The reporter is not a third-party iframe. It is a native React widget rendered once inside the CRM shell.
Integration on the App
CrmShellincludes<BugFeedbackWidget />next to<WooxAgentWidget />.CSS pins the button:
Desktop:
position: fixed; right: 22px; bottom: 22px; z-index: 1200Mobile (
max-width: 640px):right: 14px; bottom: 14px(WooX Agent FAB sits atright: 74pxso they do not overlap)
User opens modal → fills type, description, optional screenshot, email →
POST /api/feedback.
Add the same pattern to another Next.js surface
Copy or import
BugFeedbackWidgetand ensure the app root uses#woox-app(or duplicate the CSS selectors under your root id).Mount
<BugFeedbackWidget />in a layout that wraps all authenticated CRM pages (same level as toasts / agent FAB).Ensure
useCrm()context is available (widget reads session, org name, role for the payload).Deploy server env vars (sections 4–5). Without at least Slack webhook or Supabase service role, the API returns 503.
Customizing position
Adjust #woox-app .bug-feedback-fab in app/woox.css. Keep z-index above main content but consistent with other FABs (agent uses 1200 as well).
3. Slack message (Incoming Webhook)
App uses a Slack Incoming Webhook (no bot token required for posting). The server builds a Block Kit message in buildSlackFeedbackPayload().
Message shape
Header:
[APP Name] {Bug|Función|Mejora} — {reporter email}Fields: tipo, correo, nombre, usuario CRM, rol, organización, página, entorno (
VERCEL_ENV/NODE_ENV)Section: descripción (escaped for Slack mrkdwn)
Optional image block when a signed screenshot URL exists
To change copy or fields, edit lib/feedback/slack-message.ts and run lib/feedback/slack-message.test.ts.
Slack app used for the App
App name: Notifications [App Name](Slack workspace app)
This app owns the Incoming Webhook that posts into the team channel used for CRM feedback (e.g. #crm-woox-enrique — confirm the channel with the team).
Create or rotate the webhook URL (new project or channel)
Go to Slack API apps → open Notifications [App Name] (or Create New App → From scratch with that name if starting fresh).
Incoming Webhooks → turn On.
Add New Webhook to Workspace → pick the target channel → copy the URL (
https://hooks.slack.com/services/...).Set
SLACK_FEEDBACK_WEBHOOK_URLto that URL:Local:
.env.localVercel: Project → Settings → Environment Variables → Sensitive → Production (+ Preview if needed)
Redeploy. Test from production UI (bottom-right bug button).
Note: scripts/push-env-vercel.mjs pushes SLACK_FEEDBACK_WEBHOOK_URL from .env.local to Vercel; it does not print secret values.
If a webhook URL was ever pasted in chat or committed by mistake, revoke it in Slack (remove webhook / rotate) and create a new one.
4. Plutio task creation
When PLUTIO_API_CLIENT_ID and PLUTIO_API_SECRET are set, each successful DB insert triggers createPlutioFeedbackTask():
Title:
[App Name· {type}] {first 72 chars of description}Body: description + reporter email/name, org, page URL, screenshot link, internal
reportIdProject / board: env or defaults in
lib/feedback/plutio-config.tsColumn: task group titled QA (
PLUTIO_QA_GROUP_TITLE) or explicitPLUTIO_QA_GROUP_IDAssignee / followers: resolved by email via Plutio People API
Failures are logged as [feedback] Plutio task failed with PLUTIO_DEBUG_CHECKLIST; Slack/DB can still succeed.
Default Plutio targets (Lowcode workspace)
Override with env if the app uses a different board:
Setting | Default | Env override |
|---|---|---|
Workspace subdomain ( |
|
|
Project id |
|
|
Task board id |
|
|
QA column | title |
|
Assignee |
|
|
Followers | Italo + Wallace |
|
Plutio API client — credentials (Jesus Vargas)
The Plutio OAuth API client used for the app feedback was set up in the Lowcode Plutio workspace under Settings → API manager. Jesus Vargas maintains the client credentials used in development.
Do not paste client_id / client_secret into this repo or into Slack.
To configure a new machine or Vercel:
Ask Jesus Vargas for the current
PLUTIO_API_CLIENT_IDandPLUTIO_API_SECRET, or copy them from the team secret store / an existing developer.env.localthat already has feedback working.Put them only in
.env.localand Vercel sensitive env.
If Jesus needs to generate or rotate the Plutio client:
Log in to Plutio as a user who can access the app feedback project and QA board.
Settings → API manager → enable the client for workspace subdomain
lowcode(must matchPLUTIO_BUSINESS).Create API client (or regenerate secret on existing client).
Copy Client ID and Client secret once; share via 1Password / Vercel — not email or git.
Update every environment:
PLUTIO_API_CLIENT_IDPLUTIO_API_SECRET
Optional: create the client while logged in as the desired “creator” identity (Plutio sets
createdByfrom the OAuth client owner).
Verify token manually:
curl -sS -X POST 'https://api.plutio.com/v1.11/oauth/token' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_SECRET' \ -H 'business: lowcode'
Then GET https://api.plutio.com/v1.11/tasks?limit=1 with Authorization: Bearer … and header business: lowcode.
Vercel gap
scripts/push-env-vercel.mjs currently pushes SLACK_FEEDBACK_WEBHOOK_URL but not Plutio vars. Add Plutio keys manually in the Vercel dashboard (or extend the script locally — still never commit values).
5. Environment variables checklist
Variable | Required for | Notes |
|---|---|---|
| Slack posts | From Notifications [App Name] incoming webhook |
| DB + screenshots | Without it, only Slack works if webhook is set |
| Plutio tasks | From Jesus / API manager |
| Plutio tasks | Sensitive; rotate in Plutio if leaked |
| Plutio | Default |
| Plutio | Optional board/project/assignee overrides |
Minimum for “Slack only”: SLACK_FEEDBACK_WEBHOOK_URL.
Minimum for “DB + Plutio + Slack”: service role + Plutio pair + webhook.
6. Local testing
Copy env vars into
.env.local(request Plutio values from Jesus Vargas; webhook from Slack app above).npm run dev→ log in → click bottom-right bug icon → submit.Expect: toast “Comentario enviado. Gracias.”, message in Slack, row in
feedback_reports, Plutio task in QA column.If 503: missing webhook and service role.
If Slack OK but no Plutio: check server logs for
[feedback] Plutio task failedand.context/plutio-api-feedback.md.
Super Admin inbox (localhost only)
Super admins on localhost can see an inbox inside the modal and send “resolved” emails (FeedbackSaInbox, lib/feedback/admin-access.ts). This is separate from Slack/Plutio setup.
7. Related tests
lib/feedback/slack-message.test.tslib/feedback/plutio-http.test.ts
Run: npm run test -- lib/feedback
8. Quick reference — [APP Name] Slack app
Item | Value |
|---|---|
Slack app | Notifications [APP Name] |
Integration type | Incoming Webhook |
CRM env var |
|
Plutio credentials owner | Jesus Vargas (API manager, Lowcode workspace) |
Plutio env vars |
|