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)

components/crm/BugFeedbackWidget.tsx

Mount in app shell

components/crm/crm-shell.tsx (<BugFeedbackWidget />)

Styles (fixed bottom-right FAB)

app/woox.css — .bug-feedback-fab, modal classes

API handler

app/api/feedback/route.ts

Slack Block Kit payload

lib/feedback/slack-message.ts

Plutio task create

lib/feedback/plutio-client.ts

Plutio HTTP + OAuth

lib/feedback/plutio-http.ts, lib/feedback/plutio-config.ts

Deep Plutio notes

.context/plutio-api-feedback.md


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

  1. CrmShell includes <BugFeedbackWidget /> next to <WooxAgentWidget />.

  2. CSS pins the button:

    • Desktop: position: fixed; right: 22px; bottom: 22px; z-index: 1200

    • Mobile (max-width: 640px): right: 14px; bottom: 14px (WooX Agent FAB sits at right: 74px so they do not overlap)

  3. User opens modal → fills type, description, optional screenshot, email → POST /api/feedback.

Add the same pattern to another Next.js surface

  1. Copy or import BugFeedbackWidget and ensure the app root uses #woox-app (or duplicate the CSS selectors under your root id).

  2. Mount <BugFeedbackWidget /> in a layout that wraps all authenticated CRM pages (same level as toasts / agent FAB).

  3. Ensure useCrm() context is available (widget reads session, org name, role for the payload).

  4. 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)

  1. Go to Slack API apps → open Notifications [App Name] (or Create New App → From scratch with that name if starting fresh).

  2. Incoming Webhooks → turn On.

  3. Add New Webhook to Workspace → pick the target channel → copy the URL (https://hooks.slack.com/services/...).

  4. Set SLACK_FEEDBACK_WEBHOOK_URL to that URL:

    • Local: .env.local

    • Vercel: Project → Settings → Environment Variables → Sensitive → Production (+ Preview if needed)

  5. 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 reportId

  • Project / board: env or defaults in lib/feedback/plutio-config.ts

  • Column: task group titled QA (PLUTIO_QA_GROUP_TITLE) or explicit PLUTIO_QA_GROUP_ID

  • Assignee / 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 (business header)

lowcode

PLUTIO_BUSINESS

Project id

bSYteRJpKJRaJCRdZ

PLUTIO_FEEDBACK_PROJECT_ID

Task board id

WS2HXPy67ZbXGRn2H

PLUTIO_FEEDBACK_TASK_BOARD_ID

QA column

title QA

PLUTIO_QA_GROUP_TITLE / PLUTIO_QA_GROUP_ID

Assignee

italo@lowcode.agency

PLUTIO_FEEDBACK_ASSIGNEE_EMAIL

Followers

Italo + Wallace

PLUTIO_FEEDBACK_FOLLOWER_EMAILS

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:

  1. Ask Jesus Vargas for the current PLUTIO_API_CLIENT_ID and PLUTIO_API_SECRET, or copy them from the team secret store / an existing developer .env.local that already has feedback working.

  2. Put them only in .env.local and Vercel sensitive env.

If Jesus needs to generate or rotate the Plutio client:

  1. Log in to Plutio as a user who can access the app feedback project and QA board.

  2. Settings → API manager → enable the client for workspace subdomain lowcode (must match PLUTIO_BUSINESS).

  3. Create API client (or regenerate secret on existing client).

  4. Copy Client ID and Client secret once; share via 1Password / Vercel — not email or git.

  5. Update every environment:

    • PLUTIO_API_CLIENT_ID

    • PLUTIO_API_SECRET

  6. Optional: create the client while logged in as the desired “creator” identity (Plutio sets createdBy from 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_FEEDBACK_WEBHOOK_URL

Slack posts

From Notifications [App Name] incoming webhook

SUPABASE_SERVICE_ROLE_KEY

DB + screenshots

Without it, only Slack works if webhook is set

PLUTIO_API_CLIENT_ID

Plutio tasks

From Jesus / API manager

PLUTIO_API_SECRET

Plutio tasks

Sensitive; rotate in Plutio if leaked

PLUTIO_BUSINESS

Plutio

Default lowcode

PLUTIO_FEEDBACK_*

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

  1. Copy env vars into .env.local (request Plutio values from Jesus Vargas; webhook from Slack app above).

  2. npm run dev → log in → click bottom-right bug icon → submit.

  3. Expect: toast “Comentario enviado. Gracias.”, message in Slack, row in feedback_reports, Plutio task in QA column.

  4. If 503: missing webhook and service role.

  5. If Slack OK but no Plutio: check server logs for [feedback] Plutio task failed and .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.ts

  • lib/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

SLACK_FEEDBACK_WEBHOOK_URL

Plutio credentials owner

Jesus Vargas (API manager, Lowcode workspace)

Plutio env vars

PLUTIO_API_CLIENT_ID, PLUTIO_API_SECRET



Was this article helpful?
© 2026 LowCode Internal Docs