@digitalvibes/website-feedback
v0.4.1
Published
Development feedback overlay and Next.js App Router handlers for AI-assisted website revisions.
Readme
dibe Website Feedback
Development feedback overlay for Next.js App Router websites. Enable it on protected dev deployments, collect page and text-selection feedback in Postgres, then let an AI coding agent work through the entries.
What It Provides
- A red/white DIBE-style feedback bug in the bottom-right corner.
- A selected-text bug that opens a
change_textfeedback composer. - A fullscreen feedback dashboard for the current website.
- Next.js App Router route handlers for create, list, update, and delete.
- Postgres storage with route, URL, selection, viewport, user-agent, DOM selector, nearby text, and stage metadata.
Install From npm
pnpm add @digitalvibes/website-feedback pgThe package is published under the @digitalvibes npm scope. You need access to that npm org to publish it. If you do not own the scope, rename name in package.json before publishing.
Install Locally Before Publishing
From another Next.js project:
pnpm add file:../path/to/dibe-website-feedbackAfter changing this package locally, rebuild it and reinstall in the consuming app:
cd /path/to/dibe-website-feedback
pnpm build
cd /path/to/your/next-app
pnpm installEnvironment
NEXT_PUBLIC_DIBE_FEEDBACK_ENABLED=true
NEXT_PUBLIC_DIBE_FEEDBACK_SITE_ID=my-site
DIBE_FEEDBACK_DATABASE_URL=postgres://user:password@host:5432/db
# Optional. Overlay UI language: "en" (default) or "de".
NEXT_PUBLIC_DIBE_FEEDBACK_LANGUAGE=deYou can also set the language per mount with <WebsiteFeedbackProvider language="de">.
Example for Savali:
NEXT_PUBLIC_DIBE_FEEDBACK_ENABLED=true
NEXT_PUBLIC_DIBE_FEEDBACK_SITE_ID=savaliRestart next dev after changing NEXT_PUBLIC_DIBE_FEEDBACK_ENABLED or NEXT_PUBLIC_DIBE_FEEDBACK_SITE_ID.
To keep the real feedback overlay out of builds where these env vars are missing, wrap your Next config:
// next.config.ts
import type { NextConfig } from "next";
import { withDibeFeedback } from "@digitalvibes/website-feedback/next-config";
const nextConfig: NextConfig = {};
export default withDibeFeedback(nextConfig);App Router Setup
Wrap your app or development layout:
import type { ReactNode } from "react";
import { WebsiteFeedbackProvider } from "@digitalvibes/website-feedback/client";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<WebsiteFeedbackProvider>{children}</WebsiteFeedbackProvider>
</body>
</html>
);
}Mount the API route:
// app/api/dibe-feedback/route.ts
export { DELETE, GET, PATCH, POST } from "@digitalvibes/website-feedback/next";Run the migration against your Postgres database:
for f in node_modules/@digitalvibes/website-feedback/migrations/*.sql; do
psql "$DIBE_FEEDBACK_DATABASE_URL" -f "$f"
doneUse In Another Next.js Site
- Install the package:
pnpm add @digitalvibes/website-feedback pg- Add environment variables to the target site:
NEXT_PUBLIC_DIBE_FEEDBACK_ENABLED=true
NEXT_PUBLIC_DIBE_FEEDBACK_SITE_ID=your-site-slug
DIBE_FEEDBACK_DATABASE_URL=postgres://user:password@host:5432/db- Add the Next config wrapper:
// next.config.ts
import type { NextConfig } from "next";
import { withDibeFeedback } from "@digitalvibes/website-feedback/next-config";
const nextConfig: NextConfig = {};
export default withDibeFeedback(nextConfig);When feedback env vars are missing, this aliases @digitalvibes/website-feedback/client to a tiny noop module so the real overlay, styles, and icons are not built into the page bundle.
- Add the provider to
app/layout.tsx:
import type { ReactNode } from "react";
import { WebsiteFeedbackProvider } from "@digitalvibes/website-feedback/client";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<WebsiteFeedbackProvider>{children}</WebsiteFeedbackProvider>
</body>
</html>
);
}- Add the route handler at
app/api/dibe-feedback/route.ts:
export const runtime = "nodejs";
export { DELETE, GET, PATCH, POST } from "@digitalvibes/website-feedback/next";- Apply the migration once for the shared database:
for f in node_modules/@digitalvibes/website-feedback/migrations/*.sql; do
psql "$DIBE_FEEDBACK_DATABASE_URL" -f "$f"
done- Restart the app. The bottom-right bug appears only when
NEXT_PUBLIC_DIBE_FEEDBACK_ENABLED=trueandNEXT_PUBLIC_DIBE_FEEDBACK_SITE_IDis set.
When those env vars are missing or disabled at build time, withDibeFeedback aliases the client import to a noop module. That keeps the real feedback UI out of normal page bundles.
Use the direct client import only when you explicitly want to control gating yourself:
"use client";
import { WebsiteFeedbackProvider } from "@digitalvibes/website-feedback/client";Server-Gated Mount
WebsiteFeedbackGate is a server component that checks the env vars first and only
then dynamically imports the client overlay. Use it instead of WebsiteFeedbackProvider
when you want the gating decision to happen on the server:
import type { ReactNode } from "react";
import { WebsiteFeedbackGate } from "@digitalvibes/website-feedback/next-provider";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<WebsiteFeedbackGate>{children}</WebsiteFeedbackGate>
</body>
</html>
);
}The dynamic import keeps the overlay out of the server bundle, and withDibeFeedback
still aliases it to the noop module when the env vars are missing.
Project Layout
src/
index.ts root barrel (provider, overlay, withDibeFeedback, gate, public types)
client.ts "use client" entry: React context + WebsiteFeedbackProvider
overlay/
overlay.ts FeedbackOverlay - launcher, menu, pin mode, composes the rest
composer.ts new-feedback form (selection / general / pin)
dashboard.ts fullscreen board with filters
card.ts one entry inside the dashboard
markers.ts on-page pins for open entries
css.ts all overlay styles (single injected <style>)
types.ts types shared across overlay modules
feedback-api.ts the only place that talks HTTP to the route handlers
server.ts createFeedbackRouteHandlers - GET/POST/PATCH/DELETE
db.ts Postgres adapter behind the FeedbackDatabase interface
validation.ts runtime payload parsing for the route handlers
config.ts env reading + client/server config resolution
i18n.ts en/de dictionaries and the translate() helper
types.ts shared domain types, single source of truth for stages/types
noop-client.ts zero-cost stand-in swapped in by withDibeFeedbackWhen adding a UI feature, put new HTTP calls in feedback-api.ts and new copy in
i18n.ts (both dictionaries) rather than inline. New stages or feedback types go in
types.ts first - the const arrays there drive both the TypeScript types and the
runtime guards in validation.ts.
Publish
Run checks first:
pnpm typecheck
pnpm test
pnpm build
npm pack --dry-runPublish:
npm login
pnpm publish --access publicFor a patch release:
pnpm version patch
pnpm publish --access publicThen install or update in another project:
pnpm add @digitalvibes/website-feedback@latest pgLocal Test App
This repo includes a standalone test app that uses the real package route handlers. Add DIBE_FEEDBACK_DATABASE_URL to examples/local-test-app/.env.local before running it.
cd examples/local-test-app
pnpm install
pnpm db:migrate
pnpm devOpen http://localhost:3017.
Try:
- click the bottom-right bug to open the dashboard
- click
Newto create page feedback - select text on the page, then click the small bug to create
change_textfeedback
Feedback Lifecycle
open -> in_progress -> applied -> approved
|
+--> "Needs work": back to open, denied_at setAn agent takes an entry to applied and stops there. The client then hits Approve
or Needs work in the dashboard. Only the client produces approved; sending work
back reopens the entry and stamps denied_at so the agent knows it is a rework.
dismissed is for feedback that will not be actioned.
Two separate text fields keep the conversation intact:
comment- the client's own words. Agents must never overwrite this.agent_response- the short answer written back when the work is done. Shown to the client in the dashboard, withagent_responded_atset automatically.
Migrations
Migrations ship inside the package and are safe to re-run:
| File | Adds |
| --- | --- |
| 001_create_feedback_entries.sql | The dibe_feedback_entries table. |
| 002_add_agent_response.sql | agent_response, agent_responded_at. |
| 003_add_approval.sql | The approved stage, plus denied_at. |
Apply all of them after upgrading:
for f in node_modules/@digitalvibes/website-feedback/migrations/*.sql; do
psql "$DIBE_FEEDBACK_DATABASE_URL" -f "$f"
doneReading an un-migrated database still works - missing columns come back as null.
AI Agent Feedback Loop
AI coding agents should read docs/AI_AGENTS.md before working from feedback entries.
Short version:
- Query feedback entries for the current
site_id. - Prefer
openentries unless the user asks otherwise. - Set an entry to
in_progressbefore editing. - Implement the requested website change.
- Verify the affected route.
- Set the entry to
appliedwhen the change is complete, ordismissedonly when the feedback is invalid or intentionally skipped. - Add a short note to the target repo docs explaining that this package is the source of the client-feedback loop.
