Skip to content

A beautifully designed, high-performance e-commerce platform built with Next.js 14, TypeScript, Prisma, NeonDB, Vercel Blob Storage, Clerk authentication, Stripe payments, and shadcn/ui. Next Store offers a seamless online shopping experience with fast checkout, secure payments, and a curated selection of products.

Notifications You must be signed in to change notification settings

arnobt78/Ecommerce-Platform--NextJS-Serverless-FullStack

Repository files navigation

Next Store | E-Commerce Platform - Next.js, TypeScript, Prisma, NeonDB, Vercel Blob, Clerk, Stripe Fullstack Project

A beautifully designed, high-performance e-commerce platform built with Next.js 14, TypeScript, Prisma, NeonDB, Vercel Blob Storage, Clerk authentication, Stripe payments, and shadcn/ui. Next Store offers a seamless online shopping experience with fast checkout, secure payments, and a curated selection of products.

Screenshot 2025-06-14 at 14 56 42 Screenshot 2025-06-14 at 14 57 07 Screenshot 2025-06-14 at 14 58 00 Screenshot 2025-06-14 at 14 59 55 Screenshot 2025-06-14 at 15 00 18 Screenshot 2025-06-14 at 15 00 40 Screenshot 2025-06-14 at 15 00 51 Screenshot 2025-06-14 at 15 01 26


πŸ“‹ Table of Contents


πŸš€ Features & Functionalities

Core Features

  • πŸ›οΈ Product Management

    • Browse products with grid and list views
    • Search and filter products by name or company
    • Featured products showcase on homepage
    • Detailed product pages with images, descriptions, and reviews
    • Admin CRUD operations for products
  • πŸ›’ Shopping Cart

    • Add/remove items from cart
    • Update item quantities
    • Real-time cart total calculations
    • Persistent cart per user session
  • πŸ’³ Secure Checkout

    • Stripe embedded checkout integration
    • Secure payment processing
    • Order confirmation and tracking
  • ⭐ Favorites System

    • Save favorite products
    • Quick access to saved items
    • Toggle favorites with one click
  • πŸ“ Product Reviews

    • Submit product reviews with ratings (1-5 stars)
    • View all reviews for each product
    • Average rating calculation
    • Review management (view and delete your reviews)
  • πŸ‘€ User Authentication

    • Clerk-powered authentication
    • Multiple sign-in options (Google, GitHub, Email)
    • Protected routes and admin access control
    • User profile management
  • πŸ‘¨β€πŸ’Ό Admin Dashboard

    • Admin-only product management
    • Sales overview and analytics
    • Order management
    • Image upload and management
  • 🎨 Modern UI/UX

    • Dark mode support
    • Responsive design (mobile-first)
    • Beautiful shadcn/ui components
    • Smooth animations and transitions
    • Loading states and error handling
  • πŸ“Έ Image Management

    • Upload product images to Vercel Blob Storage
    • Automatic image optimization
    • Image deletion on product removal

πŸ› οΈ Tech Stack

Frontend

  • Next.js 14 - React framework with App Router
  • TypeScript - Type-safe development
  • React 18 - UI library
  • Tailwind CSS - Utility-first CSS framework
  • shadcn/ui - Beautiful, accessible UI components
  • Radix UI - Unstyled, accessible component primitives
  • next-themes - Dark mode implementation
  • Embla Carousel - Carousel component for hero section
  • React Icons - Icon library
  • React Share - Social sharing functionality

Backend & Database

  • Prisma ORM - Type-safe database access
  • NeonDB - Serverless PostgreSQL database
  • Next.js Server Actions - Server-side data mutations
  • Next.js API Routes - RESTful API endpoints

Authentication & Payments

  • Clerk - Authentication and user management
  • Stripe - Payment processing and checkout

Storage & Deployment

  • Vercel Blob Storage - Image and file storage
  • Vercel - Hosting and deployment platform

Development Tools

  • Zod - Schema validation
  • ESLint - Code linting
  • TypeScript - Static type checking

πŸ“ Project Structure

nextjs-store/
β”œβ”€β”€ app/                          # Next.js App Router directory
β”‚   β”œβ”€β”€ about/                    # About page
β”‚   β”œβ”€β”€ admin/                    # Admin dashboard routes
β”‚   β”‚   β”œβ”€β”€ layout.tsx           # Admin layout with sidebar
β”‚   β”‚   β”œβ”€β”€ products/            # Product management
β”‚   β”‚   β”‚   β”œβ”€β”€ [id]/           # Dynamic product routes
β”‚   β”‚   β”‚   β”‚   └── edit/      # Edit product page
β”‚   β”‚   β”‚   β”œβ”€β”€ create/         # Create product page
β”‚   β”‚   β”‚   β”œβ”€β”€ loading.tsx    # Loading state
β”‚   β”‚   β”‚   └── page.tsx        # Products list page
β”‚   β”‚   β”œβ”€β”€ sales/              # Sales dashboard
β”‚   β”‚   β”‚   β”œβ”€β”€ loading.tsx
β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   └── Sidebar.tsx         # Admin sidebar component
β”‚   β”œβ”€β”€ api/                     # API routes
β”‚   β”‚   β”œβ”€β”€ confirm/            # Stripe payment confirmation
β”‚   β”‚   β”‚   └── route.ts
β”‚   β”‚   └── payment/             # Stripe checkout session
β”‚   β”‚       └── route.ts
β”‚   β”œβ”€β”€ cart/                    # Shopping cart page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ checkout/                # Checkout page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ favorites/               # User favorites page
β”‚   β”‚   β”œβ”€β”€ loading.tsx
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ orders/                  # User orders page
β”‚   β”‚   β”œβ”€β”€ loading.tsx
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ products/                # Products pages
β”‚   β”‚   β”œβ”€β”€ [id]/               # Single product page
β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”œβ”€β”€ loading.tsx
β”‚   β”‚   └── page.tsx            # Products list page
β”‚   β”œβ”€β”€ reviews/                 # Reviews page
β”‚   β”‚   β”œβ”€β”€ loading.tsx
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ favicon.ico              # Site favicon
β”‚   β”œβ”€β”€ globals.css              # Global styles
β”‚   β”œβ”€β”€ layout.tsx               # Root layout
β”‚   β”œβ”€β”€ page.tsx                 # Homepage
β”‚   β”œβ”€β”€ providers.tsx             # Context providers
β”‚   └── theme-provider.tsx        # Theme context provider
β”œβ”€β”€ components/                   # Reusable components
β”‚   β”œβ”€β”€ cart/                    # Cart-related components
β”‚   β”‚   β”œβ”€β”€ CartItemColumns.tsx
β”‚   β”‚   β”œβ”€β”€ CartItemsList.tsx
β”‚   β”‚   β”œβ”€β”€ CartTotals.tsx
β”‚   β”‚   └── ThirdColumn.tsx
β”‚   β”œβ”€β”€ form/                    # Form components
β”‚   β”‚   β”œβ”€β”€ Buttons.tsx
β”‚   β”‚   β”œβ”€β”€ CheckboxInput.tsx
β”‚   β”‚   β”œβ”€β”€ FormContainer.tsx
β”‚   β”‚   β”œβ”€β”€ FormInput.tsx
β”‚   β”‚   β”œβ”€β”€ ImageInput.tsx
β”‚   β”‚   β”œβ”€β”€ ImageInputContainer.tsx
β”‚   β”‚   β”œβ”€β”€ PriceInput.tsx
β”‚   β”‚   └── TextAreaInput.tsx
β”‚   β”œβ”€β”€ global/                  # Global utility components
β”‚   β”‚   β”œβ”€β”€ Container.tsx
β”‚   β”‚   β”œβ”€β”€ EmptyList.tsx
β”‚   β”‚   β”œβ”€β”€ LoadingContainer.tsx
β”‚   β”‚   β”œβ”€β”€ LoadingTable.tsx
β”‚   β”‚   └── SectionTitle.tsx
β”‚   β”œβ”€β”€ home/                    # Homepage components
β”‚   β”‚   β”œβ”€β”€ FeaturedProducts.tsx
β”‚   β”‚   β”œβ”€β”€ Hero.tsx
β”‚   β”‚   └── HeroCarousel.tsx
β”‚   β”œβ”€β”€ navbar/                  # Navigation components
β”‚   β”‚   β”œβ”€β”€ CartButton.tsx
β”‚   β”‚   β”œβ”€β”€ DarkMode.tsx
β”‚   β”‚   β”œβ”€β”€ LinksDropdown.tsx
β”‚   β”‚   β”œβ”€β”€ Logo.tsx
β”‚   β”‚   β”œβ”€β”€ Navbar.tsx
β”‚   β”‚   β”œβ”€β”€ NavSearch.tsx
β”‚   β”‚   β”œβ”€β”€ SignOutLink.tsx
β”‚   β”‚   └── UserIcon.tsx
β”‚   β”œβ”€β”€ products/                # Product-related components
β”‚   β”‚   β”œβ”€β”€ FavoriteToggleButton.tsx
β”‚   β”‚   β”œβ”€β”€ FavoriteToggleForm.tsx
β”‚   β”‚   β”œβ”€β”€ ProductsContainer.tsx
β”‚   β”‚   β”œβ”€β”€ ProductsGrid.tsx
β”‚   β”‚   └── ProductsList.tsx
β”‚   β”œβ”€β”€ reviews/                 # Review components
β”‚   β”‚   β”œβ”€β”€ Comment.tsx
β”‚   β”‚   β”œβ”€β”€ ProductReviews.tsx
β”‚   β”‚   β”œβ”€β”€ Rating.tsx
β”‚   β”‚   β”œβ”€β”€ RatingInput.tsx
β”‚   β”‚   β”œβ”€β”€ ReviewCard.tsx
β”‚   β”‚   └── SubmitReview.tsx
β”‚   β”œβ”€β”€ single-product/          # Single product page components
β”‚   β”‚   β”œβ”€β”€ AddToCart.tsx
β”‚   β”‚   β”œβ”€β”€ BreadCrumbs.tsx
β”‚   β”‚   β”œβ”€β”€ ProductRating.tsx
β”‚   β”‚   β”œβ”€β”€ SelectProductAmount.tsx
β”‚   β”‚   └── ShareButton.tsx
β”‚   └── ui/                      # shadcn/ui components
β”‚       β”œβ”€β”€ breadcrumb.tsx
β”‚       β”œβ”€β”€ button.tsx
β”‚       β”œβ”€β”€ card.tsx
β”‚       β”œβ”€β”€ carousel.tsx
β”‚       β”œβ”€β”€ checkbox.tsx
β”‚       β”œβ”€β”€ dropdown-menu.tsx
β”‚       β”œβ”€β”€ input.tsx
β”‚       β”œβ”€β”€ label.tsx
β”‚       β”œβ”€β”€ popover.tsx
β”‚       β”œβ”€β”€ select.tsx
β”‚       β”œβ”€β”€ separator.tsx
β”‚       β”œβ”€β”€ skeleton.tsx
β”‚       β”œβ”€β”€ table.tsx
β”‚       β”œβ”€β”€ textarea.tsx
β”‚       β”œβ”€β”€ toast.tsx
β”‚       β”œβ”€β”€ toaster.tsx
β”‚       └── use-toast.ts
β”œβ”€β”€ lib/                         # Utility libraries
β”‚   └── utils.ts                 # Utility functions (cn, etc.)
β”œβ”€β”€ prisma/                      # Prisma configuration
β”‚   β”œβ”€β”€ schema.prisma            # Database schema
β”‚   β”œβ”€β”€ seed.js                  # Database seeding script
β”‚   └── products.json            # Sample product data
β”œβ”€β”€ public/                      # Static assets
β”‚   β”œβ”€β”€ images/                  # Image assets
β”‚   β”‚   β”œβ”€β”€ hero1.jpg
β”‚   β”‚   β”œβ”€β”€ hero2.jpg
β”‚   β”‚   β”œβ”€β”€ hero3.jpg
β”‚   β”‚   β”œβ”€β”€ hero4.jpg
β”‚   β”‚   └── product-*.jpg
β”‚   └── logo.png                 # Site logo
β”œβ”€β”€ utils/                       # Utility functions
β”‚   β”œβ”€β”€ actions.ts               # Server actions
β”‚   β”œβ”€β”€ db.ts                    # Prisma client instance
β”‚   β”œβ”€β”€ format.ts                # Formatting utilities
β”‚   β”œβ”€β”€ links.ts                 # Navigation links
β”‚   β”œβ”€β”€ schemas.ts               # Zod validation schemas
β”‚   β”œβ”€β”€ supabase.ts              # Image upload/delete (Vercel Blob)
β”‚   └── types.ts                 # TypeScript type definitions
β”œβ”€β”€ .env                         # Environment variables (not committed)
β”œβ”€β”€ .env.local                   # Local environment variables (not committed)
β”œβ”€β”€ middleware.ts                 # Next.js middleware (Clerk auth)
β”œβ”€β”€ next.config.mjs              # Next.js configuration
β”œβ”€β”€ package.json                 # Dependencies and scripts
β”œβ”€β”€ tailwind.config.ts           # Tailwind CSS configuration
β”œβ”€β”€ tsconfig.json                # TypeScript configuration
└── README.md                    # This file

πŸš€ Getting Started

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js 18.x or higher
  • npm or yarn package manager
  • Git for version control

Installation Steps

  1. Clone the repository
git clone https://github.com/your-username/nextjs-store.git
cd nextjs-store
  1. Install dependencies
npm install
  1. Set up environment variables

Create .env and .env.local files in the root directory (see Environment Variables Setup section below).

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

# Push schema to database
npx prisma db push

# Seed the database (optional)
node prisma/seed.js
  1. Run the development server
npm run dev
  1. Open your browser

Navigate to http://localhost:3000 to see the application.


πŸ” Environment Variables Setup

This project requires several environment variables to function properly. Create two files: .env and .env.local in the root directory.

.env File

This file contains non-sensitive configuration variables:

# NeonDB Database Connection
DATABASE_URL="postgresql://user:password@host:port/database?sslmode=require"
DIRECT_URL="postgresql://user:password@host:port/database?sslmode=require"

# Admin User ID (Clerk)
ADMIN_USER_ID="user_xxxxxxxxxxxxx"

# Website URL
NEXT_PUBLIC_WEBSITE_URL="https://your-domain.vercel.app/"

# Stripe Configuration
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_xxxxxxxxxxxxx"
STRIPE_SECRET_KEY="sk_test_xxxxxxxxxxxxx"
# Optional: For webhook verification
# STRIPE_WEBHOOK_SECRET="whsec_xxxxxxxxxxxxx"

.env.local File

This file contains sensitive secrets (never commit to git):

# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_xxxxxxxxxxxxx"
CLERK_SECRET_KEY="sk_test_xxxxxxxxxxxxx"

# Vercel Blob Storage
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_xxxxxxxxxxxxx"

How to Get Each Environment Variable

1. NeonDB Database Connection

  1. Go to Neon Console
  2. Create a new project or select an existing one
  3. Go to Connection Details
  4. Copy the Pooled connection string β†’ Use for DATABASE_URL
  5. Copy the Direct connection string β†’ Use for DIRECT_URL

Format:

DATABASE_URL="postgresql://user:[email protected]/dbname?sslmode=require"
DIRECT_URL="postgresql://user:[email protected]/dbname?sslmode=require"

2. Clerk Authentication

  1. Go to Clerk Dashboard
  2. Create a new application or select an existing one
  3. Go to API Keys section
  4. Copy Publishable Key β†’ Use for NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
  5. Copy Secret Key β†’ Use for CLERK_SECRET_KEY
  6. To get ADMIN_USER_ID:
    • Sign in to your application
    • Go to Users section in Clerk dashboard
    • Click on your user
    • Copy the User ID β†’ Use for ADMIN_USER_ID

3. Stripe Payments

  1. Go to Stripe Dashboard
  2. Navigate to Developers β†’ API keys
  3. Copy Publishable key β†’ Use for NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
  4. Copy Secret key β†’ Use for STRIPE_SECRET_KEY
  5. For webhooks (optional):
    • Go to Developers β†’ Webhooks
    • Create a webhook endpoint
    • Copy the Signing secret β†’ Use for STRIPE_WEBHOOK_SECRET

4. Vercel Blob Storage

  1. Go to Vercel Dashboard
  2. Select your project
  3. Navigate to Storage tab (top navigation)
  4. Click Create next to Blob
  5. Name your blob store (e.g., product-images)
  6. Click Connect to connect it to your project
  7. The BLOB_READ_WRITE_TOKEN will be automatically added to your Vercel environment variables
  8. Copy the token from Vercel dashboard β†’ Settings β†’ Environment Variables
  9. Add it to your local .env.local file

5. Website URL

Set NEXT_PUBLIC_WEBSITE_URL to your production domain:

NEXT_PUBLIC_WEBSITE_URL="https://your-domain.vercel.app/"

Important Notes

  • Never commit .env or .env.local files to version control
  • Both files are already in .gitignore
  • Use quotes around values that contain special characters
  • For production, add all variables to your Vercel project settings

πŸ—„οΈ Database Setup

Prisma Schema

The project uses Prisma ORM with the following models:

  • Product - Stores product information
  • Favorite - User favorite products
  • Review - Product reviews and ratings
  • Cart - Shopping cart
  • CartItem - Individual cart items
  • Order - Customer orders

Database Commands

# Generate Prisma Client
npx prisma generate

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

# Create a migration (production)
npx prisma migrate dev --name migration_name

# Seed the database
node prisma/seed.js

# Open Prisma Studio (database GUI)
npx prisma studio

Database Schema Overview

model Product {
  id          String     @id @default(uuid())
  name        String
  company     String
  description String
  featured    Boolean
  image       String
  price       Int
  clerkId     String
  createdAt   DateTime   @default(now())
  updatedAt   DateTime   @updatedAt
  favorites   Favorite[]
  reviews     Review[]
  cartItems   CartItem[]
}

model Favorite {
  id        String   @id @default(uuid())
  clerkId   String
  productId String
  product   Product  @relation(fields: [productId], references: [id], onDelete: Cascade)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Review {
  id            String   @id @default(uuid())
  clerkId       String
  productId     String
  rating        Int
  comment       String
  authorName    String
  authorImageUrl String
  product       Product  @relation(fields: [productId], references: [id], onDelete: Cascade)
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
}

model Cart {
  id            String     @id @default(uuid())
  clerkId       String
  cartItems     CartItem[]
  numItemsInCart Int       @default(0)
  cartTotal     Int        @default(0)
  shipping      Int        @default(5)
  tax           Int        @default(0)
  taxRate       Float      @default(0.1)
  orderTotal    Int        @default(0)
  createdAt     DateTime   @default(now())
  updatedAt     DateTime   @updatedAt
}

model CartItem {
  id        String   @id @default(uuid())
  productId String
  cartId    String
  amount    Int
  product   Product  @relation(fields: [productId], references: [id], onDelete: Cascade)
  cart      Cart     @relation(fields: [cartId], references: [id], onDelete: Cascade)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Order {
  id         String   @id @default(uuid())
  clerkId    String
  products   Int      @default(0)
  orderTotal Int      @default(0)
  tax        Int      @default(0)
  shipping   Int      @default(0)
  email      String
  isPaid     Boolean  @default(false)
  createdAt  DateTime @default(now())
  updatedAt DateTime @updatedAt
}

πŸ”Œ API Endpoints

The project includes two API routes for Stripe payment processing:

1. POST /api/payment

Creates a Stripe checkout session for payment processing.

Request Body:

{
  "orderId": "order-uuid",
  "cartId": "cart-uuid"
}

Response:

{
  "clientSecret": "cs_test_xxxxxxxxxxxxx"
}

Usage Example:

const response = await fetch("/api/payment", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ orderId, cartId }),
});
const { clientSecret } = await response.json();

2. GET /api/confirm?session_id={CHECKOUT_SESSION_ID}

Confirms payment and updates order status after Stripe checkout completion.

Query Parameters:

  • session_id - Stripe checkout session ID

Response:

  • Redirects to /orders page on success

How It Works:

  1. Retrieves the Stripe checkout session
  2. Updates order status to isPaid: true if payment is complete
  3. Deletes the cart after successful payment
  4. Redirects user to orders page

πŸ›£οΈ Routes & Pages

Public Routes

  • / - Homepage with hero section and featured products
  • /about - About page
  • /products - Products listing page with search functionality
  • /products/[id] - Single product detail page
  • /cart - Shopping cart page
  • /checkout - Checkout page with Stripe embedded checkout
  • /favorites - User's favorite products (requires authentication)
  • /orders - User's order history (requires authentication)
  • /reviews - User's submitted reviews (requires authentication)

Admin Routes (Protected)

  • /admin/sales - Sales dashboard and analytics
  • /admin/products - Product management list
  • /admin/products/create - Create new product
  • /admin/products/[id]/edit - Edit existing product

Route Protection

All routes are protected by Clerk middleware. Admin routes additionally check for ADMIN_USER_ID match.

Middleware Configuration:

// middleware.ts
import { clerkMiddleware } from "@clerk/nextjs/server";

export default clerkMiddleware();

export const config = {
  matcher: ["/((?!_next|favicon.ico|public).*)"],
};

🧩 Components Guide

Component Categories

1. Global Components (components/global/)

Container.tsx
  • Wrapper component for consistent page layout
  • Usage: <Container className="py-20">{children}</Container>
LoadingContainer.tsx
  • Loading state component with skeleton UI
  • Usage: <LoadingContainer />
EmptyList.tsx
  • Displays empty state messages
  • Usage: <EmptyList resourceName="products" />
SectionTitle.tsx
  • Consistent section heading component
  • Usage: <SectionTitle text="Featured Products" />

2. Form Components (components/form/)

FormContainer.tsx
  • Wrapper for form elements with consistent styling
  • Usage: <FormContainer title="Create Product">{form}</FormContainer>
FormInput.tsx
  • Reusable text input component
  • Usage: <FormInput name="name" label="Product Name" />
PriceInput.tsx
  • Specialized input for price with currency formatting
  • Usage: <PriceInput name="price" label="Price" />
TextAreaInput.tsx
  • Textarea component for longer text inputs
  • Usage: <TextAreaInput name="description" label="Description" />
ImageInput.tsx
  • File input for image uploads
  • Usage: <ImageInput />
CheckboxInput.tsx
  • Checkbox component with label
  • Usage: <CheckboxInput name="featured" label="Featured Product" />

3. Product Components (components/products/)

ProductsContainer.tsx
  • Container that handles product fetching and layout switching
  • Usage: <ProductsContainer layout="grid" search={searchTerm} />
ProductsGrid.tsx
  • Grid layout for product display
  • Usage: <ProductsGrid products={products} />
ProductsList.tsx
  • List layout for product display
  • Usage: <ProductsList products={products} />
FavoriteToggleButton.tsx
  • Button to toggle favorite status
  • Usage: <FavoriteToggleButton productId={productId} />

4. Cart Components (components/cart/)

CartItemsList.tsx
  • Displays all items in the cart
  • Usage: <CartItemsList cartItems={cartItems} />
CartTotals.tsx
  • Displays cart totals (subtotal, tax, shipping, total)
  • Usage: <CartTotals cart={cart} />
CartItemColumns.tsx
  • Column components for cart item display
  • Usage: <FirstColumn name={name} image={image} />

5. Review Components (components/reviews/)

ProductReviews.tsx
  • Displays all reviews for a product
  • Usage: <ProductReviews productId={productId} />
SubmitReview.tsx
  • Form component for submitting reviews
  • Usage: <SubmitReview productId={productId} />
ReviewCard.tsx
  • Individual review card component
  • Usage: <ReviewCard review={review} />
Rating.tsx
  • Star rating display component
  • Usage: <Rating rating={4.5} />

6. Navbar Components (components/navbar/)

Navbar.tsx
  • Main navigation bar component
  • Usage: Automatically included in root layout
NavSearch.tsx
  • Search input in navbar
  • Usage: Included in Navbar
CartButton.tsx
  • Cart icon button with item count
  • Usage: Included in Navbar
DarkMode.tsx
  • Dark mode toggle button
  • Usage: Included in Navbar
LinksDropdown.tsx
  • Dropdown menu for navigation links
  • Usage: Included in Navbar

7. UI Components (components/ui/)

These are shadcn/ui components. You can add more using:

npx shadcn-ui@latest add [component-name]

Common components used:

  • Button - Styled button component
  • Card - Card container component
  • Input - Text input component
  • Table - Table component
  • Toast - Toast notification system
  • Skeleton - Loading skeleton component

⚑ Server Actions

Server Actions are defined in utils/actions.ts. They handle all server-side data mutations.

Product Actions

fetchFeaturedProducts()

const products = await fetchFeaturedProducts();
// Returns: Product[] - All products where featured: true

fetchAllProducts({ search })

const products = await fetchAllProducts({ search: "lamp" });
// Returns: Product[] - Filtered products by search term

fetchSingleProduct(productId)

const product = await fetchSingleProduct("product-uuid");
// Returns: Product - Single product or redirects if not found

createProductAction(prevState, formData)

// Server action for creating a product
// Handles image upload, validation, and database insertion

updateProductAction(prevState, formData)

// Server action for updating product details

updateProductImageAction(prevState, formData)

// Server action for updating product image
// Handles old image deletion and new image upload

deleteProductAction(prevState)

// Server action for deleting a product
// Also deletes associated image from storage

Cart Actions

fetchCartItems()

const itemCount = await fetchCartItems();
// Returns: number - Number of items in cart

addToCartAction(prevState, formData)

// Server action for adding items to cart
// Creates cart if doesn't exist, updates totals

updateCartItemAction({ amount, cartItemId })

// Server action for updating cart item quantity

removeCartItemAction(prevState, formData)

// Server action for removing item from cart

Favorite Actions

fetchFavoriteId({ productId })

const favoriteId = await fetchFavoriteId({ productId });
// Returns: string | null - Favorite ID if exists

toggleFavoriteAction(prevState)

// Server action for toggling favorite status

fetchUserFavorites()

const favorites = await fetchUserFavorites();
// Returns: Favorite[] with product data

Review Actions

createReviewAction(prevState, formData)

// Server action for creating a product review

fetchProductReviews(productId)

const reviews = await fetchProductReviews("product-uuid");
// Returns: Review[] - All reviews for a product

fetchProductRating(productId)

const { rating, count } = await fetchProductRating("product-uuid");
// Returns: { rating: string, count: number }

deleteReviewAction(prevState)

// Server action for deleting a review

Order Actions

createOrderAction(prevState, formData)

// Server action for creating an order
// Deletes unpaid orders, creates new order

fetchUserOrders()

const orders = await fetchUserOrders();
// Returns: Order[] - All paid orders for user

fetchAdminOrders()

const orders = await fetchAdminOrders();
// Returns: Order[] - All paid orders (admin only)

πŸ”„ How It Works

Authentication Flow

  1. User visits the site
  2. Clerk middleware checks authentication status
  3. Protected routes require sign-in
  4. After sign-in, user session is maintained
  5. Admin routes check ADMIN_USER_ID match

Product Management Flow

  1. Create Product:

    • Admin fills form with product details
    • Image is uploaded to Vercel Blob Storage
    • Image URL is returned and stored in database
    • Product is created with all details
  2. Update Product:

    • Admin edits product details
    • If image is updated, old image is deleted
    • New image is uploaded and URL updated
    • Product record is updated in database
  3. Delete Product:

    • Product is deleted from database
    • Associated image is deleted from storage
    • Related favorites, reviews, and cart items are cascade deleted

Shopping Cart Flow

  1. User adds product to cart
  2. Cart is created if doesn't exist
  3. Cart item is added or quantity updated
  4. Cart totals are recalculated (subtotal, tax, shipping, total)
  5. Cart persists across sessions per user

Checkout Flow

  1. User clicks checkout from cart
  2. Order is created with cart details
  3. Stripe checkout session is created via /api/payment
  4. User completes payment in embedded Stripe checkout
  5. After payment, /api/confirm is called
  6. Order status is updated to isPaid: true
  7. Cart is deleted
  8. User is redirected to orders page

Image Upload Flow

  1. User selects image file
  2. File is validated (size, type)
  3. Image is uploaded to Vercel Blob Storage using uploadImage()
  4. Public URL is returned
  5. URL is stored in database
  6. Image is served from Vercel Blob CDN

Review System Flow

  1. User views product page
  2. If user hasn't reviewed, review form is shown
  3. User submits rating and comment
  4. Review is validated and saved
  5. Product rating is recalculated
  6. Review appears on product page

♻️ Reusing Components

How to Reuse Components in Other Projects

1. Copy Component Files

Simply copy the component file and its dependencies:

# Example: Reusing the Container component
cp components/global/Container.tsx your-project/components/

2. Install Required Dependencies

Check package.json for required packages:

npm install tailwind-merge clsx

3. Update Imports

Update import paths to match your project structure:

// Before
import Container from "@/components/global/Container";

// After (if using different path)
import Container from "../components/Container";

4. Component Usage Examples

Container Component
import Container from "@/components/global/Container";

export default function MyPage() {
  return (
    <Container className="py-20">
      <h1>My Content</h1>
    </Container>
  );
}
Form Components
import FormContainer from "@/components/form/FormContainer";
import FormInput from "@/components/form/FormInput";
import { createProductAction } from "@/utils/actions";

export default function CreateForm() {
  return (
    <FormContainer title="Create Item">
      <form action={createProductAction}>
        <FormInput name="name" label="Name" />
        <button type="submit">Submit</button>
      </form>
    </FormContainer>
  );
}
Product Grid
import ProductsGrid from "@/components/products/ProductsGrid";

export default async function ProductsPage() {
  const products = await fetchProducts();
  return <ProductsGrid products={products} />;
}
Loading States
import { Suspense } from "react";
import LoadingContainer from "@/components/global/LoadingContainer";
import ProductsGrid from "@/components/products/ProductsGrid";

export default function ProductsPage() {
  return (
    <Suspense fallback={<LoadingContainer />}>
      <ProductsGrid products={products} />
    </Suspense>
  );
}

Adapting Components

Most components are designed to be reusable. To adapt them:

  1. Update Types: Modify TypeScript interfaces to match your data structure
  2. Update Actions: Replace server actions with your own data fetching logic
  3. Update Styling: Adjust Tailwind classes to match your design system
  4. Remove Dependencies: Remove Clerk-specific code if not using Clerk

πŸš€ Deployment

Deploying to Vercel

  1. Push to GitHub
git add .
git commit -m "Ready for deployment"
git push origin main
  1. Import to Vercel

    • Go to Vercel Dashboard
    • Click Add New Project
    • Import your GitHub repository
    • Vercel will auto-detect Next.js
  2. Configure Environment Variables

    • Go to Settings β†’ Environment Variables
    • Add all variables from .env and .env.local
    • Set for all environments (Production, Preview, Development)
  3. Deploy

    • Vercel will automatically deploy
    • Your site will be live at your-project.vercel.app

Build Commands

The project includes a custom build script:

{
  "scripts": {
    "build": "npx prisma generate && next build"
  }
}

This ensures Prisma Client is generated before building.

Post-Deployment Checklist

  • All environment variables are set in Vercel
  • Database is accessible from Vercel
  • Stripe keys are set (use production keys)
  • Clerk keys are set
  • Vercel Blob Storage is connected
  • Domain is configured (if using custom domain)
  • Test all major features (cart, checkout, admin)

🏷️ Keywords

Technologies:

  • Next.js 14
  • React 18
  • TypeScript
  • Prisma ORM
  • NeonDB
  • PostgreSQL
  • Vercel Blob Storage
  • Clerk Authentication
  • Stripe Payments
  • Tailwind CSS
  • shadcn/ui
  • Radix UI
  • Zod Validation
  • Server Actions
  • App Router

Features:

  • E-commerce
  • Online Store
  • Shopping Cart
  • Product Management
  • Payment Processing
  • User Authentication
  • Admin Dashboard
  • Product Reviews
  • Favorites System
  • Image Upload
  • Dark Mode
  • Responsive Design

Concepts:

  • Server-Side Rendering (SSR)
  • Static Site Generation (SSG)
  • API Routes
  • Server Actions
  • Type-Safe Database
  • Form Validation
  • Error Handling
  • Loading States

πŸŽ“ Educational Value

This project demonstrates:

  1. Modern Next.js Patterns:

    • App Router architecture
    • Server Components vs Client Components
    • Server Actions for mutations
    • API Routes for external integrations
  2. Type Safety:

    • TypeScript throughout
    • Prisma type generation
    • Zod schema validation
  3. Database Design:

    • Relational database modeling
    • Cascade deletions
    • Efficient queries
  4. Authentication & Authorization:

    • Clerk integration
    • Protected routes
    • Role-based access (admin)
  5. Payment Integration:

    • Stripe embedded checkout
    • Payment confirmation flow
    • Order management
  6. File Storage:

    • Vercel Blob Storage
    • Image upload handling
    • Public URL generation
  7. UI/UX Best Practices:

    • Responsive design
    • Dark mode
    • Loading states
    • Error handling
    • Form validation
  8. Code Organization:

    • Component reusability
    • Separation of concerns
    • Utility functions
    • Type definitions

πŸ“š Learning Resources

Next.js

Prisma

Clerk

Stripe

Vercel Blob


πŸ› Troubleshooting

Common Issues

1. Database Connection Error

  • Verify DATABASE_URL and DIRECT_URL are correct
  • Check if database is accessible
  • Ensure SSL mode is set correctly

2. Image Upload Fails

  • Verify BLOB_READ_WRITE_TOKEN is set
  • Check Vercel Blob store is connected
  • Ensure token has read/write permissions

3. Authentication Not Working

  • Verify Clerk keys are correct
  • Check middleware configuration
  • Ensure Clerk app is properly configured

4. Stripe Payment Fails

  • Verify Stripe keys are correct
  • Check API route is accessible
  • Ensure return URL is correct

5. Build Fails

  • Run npx prisma generate before build
  • Check all environment variables are set
  • Verify all dependencies are installed

🀝 Contributing

Contributions are welcome! To contribute:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

This project is open source and available under the MIT License.


πŸ‘€ Author

Arnob Mahmud


πŸ™ Acknowledgments


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 beautifully designed, high-performance e-commerce platform built with Next.js 14, TypeScript, Prisma, NeonDB, Vercel Blob Storage, Clerk authentication, Stripe payments, and shadcn/ui. Next Store offers a seamless online shopping experience with fast checkout, secure payments, and a curated selection of products.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •