- Project Overview
- Live Demo & Integration
- Features
- Technology Stack
- Project Structure
- Prerequisites
- Installation Guide
- Environment Variables Setup
- Database Setup
- Running the Project
- Project Walkthrough
- Components Documentation
- API Routes & Endpoints
- Widget Integration Guide
- Reusing Components in Other Projects
- Development & Customization
- Building for Production
- Deployment
- Keywords & Topics
- Learn More
- About
- Conclusion
Embedded Feedback Widget is a modern, production-ready, full-stack feedback collection system built with Next.js. This project demonstrates best practices for building reusable, embeddable web widgets that can be integrated into any website or web application.
- Collects User Feedback: Allows users to submit feedback with name, email, message, and a 1-5 star rating
- Database Storage: Stores feedback entries in MongoDB using Prisma ORM
- Widget Embedding: Can be embedded in any HTML page as a standalone web component
- API Integration: Provides RESTful API endpoints for creating and retrieving feedback
- Modern UI: Built with Radix UI primitives and Tailwind CSS for a beautiful, accessible interface
This project is designed as a comprehensive learning resource covering:
- Next.js App Router architecture
- React Server and Client Components
- Web Components and Shadow DOM
- API Route handlers
- Database integration with Prisma
- Modern JavaScript/TypeScript patterns
- Component reusability and modularity
- Build tooling and bundling strategies
- Live Widget: https://embedded-feedback.vercel.app/
- Integrated Example: https://embedded-marketing.netlify.app/
- Integration Repository: Embedded-Widget-Marketing-Interactive-Landing--React-Frontend
- π Feedback Collection Form: User-friendly form with name, email, message fields, and interactive star rating
- β Star Rating System: Interactive 5-star rating component with visual feedback
- πΎ Database Persistence: All feedback is stored in MongoDB with timestamps
- π RESTful API: Clean API endpoints for creating and retrieving feedback
- π CORS Support: Cross-origin resource sharing enabled for widget embedding
- π¨ Modern UI Components: Built with Radix UI for accessibility and Tailwind CSS for styling
- π Type Safety: TypeScript support with gradual typing approach
- π¦ Web Component Support: Can be embedded as a custom HTML element (
<my-widget>) - π Production Ready: Optimized builds, error handling, and loading states
- π± Responsive Design: Works seamlessly on desktop and mobile devices
- βΏ Accessible: WCAG compliant components with keyboard navigation support
- π οΈ Hot Module Replacement: Fast development with Turbopack
- π Comprehensive Comments: Educational comments throughout codebase
- π ESLint Configuration: Code quality and consistency checks
- π Well Documented: Extensive documentation for learning and reference
- Next.js 15.3.8 - React framework with App Router, Server Components, and API Routes
- React 18.2.0 - UI library with hooks and functional components
- TypeScript 5 - Type-safe JavaScript with gradual typing
- Prisma 6.10.0 - Next-generation ORM for database access
- Tailwind CSS 3.4.4 - Utility-first CSS framework
- Radix UI - Unstyled, accessible UI primitives
@radix-ui/react-popover- Popover component@radix-ui/react-label- Accessible label component@radix-ui/react-separator- Visual separator@radix-ui/react-slot- Component composition utility
- Lucide React - Beautiful icon library
- class-variance-authority - Component variant management
- clsx & tailwind-merge - Class name utilities
- MongoDB - NoSQL document database (can also use PostgreSQL)
- Prisma Client - Type-safe database client
- Vite 6.3.5 - Fast build tool for widget bundling
- PostCSS - CSS processing
- ESLint - Code linting
- Turbopack - Next.js's fast bundler (development)
- Vercel - Recommended hosting platform (serverless functions, edge network)
Understanding the project structure is crucial for navigation and development:
feedback-widget-next/
βββ .env # Environment variables (not in git)
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore patterns
βββ components.json # shadcn/ui configuration
βββ eslint.config.mjs # ESLint configuration
βββ next.config.ts # Next.js configuration
βββ package.json # Dependencies and scripts
βββ package-lock.json # Dependency lock file
βββ postcss.config.js # PostCSS configuration
βββ tailwind.config.js # Tailwind CSS configuration
βββ tsconfig.json # TypeScript configuration
βββ vite.config.widget.js # Vite config for widget bundling
β
βββ prisma/
β βββ schema.prisma # Database schema definition
β
βββ public/
β βββ favicon.ico # Site favicon
β βββ widget.umd.js # Built widget bundle (generated)
β
βββ src/
βββ app/ # Next.js App Router directory
β βββ api/ # API routes
β β βββ feedback/
β β βββ route.js # Feedback API endpoints (GET, POST, OPTIONS)
β βββ favicon.ico # App favicon
β βββ globals.css # Global styles and CSS variables
β βββ layout.tsx # Root layout component (metadata, fonts)
β βββ page.jsx # Home page component
β βββ page.module.css # Page-specific styles
β
βββ components/ # React components
β βββ ui/ # Reusable UI components (shadcn/ui)
β β βββ button.jsx/tsx # Button component
β β βββ card.tsx # Card component
β β βββ input.jsx/tsx # Input field component
β β βββ label.jsx/tsx # Label component
β β βββ popover.jsx/tsx # Popover component
β β βββ separator.jsx # Separator component
β β βββ textarea.jsx/tsx # Textarea component
β βββ Widget.jsx # Main feedback widget component
β
βββ lib/ # Utility libraries
β βββ prisma.js # Prisma client singleton
β βββ utils.js # Utility functions (JavaScript)
β βββ utils.ts # Utility functions (TypeScript)
β
βββ web-component.jsx # Web Component wrapper for embeddingsrc/app/layout.tsx: Root layout that wraps all pages, contains SEO metadata and global fontssrc/app/page.jsx: Home page that displays the widgetsrc/app/api/feedback/route.js: API route handlers for feedback operationssrc/components/Widget.jsx: Main feedback widget component with form and state managementsrc/web-component.jsx: Web Component wrapper that enables embedding in any HTML pagesrc/lib/prisma.js: Prisma client singleton to prevent multiple database connectionsprisma/schema.prisma: Database schema definition for the Feedback modelvite.config.widget.js: Configuration for building the widget as a UMD bundle
Before you begin, ensure you have the following installed:
- Node.js 18.x or higher (Download)
- npm, yarn, pnpm, or bun package manager
- Git for version control
- MongoDB Atlas account (free tier available) or local MongoDB instance
- VS Code with extensions:
- ESLint
- Prettier
- Prisma
- Tailwind CSS IntelliSense
- MongoDB Compass for database visualization (optional)
- Basic understanding of JavaScript/TypeScript
- Familiarity with React concepts (hooks, components, props)
- Basic understanding of REST APIs
- Basic knowledge of Git
Follow these steps to set up the project on your local machine:
# Clone the repository
git clone <your-repo-url>
# Navigate to the project directory
cd feedback-widget-nextChoose your preferred package manager:
# Using npm
npm install
# Using yarn
yarn install
# Using pnpm
pnpm install
# Using bun
bun installThis will install all required dependencies listed in package.json.
Create a .env file in the root directory:
# Copy the example file
cp .env.example .env
# Or create manually
touch .envSee the Environment Variables Setup section for detailed instructions on configuring your .env file.
# Generate Prisma Client
npx prisma generate
# Push the schema to your database
npx prisma db pushSee the Database Setup section for more details.
# Using npm
npm run dev
# Using yarn
yarn dev
# Using pnpm
pnpm dev
# Using bun
bun devThe application will be available at http://localhost:3000.
Environment variables are crucial for configuring your application. They keep sensitive information like database credentials out of your codebase.
Create a .env file in the root directory of your project. This file should never be committed to Git (it's already in .gitignore).
This is the connection string for your MongoDB database.
Format for MongoDB Atlas (Cloud):
DATABASE_URL="mongodb+srv://<username>:<password>@<cluster-url>/<database-name>?retryWrites=true&w=majority"Getting Your MongoDB Atlas Connection String:
- Sign up at MongoDB Atlas (free tier available)
- Create a new cluster (choose free M0 tier)
- Create a database user:
- Go to "Database Access" β "Add New Database User"
- Choose "Password" authentication
- Save the username and password
- Whitelist your IP address:
- Go to "Network Access" β "Add IP Address"
- Add
0.0.0.0/0for development (allows all IPs) or your specific IP
- Get your connection string:
- Go to "Database" β "Connect" β "Connect your application"
- Copy the connection string
- Replace
<password>with your database user password - Replace
<dbname>with your database name (e.g., "feedback-widget")
Example .env file:
DATABASE_URL="mongodb+srv://myuser:mypassword123@cluster0.abc123.mongodb.net/feedback-widget?retryWrites=true&w=majority"Format for Local MongoDB:
DATABASE_URL="mongodb://localhost:27017/feedback-widget"When deploying to production (e.g., Vercel), add environment variables in your hosting platform's dashboard:
- Vercel: Go to Project Settings β Environment Variables
- Add
DATABASE_URLwith your production database connection string - Redeploy your application
- β
Never commit
.envfiles to Git - β Use different databases for development and production
- β Rotate database passwords regularly
- β
Use environment-specific
.envfiles (.env.development,.env.production) - β Restrict MongoDB network access in production
This project uses Prisma ORM to interact with MongoDB. Prisma provides type-safe database access and automatic migrations.
The database schema is defined in prisma/schema.prisma:
model Feedback {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String?
email String?
message String
rating Int?
createdAt DateTime @default(now())
}Field Descriptions:
id: Unique identifier (MongoDB ObjectId)name: User's name (optional)email: User's email (optional)message: Feedback message (required)rating: Star rating 1-5 (optional)createdAt: Timestamp when feedback was created (auto-set)
- Generate Prisma Client:
npx prisma generateThis command reads your schema and generates a type-safe Prisma Client that you can use in your application.
- Push Schema to Database:
npx prisma db pushThis command creates/updates the database structure based on your schema. It's perfect for development and prototyping.
For Production: Use prisma migrate for proper migrations:
npx prisma migrate dev --name initYou can verify your database connection using Prisma Studio:
npx prisma studioThis opens a visual database browser at http://localhost:5555 where you can view and manage your data.
If you prefer PostgreSQL over MongoDB:
- Update
prisma/schema.prisma:
datasource db {
provider = "postgresql" // Changed from "mongodb"
url = env("DATABASE_URL")
}
model Feedback {
id String @id @default(uuid()) // Changed from ObjectId
name String?
email String?
message String
rating Int?
createdAt DateTime @default(now())
@@map("feedbacks") // Optional: custom table name
}- Update your
.envfile with PostgreSQL connection string:
DATABASE_URL="postgresql://user:password@localhost:5432/feedback-widget"- Regenerate and push:
npx prisma generate
npx prisma db pushStart the development server with hot module replacement:
npm run devFeatures:
- Fast refresh (instant updates on file changes)
- Turbopack bundler for faster builds
- Error overlay in browser
- Accessible at http://localhost:3000
Build the project for production:
npm run buildThis command:
- Generates Prisma Client
- Builds the Next.js application
- Builds the widget UMD bundle
Run the production build locally:
npm run build
npm startBuild just the widget bundle for embedding:
npm run build:widgetThis outputs widget.umd.js in the public/ directory.
This section provides a detailed walkthrough of how the application works.
-
User Interaction:
- User clicks the floating "Feedback" button (bottom-right corner)
- A popover opens with the feedback form
-
Form Submission:
- User fills in name, email, message, and selects a star rating
- User clicks "Submit"
- Form data is sent to
/api/feedbackvia POST request
-
API Processing:
- API route handler receives the request
- Validates the message field (required)
- Creates a new feedback entry in the database using Prisma
- Returns success response
-
UI Update:
- Widget shows success message
- Form is hidden
- User can close the popover
RootLayout (layout.tsx)
βββ Home Page (page.jsx)
βββ Widget Component (Widget.jsx)
βββ Popover (Radix UI)
β βββ PopoverTrigger (Button)
β βββ PopoverContent
β βββ Form (conditional: if not submitted)
β β βββ Name Input
β β βββ Email Input
β β βββ Message Textarea
β β βββ Star Rating (5 StarIcon components)
β β βββ Submit Button
β βββ Success Message (conditional: if submitted)
βββ Separator
The Widget component uses React hooks for state:
const [rating, setRating] = useState(3); // Current star rating
const [submitted, setSubmitted] = useState(false); // Form submission status
const [loading, setLoading] = useState(false); // API call loading state
const [error, setError] = useState(""); // Error messageUser Input β Widget Component State β API Call β Database
β
Success/Error β UI Update
The main feedback collection component.
Props:
apiBase(string, optional): API endpoint URL (defaults to "/api/feedback")
Usage:
import Widget from "@/components/Widget";
// With default API endpoint
<Widget />
// With custom API endpoint
<Widget apiBase="https://api.example.com/feedback" />Features:
- Floating button that opens a popover
- Form with name, email, message, and rating fields
- Star rating system (1-5 stars)
- Loading states during submission
- Error handling and display
- Success state after submission
Key Functions:
// Handle star rating selection
const onSelectStar = (index) => {
setRating(index + 1);
};
// Handle form submission
const submit = async (e) => {
e.preventDefault();
// ... submission logic
};Reusable UI components built with Radix UI and Tailwind CSS.
Button Component:
import { Button } from "@/components/ui/button";
<Button variant="default" size="default">Click me</Button>
<Button variant="outline" size="sm">Outline</Button>
<Button variant="ghost" size="lg">Ghost</Button>Variants: default, destructive, outline, secondary, ghost, link
Sizes: default, sm, lg, icon
Input Component:
import { Input } from "@/components/ui/input";
<Input type="email" placeholder="Enter email" id="email" />;Textarea Component:
import { Textarea } from "@/components/ui/textarea";
<Textarea
placeholder="Enter message"
id="feedback"
className="min-h-[100px]"
/>;Label Component:
import { Label } from "@/components/ui/label";
<Label htmlFor="email">Email Address</Label>;Popover Component:
import {
Popover,
PopoverTrigger,
PopoverContent,
} from "@/components/ui/popover";
<Popover>
<PopoverTrigger asChild>
<Button>Open</Button>
</PopoverTrigger>
<PopoverContent>
<p>Content goes here</p>
</PopoverContent>
</Popover>;Separator Component:
import { Separator } from "@/components/ui/separator";
<Separator className="my-4" />;The API routes are located in src/app/api/feedback/route.js. This file uses Next.js App Router's route handlers.
- Development:
http://localhost:3000/api/feedback - Production:
https://embedded-feedback.vercel.app/api/feedback
Creates a new feedback entry.
Request:
fetch("/api/feedback", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "John Doe",
email: "john@example.com",
message: "Great product!",
rating: 5,
}),
});Request Body:
name(string, optional): User's nameemail(string, optional): User's emailmessage(string, required): Feedback messagerating(number, optional): Star rating (1-5)
Response (Success - 201):
{
"id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"message": "Great product!",
"rating": 5,
"createdAt": "2025-01-15T10:30:00.000Z"
}Response (Error - 400):
{
"error": "Message is required"
}Response (Error - 500):
{
"error": "Failed to save feedback"
}Retrieves all feedback entries, ordered by creation date (newest first).
Request:
fetch("/api/feedback")
.then((res) => res.json())
.then((data) => console.log(data));Response (Success - 200):
[
{
"id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"message": "Great product!",
"rating": 5,
"createdAt": "2025-01-15T10:30:00.000Z"
},
{
"id": "507f1f77bcf86cd799439012",
"name": "Jane Smith",
"email": "jane@example.com",
"message": "Love it!",
"rating": 4,
"createdAt": "2025-01-14T15:20:00.000Z"
}
]Handles CORS preflight requests. This is automatically called by browsers before cross-origin requests.
Response (204):
No content, just CORS headers.
The API includes CORS headers to allow cross-origin requests:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-TypeThis allows the widget to be embedded on different domains.
The widget can be embedded in any HTML page, even outside of React applications, using the Web Component approach.
Build the widget bundle and embed it as a custom HTML element.
npm run build:widgetThis creates public/widget.umd.js.
Add the following to any HTML page:
<!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 (required for the 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 bundle -->
<script src="https://embedded-feedback.vercel.app/widget.umd.js"></script>
<!-- Use the widget as a custom HTML element -->
<my-widget
api-base="https://embedded-feedback.vercel.app/api/feedback"
></my-widget>
<!-- Your other content -->
</body>
</html>You can customize the API endpoint:
<my-widget api-base="https://your-api.com/feedback"></my-widget>If you're building a React application, you can import the component directly:
import Widget from "@/components/Widget";
function MyPage() {
return (
<div>
<h1>My React App</h1>
<Widget apiBase="/api/feedback" />
</div>
);
}You can also embed the entire page in an iframe:
<iframe
src="https://embedded-feedback.vercel.app/"
width="400"
height="600"
frameborder="0"
></iframe>- The widget uses Shadow DOM, so its styles are isolated
- The widget is positioned fixed in the bottom-right corner
- You can override positioning with CSS:
my-widget {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
}All components in this project are designed to be reusable. Here's how to use them in other projects:
The UI components in src/components/ui/ are framework-agnostic React components that can be used anywhere.
Copy the component file(s) you need to your project:
# Example: Copy Button component
cp src/components/ui/button.jsx your-project/src/components/ui/
cp src/lib/utils.ts your-project/src/lib/ # Required dependencyInstall required dependencies:
npm install @radix-ui/react-slot class-variance-authority clsx tailwind-mergeimport { Button } from "./components/ui/button";
function MyComponent() {
return <Button variant="default">Click me</Button>;
}To reuse the entire widget:
- Copy
src/components/Widget.jsxto your project - Copy required UI components (
button,input,textarea,label,popover,separator) - Install all dependencies from
package.json - Adjust import paths as needed
You can extract these components into a separate npm package:
- Create a new repository for your component library
- Copy components and configure build tools
- Publish to npm:
npm publish- Install in other projects:
npm install your-component-libraryTo add new UI components using shadcn/ui:
npx shadcn-ui@latest add [component-name]Example:
npx shadcn-ui@latest add dialog
npx shadcn-ui@latest add toastEdit tailwind.config.js to customize your theme:
module.exports = {
theme: {
extend: {
colors: {
// Add custom colors
brand: {
primary: "#your-color",
secondary: "#your-color",
},
},
borderRadius: {
// Add custom border radius
custom: "12px",
},
},
},
};- Edit
prisma/schema.prisma:
model Feedback {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String?
email String?
message String
rating Int?
category String? // New field
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt // New field
}- Push changes:
npx prisma generate
npx prisma db pushYou can add client-side validation to the Widget component:
const submit = async (e) => {
e.preventDefault();
// Validation
if (!message.trim()) {
setError("Message is required");
return;
}
if (email && !/\S+@\S+\.\S+/.test(email)) {
setError("Please enter a valid email");
return;
}
// ... rest of submission logic
};Create a new route file in src/app/api/:
// src/app/api/feedback/[id]/route.js
import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
export async function GET(request, { params }) {
const { id } = params;
try {
const feedback = await prisma.feedback.findUnique({
where: { id },
});
if (!feedback) {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
return NextResponse.json(feedback);
} catch (error) {
return NextResponse.json({ error: "Failed to fetch" }, { status: 500 });
}
}Build the entire Next.js application:
npm run buildThis creates an optimized production build in the .next directory.
Build just the widget for embedding:
npm run build:widgetThis creates public/widget.umd.js using Vite.
The build script (npm run build) does three things:
- Generates Prisma Client: Creates type-safe database client
- Builds Next.js App: Compiles and optimizes the Next.js application
- Builds Widget Bundle: Creates UMD bundle for embedding
Vercel is the recommended platform for Next.js applications.
git add .
git commit -m "Ready for deployment"
git push origin main- Go to vercel.com
- Click "Import Project"
- Select your GitHub repository
- Configure environment variables:
- Add
DATABASE_URLwith your production database connection string
- Add
- Click "Deploy"
Update the widget embedding URLs to use your Vercel deployment:
<script src="https://your-app.vercel.app/widget.umd.js"></script>
<my-widget api-base="https://your-app.vercel.app/api/feedback"></my-widget>- Connect your GitHub repository
- Build command:
npm run build - Publish directory:
.next - Add environment variables in Netlify dashboard
- Connect your GitHub repository
- Add environment variables
- Railway automatically detects Next.js and deploys
Create a Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]Build and run:
docker build -t feedback-widget .
docker run -p 3000:3000 -e DATABASE_URL="your-db-url" feedback-widgetThis project covers and demonstrates the following concepts and technologies:
Frontend:
- React, React Hooks, Functional Components, Client Components, Server Components
- Next.js, App Router, API Routes, Server-Side Rendering
- Tailwind CSS, Utility-First CSS, Responsive Design
- Web Components, Custom Elements, Shadow DOM
- TypeScript, JavaScript ES6+, Modern JavaScript
Backend:
- RESTful API, HTTP Methods, API Routes
- CORS, Cross-Origin Resource Sharing
- Serverless Functions, Edge Functions
Database:
- MongoDB, NoSQL, Document Database
- Prisma ORM, Database Migrations, Type-Safe Database Access
- Database Schema Design, Data Modeling
UI/UX:
- Radix UI, Accessible Components, ARIA Attributes
- Form Handling, Input Validation, User Feedback
- Loading States, Error Handling, Success States
Build Tools:
- Vite, Module Bundling, UMD Format
- Turbopack, Fast Refresh, Hot Module Replacement
- PostCSS, CSS Processing
Development:
- Git, Version Control
- ESLint, Code Quality
- Environment Variables, Configuration Management
- Component Reusability, Modular Architecture
Deployment:
- Vercel, Serverless Deployment
- Production Builds, Performance Optimization
Keywords: feedback-widget, reactjs, nextjs, feedback-form, mongodb, prisma, tailwindcss, widget-embedding, web-components, reusable-components, fullstack, typescript, api-integration, vercel, modern-web, component-library, teaching-resource, educational-project, real-world-example
- Next.js Documentation - Comprehensive Next.js guide
- React Documentation - Official React documentation
- Prisma Documentation - Prisma ORM guide
- Tailwind CSS Documentation - Tailwind CSS reference
- Radix UI Documentation - Radix UI components
- Vercel Documentation - Vercel deployment guide
- Next.js Learn Course - Interactive Next.js tutorial
- React Testing Library - Testing React components
- Web Components Guide - MDN Web Components documentation
- MongoDB University - Free MongoDB courses
- Next.js Examples - Official Next.js examples
- shadcn/ui - Re-usable components built with Radix UI and Tailwind CSS
Author: Arnob Mahmud
Portfolio: https://arnob-mahmud.vercel.app/
This project is designed as a comprehensive teaching and demonstration tool for modern web development workflows. It showcases:
- Best Practices: Industry-standard patterns and conventions
- Modern Stack: Latest versions of popular frameworks and tools
- Real-World Patterns: Practical solutions to common problems
- Educational Focus: Extensive comments and documentation for learning
- Learning: Understand modern React and Next.js patterns
- Reference: Use as a reference for similar projects
- Starting Point: Fork and customize for your own needs
- Production: Deploy and use in real applications
Contributions, issues, and feature requests are welcome! Feel free to:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
This Embedded Feedback Widget project demonstrates a complete, production-ready full-stack application built with modern web technologies. It showcases:
β
Component Reusability - Modular, reusable components that can be used across projects
β
Modern Architecture - Next.js App Router, React Server Components, API Routes
β
Type Safety - TypeScript and Prisma for type-safe code
β
Best Practices - Proper error handling, loading states, and user feedback
β
Accessibility - WCAG-compliant components with keyboard navigation
β
Production Ready - Optimized builds, CORS support, and deployment configurations
β
Educational Value - Comprehensive comments and documentation for learning
Whether you're learning modern web development, building a feedback system for your application, or creating reusable components, this project provides a solid foundation to build upon.
The codebase is well-structured, thoroughly commented, and follows industry best practices, making it an excellent resource for developers at all levels.
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! π


