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.
- Live-Demo: https://store-next-beta.vercel.app/
- Features & Functionalities
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables Setup
- Database Setup
- API Endpoints
- Routes & Pages
- Components Guide
- Server Actions
- How It Works
- Reusing Components
- Deployment
- Keywords
- Educational Value
- Learning Resources
- Troubleshooting
- Contributing
- License
- Author
- Acknowledgments
-
ποΈ 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
- 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
- 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
- Clerk - Authentication and user management
- Stripe - Payment processing and checkout
- Vercel Blob Storage - Image and file storage
- Vercel - Hosting and deployment platform
- Zod - Schema validation
- ESLint - Code linting
- TypeScript - Static type checking
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 fileBefore you begin, ensure you have the following installed:
- Node.js 18.x or higher
- npm or yarn package manager
- Git for version control
- Clone the repository
git clone https://github.com/your-username/nextjs-store.git
cd nextjs-store- Install dependencies
npm install- Set up environment variables
Create .env and .env.local files in the root directory (see Environment Variables Setup section below).
- 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- Run the development server
npm run dev- Open your browser
Navigate to http://localhost:3000 to see the application.
This project requires several environment variables to function properly. Create two files: .env and .env.local in the root directory.
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"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"- Go to Neon Console
- Create a new project or select an existing one
- Go to Connection Details
- Copy the Pooled connection string β Use for
DATABASE_URL - 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"- Go to Clerk Dashboard
- Create a new application or select an existing one
- Go to API Keys section
- Copy Publishable Key β Use for
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY - Copy Secret Key β Use for
CLERK_SECRET_KEY - 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
- Go to Stripe Dashboard
- Navigate to Developers β API keys
- Copy Publishable key β Use for
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY - Copy Secret key β Use for
STRIPE_SECRET_KEY - For webhooks (optional):
- Go to Developers β Webhooks
- Create a webhook endpoint
- Copy the Signing secret β Use for
STRIPE_WEBHOOK_SECRET
- Go to Vercel Dashboard
- Select your project
- Navigate to Storage tab (top navigation)
- Click Create next to Blob
- Name your blob store (e.g.,
product-images) - Click Connect to connect it to your project
- The
BLOB_READ_WRITE_TOKENwill be automatically added to your Vercel environment variables - Copy the token from Vercel dashboard β Settings β Environment Variables
- Add it to your local
.env.localfile
Set NEXT_PUBLIC_WEBSITE_URL to your production domain:
NEXT_PUBLIC_WEBSITE_URL="https://your-domain.vercel.app/"- Never commit
.envor.env.localfiles 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
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
# 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 studiomodel 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
}The project includes two API routes for Stripe payment processing:
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();Confirms payment and updates order status after Stripe checkout completion.
Query Parameters:
session_id- Stripe checkout session ID
Response:
- Redirects to
/orderspage on success
How It Works:
- Retrieves the Stripe checkout session
- Updates order status to
isPaid: trueif payment is complete - Deletes the cart after successful payment
- Redirects user to orders page
/- 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/sales- Sales dashboard and analytics/admin/products- Product management list/admin/products/create- Create new product/admin/products/[id]/edit- Edit existing product
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).*)"],
};- Wrapper component for consistent page layout
- Usage:
<Container className="py-20">{children}</Container>
- Loading state component with skeleton UI
- Usage:
<LoadingContainer />
- Displays empty state messages
- Usage:
<EmptyList resourceName="products" />
- Consistent section heading component
- Usage:
<SectionTitle text="Featured Products" />
- Wrapper for form elements with consistent styling
- Usage:
<FormContainer title="Create Product">{form}</FormContainer>
- Reusable text input component
- Usage:
<FormInput name="name" label="Product Name" />
- Specialized input for price with currency formatting
- Usage:
<PriceInput name="price" label="Price" />
- Textarea component for longer text inputs
- Usage:
<TextAreaInput name="description" label="Description" />
- File input for image uploads
- Usage:
<ImageInput />
- Checkbox component with label
- Usage:
<CheckboxInput name="featured" label="Featured Product" />
- Container that handles product fetching and layout switching
- Usage:
<ProductsContainer layout="grid" search={searchTerm} />
- Grid layout for product display
- Usage:
<ProductsGrid products={products} />
- List layout for product display
- Usage:
<ProductsList products={products} />
- Button to toggle favorite status
- Usage:
<FavoriteToggleButton productId={productId} />
- Displays all items in the cart
- Usage:
<CartItemsList cartItems={cartItems} />
- Displays cart totals (subtotal, tax, shipping, total)
- Usage:
<CartTotals cart={cart} />
- Column components for cart item display
- Usage:
<FirstColumn name={name} image={image} />
- Displays all reviews for a product
- Usage:
<ProductReviews productId={productId} />
- Form component for submitting reviews
- Usage:
<SubmitReview productId={productId} />
- Individual review card component
- Usage:
<ReviewCard review={review} />
- Star rating display component
- Usage:
<Rating rating={4.5} />
- Main navigation bar component
- Usage: Automatically included in root layout
- Search input in navbar
- Usage: Included in Navbar
- Cart icon button with item count
- Usage: Included in Navbar
- Dark mode toggle button
- Usage: Included in Navbar
- Dropdown menu for navigation links
- Usage: Included in Navbar
These are shadcn/ui components. You can add more using:
npx shadcn-ui@latest add [component-name]Common components used:
Button- Styled button componentCard- Card container componentInput- Text input componentTable- Table componentToast- Toast notification systemSkeleton- Loading skeleton component
Server Actions are defined in utils/actions.ts. They handle all server-side data mutations.
const products = await fetchFeaturedProducts();
// Returns: Product[] - All products where featured: trueconst products = await fetchAllProducts({ search: "lamp" });
// Returns: Product[] - Filtered products by search termconst product = await fetchSingleProduct("product-uuid");
// Returns: Product - Single product or redirects if not found// Server action for creating a product
// Handles image upload, validation, and database insertion// Server action for updating product details// Server action for updating product image
// Handles old image deletion and new image upload// Server action for deleting a product
// Also deletes associated image from storageconst itemCount = await fetchCartItems();
// Returns: number - Number of items in cart// Server action for adding items to cart
// Creates cart if doesn't exist, updates totals// Server action for updating cart item quantity// Server action for removing item from cartconst favoriteId = await fetchFavoriteId({ productId });
// Returns: string | null - Favorite ID if exists// Server action for toggling favorite statusconst favorites = await fetchUserFavorites();
// Returns: Favorite[] with product data// Server action for creating a product reviewconst reviews = await fetchProductReviews("product-uuid");
// Returns: Review[] - All reviews for a productconst { rating, count } = await fetchProductRating("product-uuid");
// Returns: { rating: string, count: number }// Server action for deleting a review// Server action for creating an order
// Deletes unpaid orders, creates new orderconst orders = await fetchUserOrders();
// Returns: Order[] - All paid orders for userconst orders = await fetchAdminOrders();
// Returns: Order[] - All paid orders (admin only)- User visits the site
- Clerk middleware checks authentication status
- Protected routes require sign-in
- After sign-in, user session is maintained
- Admin routes check
ADMIN_USER_IDmatch
-
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
-
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
-
Delete Product:
- Product is deleted from database
- Associated image is deleted from storage
- Related favorites, reviews, and cart items are cascade deleted
- User adds product to cart
- Cart is created if doesn't exist
- Cart item is added or quantity updated
- Cart totals are recalculated (subtotal, tax, shipping, total)
- Cart persists across sessions per user
- User clicks checkout from cart
- Order is created with cart details
- Stripe checkout session is created via
/api/payment - User completes payment in embedded Stripe checkout
- After payment,
/api/confirmis called - Order status is updated to
isPaid: true - Cart is deleted
- User is redirected to orders page
- User selects image file
- File is validated (size, type)
- Image is uploaded to Vercel Blob Storage using
uploadImage() - Public URL is returned
- URL is stored in database
- Image is served from Vercel Blob CDN
- User views product page
- If user hasn't reviewed, review form is shown
- User submits rating and comment
- Review is validated and saved
- Product rating is recalculated
- Review appears on product page
Simply copy the component file and its dependencies:
# Example: Reusing the Container component
cp components/global/Container.tsx your-project/components/Check package.json for required packages:
npm install tailwind-merge clsxUpdate import paths to match your project structure:
// Before
import Container from "@/components/global/Container";
// After (if using different path)
import Container from "../components/Container";import Container from "@/components/global/Container";
export default function MyPage() {
return (
<Container className="py-20">
<h1>My Content</h1>
</Container>
);
}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>
);
}import ProductsGrid from "@/components/products/ProductsGrid";
export default async function ProductsPage() {
const products = await fetchProducts();
return <ProductsGrid products={products} />;
}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>
);
}Most components are designed to be reusable. To adapt them:
- Update Types: Modify TypeScript interfaces to match your data structure
- Update Actions: Replace server actions with your own data fetching logic
- Update Styling: Adjust Tailwind classes to match your design system
- Remove Dependencies: Remove Clerk-specific code if not using Clerk
- Push to GitHub
git add .
git commit -m "Ready for deployment"
git push origin main-
Import to Vercel
- Go to Vercel Dashboard
- Click Add New Project
- Import your GitHub repository
- Vercel will auto-detect Next.js
-
Configure Environment Variables
- Go to Settings β Environment Variables
- Add all variables from
.envand.env.local - Set for all environments (Production, Preview, Development)
-
Deploy
- Vercel will automatically deploy
- Your site will be live at
your-project.vercel.app
The project includes a custom build script:
{
"scripts": {
"build": "npx prisma generate && next build"
}
}This ensures Prisma Client is generated before building.
- 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)
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
This project demonstrates:
-
Modern Next.js Patterns:
- App Router architecture
- Server Components vs Client Components
- Server Actions for mutations
- API Routes for external integrations
-
Type Safety:
- TypeScript throughout
- Prisma type generation
- Zod schema validation
-
Database Design:
- Relational database modeling
- Cascade deletions
- Efficient queries
-
Authentication & Authorization:
- Clerk integration
- Protected routes
- Role-based access (admin)
-
Payment Integration:
- Stripe embedded checkout
- Payment confirmation flow
- Order management
-
File Storage:
- Vercel Blob Storage
- Image upload handling
- Public URL generation
-
UI/UX Best Practices:
- Responsive design
- Dark mode
- Loading states
- Error handling
- Form validation
-
Code Organization:
- Component reusability
- Separation of concerns
- Utility functions
- Type definitions
- Verify
DATABASE_URLandDIRECT_URLare correct - Check if database is accessible
- Ensure SSL mode is set correctly
- Verify
BLOB_READ_WRITE_TOKENis set - Check Vercel Blob store is connected
- Ensure token has read/write permissions
- Verify Clerk keys are correct
- Check middleware configuration
- Ensure Clerk app is properly configured
- Verify Stripe keys are correct
- Check API route is accessible
- Ensure return URL is correct
- Run
npx prisma generatebefore build - Check all environment variables are set
- Verify all dependencies are installed
Contributions are welcome! To contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is open source and available under the MIT License.
- Email: [email protected]
- Portfolio: https://arnob-mahmud.vercel.app/
- GitHub: @arnobt78
- Next.js - The React Framework
- Prisma - Next-generation ORM
- Clerk - Authentication
- Stripe - Payment processing
- shadcn/ui - Beautiful UI components
- Vercel - Hosting and deployment
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! π







