Skip to content

A modern, production-ready feedback collection widget system built with Next.js, React, TypeScript, Prisma, and MongoDB. This project provides an embeddable web component that can be integrated into any website, along with a comprehensive dashboard for managing projects, viewing feedback, and analyzing insights.

Notifications You must be signed in to change notification settings

arnobt78/Embedded-Feedback-Collection-Widget--NextJS-FullStack

Repository files navigation

Embedded Feedback Collection System - Next.js, MongoDB FullStack Project

A modern, production-ready feedback collection widget system built with Next.js, React, TypeScript, Prisma, and MongoDB. This project provides an embeddable web component that can be integrated into any website, along with a comprehensive dashboard for managing projects, viewing feedback, and analyzing insights.

Live-Demo Dashboard: https://embedded-feedback.vercel.app/dashboard

Live Example (Widget Integration): https://embedded-marketing.netlify.app/ and its GitHUb Repository: Embedded Marketing

Screenshot 2026-01-02 at 15 33 55 Screenshot 2026-01-03 at 13 37 36 Screenshot 2026-01-03 at 13 37 51 Screenshot 2026-01-02 at 15 35 12 Screenshot 2026-01-02 at 15 35 50

πŸ“‹ Table of Contents

  1. Project Overview
  2. Features
  3. Technology Stack
  4. Getting Started
  5. Environment Variables
  6. Project Structure
  7. API Endpoints
  8. Widget Integration Guide
  9. Dashboard Overview
  10. Components & Reusability
  11. Database Schema
  12. Development Scripts
  13. Deployment
  14. Keywords & Topics
  15. Learning Resources
  16. Tips & Best Practices
  17. Troubleshooting
  18. License

πŸ“– Project Overview

This is a full-stack feedback collection system that allows you to:

  • Embed a feedback widget into any website using a simple HTML tag
  • Manage multiple projects with unique API keys for each project
  • Collect user feedback including messages, ratings, and contact information
  • View and analyze feedback through a comprehensive dashboard
  • Export data in CSV format for further analysis
  • Monitor analytics with charts and statistics

The widget is built as a Web Component using Shadow DOM for style isolation, making it safe to embed in any website without CSS conflicts. The dashboard is a Next.js application with a modern, responsive UI built with Tailwind CSS and shadcn/ui components.


✨ Features

Widget Features

  • 🎨 Beautiful UI: Modern, accessible feedback form with star ratings
  • πŸ”’ Style Isolation: Shadow DOM prevents CSS conflicts with host websites
  • ⚑ Lightweight: Optimized bundle size for fast loading
  • 🌐 Cross-Origin Support: CORS-enabled for embedding on any domain
  • πŸ”‘ API Key Authentication: Associate feedback with specific projects
  • πŸ“± Responsive Design: Works seamlessly on desktop and mobile devices
  • ✨ Real-time Validation: Instant form validation and error handling

Dashboard Features

  • πŸ” Authentication System: Secure user authentication with email/password and Google OAuth
  • πŸ‘€ User Accounts: Individual user accounts with complete data isolation
  • πŸ“Š Overview Dashboard: Key statistics and metrics at a glance
  • πŸ“ Feedback Management: View, filter, sort, and search all feedback entries
  • πŸ—‚οΈ Project Management: Create, edit, and manage multiple projects
  • πŸ“ˆ Business Insights: Visual analytics with charts and graphs
  • πŸ”‘ API Key Management: Generate, copy, and regenerate API keys
  • πŸ“€ CSV Export: Export feedback data for external analysis
  • πŸ“§ Email Notifications: Automatic email notifications when new feedback is submitted
  • 🎨 Dark Mode: Beautiful dark theme support
  • πŸ“± Fully Responsive: Mobile-first design that works on all screen sizes

πŸ› οΈ Technology Stack

Frontend

  • Next.js 15 - React framework with App Router
  • React 18 - UI library with concurrent features
  • TypeScript - Type-safe JavaScript
  • Tailwind CSS - Utility-first CSS framework
  • shadcn/ui - High-quality React component library
  • Radix UI - Unstyled, accessible component primitives
  • React Hook Form - Performant forms with validation
  • Zod - Schema validation library
  • TanStack React Query - Server state management
  • TanStack React Table - Powerful table component
  • Recharts - Composable charting library
  • Sonner - Toast notification library
  • date-fns - Date utility library
  • Lucide React - Beautiful icon library

Backend

  • Next.js API Routes - Serverless API endpoints
  • Prisma ORM - Type-safe database client
  • MongoDB - NoSQL document database
  • NextAuth.js v5 - Authentication library with JWT sessions
  • bcryptjs - Password hashing for secure authentication
  • Brevo (Sendinblue) - Email service provider for notifications (primary)
  • Resend - Fallback email service provider

Build Tools

  • Vite - Fast build tool for widget bundle
  • Turbopack - Next.js bundler (development)
  • TypeScript Compiler - Type checking and compilation
  • Tailwind CSS CLI - CSS processing and minification

πŸš€ Getting Started

Prerequisites

  • Node.js 18+ and npm/yarn/pnpm
  • MongoDB database (local or cloud like MongoDB Atlas)
  • Basic knowledge of React, Next.js, and TypeScript

Installation

  1. Clone the repository
git clone <repository-url>
cd feedback-widget
  1. Install dependencies
npm install
# or
yarn install
# or
pnpm install
  1. Set up environment variables

See Environment Variables section for details.

  1. Set up the database
# Generate Prisma Client
npx prisma generate

# (Optional) Push schema to database (for initial setup)
npx prisma db push
  1. Build the widget
npm run build:widget
  1. Start the development server
npm run dev
  1. Open your browser

Visit http://localhost:3000 - you'll be redirected to the sign-in page.

Visit http://localhost:3000/auth/signin to sign in or create an account.

Visit http://localhost:3000/dashboard to access the dashboard (requires authentication).


πŸ” Environment Variables

Create a .env file in the root directory with the following variables:

Required Variables

# MongoDB Database Connection URL
# Format for MongoDB Atlas (cloud):
DATABASE_URL="mongodb+srv://<username>:<password>@<cluster-url>/<dbname>?retryWrites=true&w=majority&appName=<dbname>"

# Format for local MongoDB:
DATABASE_URL="mongodb://localhost:27017/feedback_widget_db"

# Format for MongoDB with authentication:
DATABASE_URL="mongodb://<username>:<password>@<host>:<port>/<dbname>?authSource=<auth-db>"

# NextAuth.js Configuration
# Generate a random secret: openssl rand -base64 32
AUTH_SECRET="your-random-secret-key-here"
NEXTAUTH_URL="http://localhost:3000"  # For local development
# For production: NEXTAUTH_URL="https://your-domain.com"

# Google OAuth (Optional - for Google sign-in)
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"

# Email Service Configuration (Brevo + Resend)
BREVO_API_KEY="your-brevo-api-key"
BREVO_SENDER_EMAIL="your-email@gmail.com"
BREVO_SENDER_NAME="Feedback Widget"
BREVO_ADMIN_EMAIL="your-email@gmail.com"

# Resend API (Fallback - Optional)
RESEND_TOKEN="your-resend-api-key"

Getting Your MongoDB Connection String

Option 1: MongoDB Atlas (Cloud - Recommended)

  1. Sign up at MongoDB Atlas
  2. Create a new cluster (free tier available)
  3. Create a database user (username and password)
  4. Whitelist your IP address (or use 0.0.0.0/0 for all IPs in development)
  5. Click "Connect" β†’ "Connect your application"
  6. Copy the connection string
  7. Replace <password> with your database user password
  8. Replace <dbname> with your database name

Example:

DATABASE_URL="mongodb+srv://myuser:mypassword@cluster0.xxxxx.mongodb.net/feedback_widget_db?retryWrites=true&w=majority&appName=feedback_widget"

Option 2: Local MongoDB

  1. Install MongoDB locally (Installation Guide)
  2. Start MongoDB service
  3. Use the connection string:
DATABASE_URL="mongodb://localhost:27017/feedback_widget_db"

Option 3: Docker MongoDB

docker run -d -p 27017:27017 --name mongodb mongo:latest

Then use:

DATABASE_URL="mongodb://localhost:27017/feedback_widget_db"

Getting Your Authentication Secrets

AUTH_SECRET

Generate a random secret key for NextAuth.js:

openssl rand -base64 32

Or use any secure random string generator. This secret is used to encrypt JWT tokens.

Google OAuth Credentials (Optional)

If you want to enable Google sign-in:

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one
  3. Enable Google+ API
  4. Go to "Credentials" β†’ "Create Credentials" β†’ "OAuth 2.0 Client ID"
  5. Configure consent screen (if not done)
  6. Create OAuth client ID for "Web application"
  7. Add authorized redirect URI: http://localhost:3000/api/auth/callback/google (development)
  8. Add authorized redirect URI: https://your-domain.com/api/auth/callback/google (production)
  9. Copy the Client ID and Client Secret

Email Service Configuration (Brevo + Resend)

Brevo (Primary Provider):

  1. Go to Brevo (formerly Sendinblue)
  2. Sign up for a free account (300 emails/day free)
  3. Go to Settings β†’ API Keys
  4. Generate a new API key and copy it
  5. Go to Settings β†’ Senders & IP
  6. Add and verify your sender email address
  7. Add the following to your .env:
    • BREVO_API_KEY - Your Brevo API key
    • BREVO_SENDER_EMAIL - Verified sender email
    • BREVO_SENDER_NAME - Display name for emails (optional)
    • BREVO_ADMIN_EMAIL - Email address to receive notifications

Resend (Fallback Provider - Optional):

  1. Go to Resend
  2. Sign up for a free account (100 emails/day free)
  3. Go to API Keys and create a new API key
  4. Verify your sender domain (optional, can use Gmail with limits)
  5. Add RESEND_TOKEN to your .env

Note: Emails are sent automatically when feedback is submitted. You'll receive notifications at BREVO_ADMIN_EMAIL. Brevo is used as the primary provider, with Resend as automatic fallback if Brevo fails.

Example .env File

See .env.example in the repository for a template:

# Environment variables for feedback-widget
# Replace <username>, <password>, <cluster-url>, <dbname> with your MongoDB details

DATABASE_URL="mongodb+srv://<username>:<password>@<cluster-url>/<dbname>?retryWrites=true&w=majority&appName=<dbname>"

# NextAuth Configuration
AUTH_SECRET="your-random-secret-key-here"
NEXTAUTH_URL="http://localhost:3000"

# Google OAuth (Optional)
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"

# Email Service Configuration (Brevo + Resend)
BREVO_API_KEY="your-brevo-api-key"
BREVO_SENDER_EMAIL="your-email@gmail.com"
BREVO_SENDER_NAME="Feedback Widget"
BREVO_ADMIN_EMAIL="your-email@gmail.com"

# Resend API (Fallback - Optional)
RESEND_TOKEN="your-resend-api-key"

πŸ“ Project Structure

feedback-widget/
β”œβ”€β”€ prisma/
β”‚   └── schema.prisma          # Database schema definition
β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ widget.umd.js          # Built widget bundle (generated)
β”‚   β”œβ”€β”€ widget-styles.css      # Widget CSS (generated)
β”‚   └── test-widget.html       # Example HTML for testing widget
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ build-widget-css.js    # CSS build script
β”‚   β”œβ”€β”€ inject-css-inline.js   # CSS injection script
β”‚   └── migrate-to-projects.ts # Migration script
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                   # Next.js App Router pages
β”‚   β”‚   β”œβ”€β”€ api/               # API routes
β”‚   β”‚   β”‚   β”œβ”€β”€ feedback/
β”‚   β”‚   β”‚   β”‚   └── route.ts   # Feedback CRUD API
β”‚   β”‚   β”‚   β”œβ”€β”€ projects/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ route.ts   # Projects list/create API
β”‚   β”‚   β”‚   β”‚   └── [id]/
β”‚   β”‚   β”‚   β”‚       └── route.ts # Project update/delete API
β”‚   β”‚   β”‚   └── business-insights/
β”‚   β”‚   β”‚       └── route.ts   # Analytics API
β”‚   β”‚   β”œβ”€β”€ dashboard/         # Dashboard pages
β”‚   β”‚   β”‚   β”œβ”€β”€ page.tsx       # Overview dashboard
β”‚   β”‚   β”‚   β”œβ”€β”€ feedback/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ page.tsx   # Feedback list page
β”‚   β”‚   β”‚   β”‚   └── [id]/
β”‚   β”‚   β”‚   β”‚       └── page.tsx # Feedback detail page
β”‚   β”‚   β”‚   β”œβ”€β”€ projects/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ page.tsx   # Projects list page
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ new/
β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx # Create project page
β”‚   β”‚   β”‚   β”‚   └── [id]/
β”‚   β”‚   β”‚   β”‚       └── page.tsx # Edit project page
β”‚   β”‚   β”‚   └── business-insights/
β”‚   β”‚   β”‚       └── page.tsx   # Analytics page
β”‚   β”‚   β”œβ”€β”€ layout.tsx         # Root layout
β”‚   β”‚   └── page.tsx           # Homepage
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ Widget.tsx         # Main feedback widget component
β”‚   β”‚   β”œβ”€β”€ auth/              # Authentication components
β”‚   β”‚   β”‚   └── auth-form.tsx  # Reusable auth form component
β”‚   β”‚   β”œβ”€β”€ dashboard/         # Dashboard components
β”‚   β”‚   β”‚   β”œβ”€β”€ dashboard-layout.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ sidebar.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ header.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ stat-card.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ feedback-table.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ feedback-table-filters.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ project-form.tsx
β”‚   β”‚   β”‚   └── chart-container.tsx
β”‚   β”‚   β”œβ”€β”€ ui/                # shadcn/ui components
β”‚   β”‚   β”‚   β”œβ”€β”€ button.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ card.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ input.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ textarea.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ table.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ dialog.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ alert-dialog.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ dropdown-menu.tsx
β”‚   β”‚   β”‚   └── ...
β”‚   β”‚   └── providers/
β”‚   β”‚       β”œβ”€β”€ query-provider.tsx
β”‚   β”‚       └── theme-provider.tsx
β”‚   β”œβ”€β”€ hooks/                 # Custom React hooks
β”‚   β”‚   β”œβ”€β”€ use-feedback.ts    # Feedback data fetching
β”‚   β”‚   β”œβ”€β”€ use-projects.ts    # Projects data fetching
β”‚   β”‚   └── use-analytics.ts   # Analytics data fetching
β”‚   β”œβ”€β”€ lib/                   # Utility functions
β”‚   β”‚   β”œβ”€β”€ prisma.ts          # Prisma client singleton
β”‚   β”‚   β”œβ”€β”€ auth.ts            # NextAuth configuration and exports
β”‚   β”‚   β”œβ”€β”€ email.ts           # Email service with Brevo and Resend fallback
β”‚   β”‚   β”œβ”€β”€ api-utils.ts       # API helper functions
β”‚   β”‚   β”œβ”€β”€ export-utils.ts    # CSV export utilities
β”‚   β”‚   β”œβ”€β”€ query-client.ts    # React Query client
β”‚   β”‚   └── utils.ts           # General utilities
β”‚   β”œβ”€β”€ types/
β”‚   β”‚   └── index.ts           # TypeScript type definitions
β”‚   β”œβ”€β”€ web-component.tsx      # Web Component wrapper
β”‚   β”œβ”€β”€ widget-styles.ts       # Widget styles export
β”‚   └── globals.css            # Global styles
β”œβ”€β”€ .env.example               # Environment variables template
β”œβ”€β”€ middleware.ts              # Next.js middleware (route protection)
β”œβ”€β”€ next.config.ts             # Next.js configuration
β”œβ”€β”€ tailwind.config.js         # Tailwind CSS configuration
β”œβ”€β”€ vite.config.widget.js      # Vite config for widget build
β”œβ”€β”€ package.json               # Dependencies and scripts
└── README.md                  # This file

πŸ”Œ API Endpoints

Feedback API

POST /api/feedback

Create a new feedback entry. Automatically sends an email notification to the admin email when feedback is submitted.

Headers:

  • Content-Type: application/json
  • X-API-Key: <your-api-key> (optional, for project association)

Request Body:

{
  "name": "John Doe",
  "email": "john@example.com",
  "message": "Great product!",
  "rating": 5
}

Response: 201 Created

{
  "id": "...",
  "name": "John Doe",
  "email": "john@example.com",
  "message": "Great product!",
  "rating": 5,
  "projectId": "...",
  "createdAt": "2024-01-01T00:00:00.000Z"
}

Email Notification:

  • Automatically sends a professional HTML email to BREVO_ADMIN_EMAIL when feedback is submitted
  • Email includes: project name, domain, rating, submitter info, feedback message, and dashboard link
  • Subject line includes timestamp and random number to avoid spam filters
  • Uses Brevo as primary provider, falls back to Resend if Brevo fails
  • Email sending is asynchronous and does not block the API response

GET /api/feedback

Get all feedback entries for authenticated user's projects (optionally filtered by project).

Authentication: Required (JWT session)

Query Parameters:

  • projectId (optional): Filter by project ID

Response: 200 OK

[
  {
    "id": "...",
    "name": "John Doe",
    "email": "john@example.com",
    "message": "Great product!",
    "rating": 5,
    "projectId": "...",
    "project": {
      "id": "...",
      "name": "My Project",
      "domain": "https://example.com"
    },
    "createdAt": "2024-01-01T00:00:00.000Z"
  }
]

Projects API

Note: All project endpoints require authentication. Users can only access their own projects.

GET /api/projects

Get all projects for the authenticated user.

Authentication: Required (JWT session)

Response: 200 OK

[
  {
    "id": "...",
    "name": "My Project",
    "domain": "https://example.com",
    "apiKey": "...",
    "description": "Project description",
    "isActive": true,
    "createdAt": "2024-01-01T00:00:00.000Z",
    "updatedAt": "2024-01-01T00:00:00.000Z",
    "_count": {
      "feedbacks": 10
    }
  }
]

POST /api/projects

Create a new project (associated with authenticated user).

Authentication: Required (JWT session)

Request Body:

{
  "name": "My Project",
  "domain": "https://example.com",
  "description": "Project description"
}

Response: 201 Created

{
  "id": "...",
  "name": "My Project",
  "domain": "https://example.com",
  "apiKey": "generated-api-key",
  "description": "Project description",
  "isActive": true,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z"
}

GET /api/projects/[id]

Get a specific project by ID (must belong to authenticated user).

Authentication: Required (JWT session)

PUT /api/projects/[id]

Update a project (must belong to authenticated user).

Authentication: Required (JWT session)

Request Body:

{
  "name": "Updated Name",
  "domain": "https://updated.com",
  "description": "Updated description",
  "isActive": true,
  "regenerateApiKey": false
}

DELETE /api/projects/[id]

Delete a project (must belong to authenticated user).

Authentication: Required (JWT session)

Business Insights API

GET /api/business-insights

Get analytics data for authenticated user's projects.

Authentication: Required (JWT session)

Query Parameters:

  • projectId (optional): Filter by project ID

Response: 200 OK

{
  "totalFeedback": 100,
  "averageRating": 4.5,
  "ratedFeedbackCount": 80,
  "ratingDistribution": [
    { "rating": 1, "count": 5 },
    { "rating": 2, "count": 10 },
    { "rating": 3, "count": 15 },
    { "rating": 4, "count": 30 },
    { "rating": 5, "count": 40 }
  ],
  "feedbackByProject": [
    {
      "projectId": "...",
      "projectName": "My Project",
      "count": 50
    }
  ],
  "recent7Days": 20,
  "recent30Days": 60,
  "totalProjects": 5
}

πŸ”§ Widget Integration Guide

Live Example

See the widget in action on a real website:

Basic Integration

Add the widget to any HTML page with just a few lines:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Website</title>
  </head>
  <body>
    <h1>Welcome to My Website</h1>

    <!-- Load React and ReactDOM UMD builds (required for widget) -->
    <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

    <!-- Load the widget script from your deployment -->
    <script src="https://embedded-feedback.vercel.app/widget.umd.js"></script>

    <!-- Embed the widget -->
    <my-widget
      api-base="https://embedded-feedback.vercel.app/api/feedback"
      api-key="your-api-key-here"
    ></my-widget>
  </body>
</html>

Integration with Project API Key

  1. Create a project in the dashboard at /dashboard/projects/new
  2. Copy the API key from the project details
  3. Use the API key in the api-key attribute:
<my-widget
  api-base="https://embedded-feedback.vercel.app/api/feedback"
  api-key="1e61d9ba70b084b5f8291f2aa75e67d9"
></my-widget>

Integration in React/Vue/Angular

The widget works in any framework! Just include the script tags and use the <my-widget> tag:

React Example:

function App() {
  return (
    <div>
      <h1>My React App</h1>
      <my-widget
        api-base="https://embedded-feedback.vercel.app/api/feedback"
        api-key="your-api-key"
      />
    </div>
  );
}

Vue Example:

<template>
  <div>
    <h1>My Vue App</h1>
    <my-widget
      api-base="https://embedded-feedback.vercel.app/api/feedback"
      api-key="your-api-key"
    />
  </div>
</template>

Local Development

For local development, use:

<my-widget
  api-base="http://localhost:3000/api/feedback"
  api-key="your-api-key"
></my-widget>

Widget Attributes

  • api-base (required): The API endpoint URL for submitting feedback
  • api-key (optional): API key for project association (if not provided, uses default project)

πŸ“Š Dashboard Overview

Authentication

The dashboard requires user authentication. You can:

  • Sign up with email and password at /auth/signup
  • Sign in with email and password at /auth/signin
  • Sign in with Google (if Google OAuth is configured)
  • Each user has their own isolated projects and feedback data

Accessing the Dashboard

After deploying or running locally:

  1. Sign up or sign in at the authentication page
  2. Access the dashboard at:

Note: Unauthenticated users will be redirected to the sign-in page automatically.

Dashboard Pages

1. Overview (/dashboard)

  • Total feedback count
  • Active projects count
  • Average rating
  • Recent feedback (last 7 days)
  • Additional statistics (last 30 days, high ratings, satisfaction rate)
  • Quick action cards

2. Feedback (/dashboard/feedback)

  • Table view of all feedback entries
  • Filter by project and rating
  • Search functionality
  • Sort by date, rating, project
  • Pagination
  • CSV export
  • Column visibility toggle
  • Detail view for each feedback entry

3. Projects (/dashboard/projects)

  • List of all projects
  • Create new project
  • Edit project details
  • Delete project
  • View API keys
  • Copy API keys
  • Project status (active/inactive)
  • Feedback count per project

4. Business Insights (/dashboard/business-insights)

  • Rating distribution charts (Bar and Area)
  • Feedback by project (Pie and Bar charts)
  • Time-based statistics
  • Interactive tooltips
  • Responsive charts with horizontal scrolling on mobile

🧩 Components & Reusability

Widget Component

Location: src/components/Widget.tsx

The main feedback widget component that can be used directly in React applications.

import Widget from "@/components/Widget";

function MyPage() {
  return (
    <Widget
      apiBase="https://embedded-feedback.vercel.app/api/feedback"
      apiKey="your-api-key"
    />
  );
}

Props:

  • apiBase?: string - API endpoint URL (default: "/api/feedback")
  • apiKey?: string - API key for project association

Dashboard Components

StatCard

Location: src/components/dashboard/stat-card.tsx

Displays a statistic with icon, value, description, and optional loading state.

import { StatCard } from "@/components/dashboard/stat-card";
import { MessageSquare } from "lucide-react";

<StatCard
  title="Total Feedback"
  value={100}
  description="All time feedback submissions"
  icon={MessageSquare}
  isLoading={false}
  colorVariant="sky"
/>;

FeedbackTable

Location: src/components/dashboard/feedback-table.tsx

Complete feedback table with filtering, sorting, pagination, and export.

import { FeedbackTable } from "@/components/dashboard/feedback-table";

<FeedbackTable
  data={feedbackData}
  isLoading={false}
  projects={projectsData}
  onProjectFilter={(projectId) => {}}
  onRatingFilter={(rating) => {}}
/>;

ProjectForm

Location: src/components/dashboard/project-form.tsx

Form component for creating/editing projects with validation.

import { ProjectForm } from "@/components/dashboard/project-form";

<ProjectForm
  defaultValues={projectData}
  onSubmit={handleSubmit}
  onCancel={handleCancel}
/>;

UI Components

All UI components are from shadcn/ui and can be imported and used directly:

import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";

Custom Hooks

useFeedback

Location: src/hooks/use-feedback.ts

React Query hook for fetching feedback data.

import { useFeedback } from "@/hooks/use-feedback";

function MyComponent() {
  const { data, isLoading, error } = useFeedback(projectId);
  // ...
}

useProjects

Location: src/hooks/use-projects.ts

React Query hooks for project management.

import {
  useProjects,
  useCreateProject,
  useUpdateProject,
} from "@/hooks/use-projects";

function MyComponent() {
  const { data: projects } = useProjects();
  const createProject = useCreateProject();

  const handleCreate = async () => {
    await createProject.mutateAsync({
      name: "New Project",
      domain: "https://example.com",
      description: "Description",
    });
  };
}

useAnalytics

Location: src/hooks/use-analytics.ts

React Query hook for fetching analytics data.

import { useAnalytics } from "@/hooks/use-analytics";

function MyComponent() {
  const { data: analytics, isLoading } = useAnalytics(projectId);
  // ...
}

πŸ—„οΈ Database Schema

User Model (NextAuth)

model User {
  id            String    @id @default(auto()) @map("_id") @db.ObjectId
  name          String?
  email         String    @unique
  emailVerified DateTime?
  password      String?   // Hashed password (for email/password auth)
  image         String?   // Profile image URL
  accounts      Account[] // OAuth accounts
  sessions      Session[] // Active sessions
  projects      Project[] // User's projects
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
}

Project Model

model Project {
  id          String     @id @default(auto()) @map("_id") @db.ObjectId
  userId      String     @db.ObjectId // User who owns this project
  user        User       @relation(fields: [userId], references: [id])
  name        String
  domain      String
  apiKey      String     @unique
  description String?
  isActive    Boolean    @default(true)
  createdAt   DateTime   @default(now())
  updatedAt   DateTime   @updatedAt
  feedbacks   Feedback[]
}

Feedback Model

model Feedback {
  id        String    @id @default(auto()) @map("_id") @db.ObjectId
  projectId String?   @db.ObjectId
  project   Project?  @relation(fields: [projectId], references: [id])
  name      String?
  email     String?
  message   String
  rating    Int?
  metadata  Json?
  createdAt DateTime  @default(now())

  @@index([projectId])
  @@index([createdAt])
}

Schema Modifications

To modify the schema:

  1. Edit prisma/schema.prisma
  2. Run npx prisma generate to regenerate Prisma Client
  3. Run npx prisma db push to sync schema with database (development)
  4. Or create a migration: npx prisma migrate dev --name your-migration-name

πŸ“œ Development Scripts

# Start development server
npm run dev

# Build for production
npm run build

# Start production server
npm start

# Lint code
npm run lint

# Build widget only
npm run build:widget

# Build widget CSS only
npm run build:widget-css

# Generate Prisma Client
npx prisma generate

# Push schema to database (development)
npx prisma db push

# Create migration
npx prisma migrate dev

# Open Prisma Studio (database GUI)
npx prisma studio

πŸš€ Deployment

Deploy to Vercel (Recommended)

  1. Push your code to GitHub

  2. Import project in Vercel

    • Go to vercel.com
    • Click "Import Project"
    • Select your repository
  3. Configure environment variables

    Add all required environment variables in Vercel project settings:

    • DATABASE_URL - MongoDB connection string
    • AUTH_SECRET - NextAuth secret key
    • NEXTAUTH_URL - Your production URL
    • BREVO_API_KEY - Brevo API key (for email notifications)
    • BREVO_SENDER_EMAIL - Verified sender email
    • BREVO_SENDER_NAME - Email sender display name (optional)
    • BREVO_ADMIN_EMAIL - Email to receive notifications
    • RESEND_TOKEN - Resend API key (optional, fallback)
    • GOOGLE_CLIENT_ID - Google OAuth client ID (optional)
    • GOOGLE_CLIENT_SECRET - Google OAuth client secret (optional)

    Go to Settings β†’ Environment Variables β†’ Add New and add each variable.

  4. Deploy

    • Vercel will automatically build and deploy
    • The widget bundle will be generated during build
  5. Update widget URLs

    • After deployment, update widget script URLs to your Vercel domain
    • Example: https://your-project.vercel.app/widget.umd.js

Build Process

The build process includes:

  1. Prisma Client Generation: npx prisma generate
  2. Next.js Build: next build
  3. Widget Build: Builds the widget bundle with Vite

The widget bundle (widget.umd.js) and styles (widget-styles.css) are output to the public/ directory and served as static files.


🏷️ Keywords & Topics

feedback widget, embedded feedback, web component, shadow dom, nextjs, react, typescript, prisma, mongodb, dashboard, analytics, api, vercel, tailwindcss, shadcn ui, react query, tanstack table, recharts, feedback collection, customer feedback, user feedback, feedback management, project management, api key authentication, cors, cross-origin, embeddable widget, feedback form, star rating, csv export, business insights, data visualization, responsive design, dark mode, fullstack, full-stack, teaching, learning, example project, production-ready, modern web development


πŸŽ“ Learning Resources

This project demonstrates:

  • Web Components: Creating custom HTML elements with Shadow DOM
  • Next.js App Router: Modern Next.js routing and API routes
  • React Patterns: Custom hooks, component composition, state management
  • TypeScript: Type-safe development with interfaces and types
  • Prisma ORM: Type-safe database queries and schema management
  • API Design: RESTful APIs with CORS support
  • Dashboard Development: Building admin interfaces with tables, charts, and filters
  • Responsive Design: Mobile-first approach with Tailwind CSS
  • Build Optimization: Separate widget bundle for performance
  • Modern Tooling: Vite, Turbopack, and modern build pipelines

πŸ’‘ Tips & Best Practices

  1. API Key Security: Keep your API keys secret. Never commit them to version control.

  2. CORS Configuration: The API allows all origins (*) for widget embedding. For production, consider restricting to specific domains.

  3. Database Indexes: The schema includes indexes on projectId and createdAt for optimal query performance.

  4. Widget Bundle Size: The widget is built separately to minimize bundle size. Keep widget dependencies minimal.

  5. Error Handling: All API routes include error handling. Check browser console and server logs for debugging.

  6. Environment Variables: Use .env.local for local development (git-ignored) and .env.example for documentation.


πŸ› Troubleshooting

Widget not appearing

  • Check browser console for errors
  • Ensure React and ReactDOM scripts are loaded before widget script
  • Verify the widget script URL is correct
  • Check CORS headers in network tab

Database connection errors

  • Verify DATABASE_URL is correct
  • Check MongoDB connection (Atlas IP whitelist, credentials)
  • Ensure Prisma Client is generated: npx prisma generate
  • Try connecting with MongoDB Compass to test connection

Build errors

  • Clear .next directory: rm -rf .next
  • Clear node_modules: rm -rf node_modules && npm install
  • Regenerate Prisma Client: npx prisma generate
  • Check Node.js version (requires 18+)

πŸ“ License

This project is open source and available for learning and educational purposes.


Happy Coding

Feel free to use this project repository and extend this project further!

If you have any questions or want to share your work, reach out via GitHub or my portfolio at https://arnob-mahmud.vercel.app/.

Enjoy building and learning! πŸš€

Thank you! 😊


About

A modern, production-ready feedback collection widget system built with Next.js, React, TypeScript, Prisma, and MongoDB. This project provides an embeddable web component that can be integrated into any website, along with a comprehensive dashboard for managing projects, viewing feedback, and analyzing insights.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published