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
- Project Overview
- Features
- Technology Stack
- Getting Started
- Environment Variables
- Project Structure
- API Endpoints
- Widget Integration Guide
- Dashboard Overview
- Components & Reusability
- Database Schema
- Development Scripts
- Deployment
- Keywords & Topics
- Learning Resources
- Tips & Best Practices
- Troubleshooting
- License
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.
- π¨ 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
- π 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
- 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
- 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
- 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
- Node.js 18+ and npm/yarn/pnpm
- MongoDB database (local or cloud like MongoDB Atlas)
- Basic knowledge of React, Next.js, and TypeScript
- Clone the repository
git clone <repository-url>
cd feedback-widget- Install dependencies
npm install
# or
yarn install
# or
pnpm install- Set up environment variables
See Environment Variables section for details.
- Set up the database
# Generate Prisma Client
npx prisma generate
# (Optional) Push schema to database (for initial setup)
npx prisma db push- Build the widget
npm run build:widget- Start the development server
npm run dev- 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).
Create a .env file in the root directory with the following 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"- Sign up at MongoDB Atlas
- Create a new cluster (free tier available)
- Create a database user (username and password)
- Whitelist your IP address (or use
0.0.0.0/0for all IPs in development) - Click "Connect" β "Connect your application"
- Copy the connection string
- Replace
<password>with your database user password - 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"- Install MongoDB locally (Installation Guide)
- Start MongoDB service
- Use the connection string:
DATABASE_URL="mongodb://localhost:27017/feedback_widget_db"docker run -d -p 27017:27017 --name mongodb mongo:latestThen use:
DATABASE_URL="mongodb://localhost:27017/feedback_widget_db"Generate a random secret key for NextAuth.js:
openssl rand -base64 32Or use any secure random string generator. This secret is used to encrypt JWT tokens.
If you want to enable Google sign-in:
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable Google+ API
- Go to "Credentials" β "Create Credentials" β "OAuth 2.0 Client ID"
- Configure consent screen (if not done)
- Create OAuth client ID for "Web application"
- Add authorized redirect URI:
http://localhost:3000/api/auth/callback/google(development) - Add authorized redirect URI:
https://your-domain.com/api/auth/callback/google(production) - Copy the Client ID and Client Secret
Brevo (Primary Provider):
- Go to Brevo (formerly Sendinblue)
- Sign up for a free account (300 emails/day free)
- Go to Settings β API Keys
- Generate a new API key and copy it
- Go to Settings β Senders & IP
- Add and verify your sender email address
- Add the following to your
.env:BREVO_API_KEY- Your Brevo API keyBREVO_SENDER_EMAIL- Verified sender emailBREVO_SENDER_NAME- Display name for emails (optional)BREVO_ADMIN_EMAIL- Email address to receive notifications
Resend (Fallback Provider - Optional):
- Go to Resend
- Sign up for a free account (100 emails/day free)
- Go to API Keys and create a new API key
- Verify your sender domain (optional, can use Gmail with limits)
- Add
RESEND_TOKENto 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.
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"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 fileCreate a new feedback entry. Automatically sends an email notification to the admin email when feedback is submitted.
Headers:
Content-Type: application/jsonX-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_EMAILwhen 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 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"
}
]Note: All project endpoints require authentication. Users can only access their own 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
}
}
]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 a specific project by ID (must belong to authenticated user).
Authentication: Required (JWT session)
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 a project (must belong to authenticated user).
Authentication: Required (JWT session)
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
}See the widget in action on a real website:
- Example Site: https://embedded-marketing.netlify.app/
- This demonstrates the widget integrated into a production website (Netlify deployment)
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>- Create a project in the dashboard at
/dashboard/projects/new - Copy the API key from the project details
- Use the API key in the
api-keyattribute:
<my-widget
api-base="https://embedded-feedback.vercel.app/api/feedback"
api-key="1e61d9ba70b084b5f8291f2aa75e67d9"
></my-widget>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>For local development, use:
<my-widget
api-base="http://localhost:3000/api/feedback"
api-key="your-api-key"
></my-widget>api-base(required): The API endpoint URL for submitting feedbackapi-key(optional): API key for project association (if not provided, uses default project)
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
After deploying or running locally:
- Sign up or sign in at the authentication page
- Access the dashboard at:
- Production: https://embedded-feedback.vercel.app/dashboard
- Local: http://localhost:3000/dashboard
Note: Unauthenticated users will be redirected to the sign-in page automatically.
- 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
- 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
- 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
- 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
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
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"
/>;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) => {}}
/>;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}
/>;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";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);
// ...
}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",
});
};
}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);
// ...
}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
}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[]
}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])
}To modify the schema:
- Edit
prisma/schema.prisma - Run
npx prisma generateto regenerate Prisma Client - Run
npx prisma db pushto sync schema with database (development) - Or create a migration:
npx prisma migrate dev --name your-migration-name
# 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-
Push your code to GitHub
-
Import project in Vercel
- Go to vercel.com
- Click "Import Project"
- Select your repository
-
Configure environment variables
Add all required environment variables in Vercel project settings:
DATABASE_URL- MongoDB connection stringAUTH_SECRET- NextAuth secret keyNEXTAUTH_URL- Your production URLBREVO_API_KEY- Brevo API key (for email notifications)BREVO_SENDER_EMAIL- Verified sender emailBREVO_SENDER_NAME- Email sender display name (optional)BREVO_ADMIN_EMAIL- Email to receive notificationsRESEND_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.
-
Deploy
- Vercel will automatically build and deploy
- The widget bundle will be generated during build
-
Update widget URLs
- After deployment, update widget script URLs to your Vercel domain
- Example:
https://your-project.vercel.app/widget.umd.js
The build process includes:
- Prisma Client Generation:
npx prisma generate - Next.js Build:
next build - 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.
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
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
-
API Key Security: Keep your API keys secret. Never commit them to version control.
-
CORS Configuration: The API allows all origins (
*) for widget embedding. For production, consider restricting to specific domains. -
Database Indexes: The schema includes indexes on
projectIdandcreatedAtfor optimal query performance. -
Widget Bundle Size: The widget is built separately to minimize bundle size. Keep widget dependencies minimal.
-
Error Handling: All API routes include error handling. Check browser console and server logs for debugging.
-
Environment Variables: Use
.env.localfor local development (git-ignored) and.env.examplefor documentation.
- 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
- Verify
DATABASE_URLis correct - Check MongoDB connection (Atlas IP whitelist, credentials)
- Ensure Prisma Client is generated:
npx prisma generate - Try connecting with MongoDB Compass to test connection
- Clear
.nextdirectory:rm -rf .next - Clear
node_modules:rm -rf node_modules && npm install - Regenerate Prisma Client:
npx prisma generate - Check Node.js version (requires 18+)
This project is open source and available for learning and educational purposes.
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! π




