DropDead E-commerce Codebase Guide
This skill provides guidance for working with the DropDead e-commerce codebase, a Next.js 15 application using App Router, Prisma ORM, PostgreSQL (Neon serverless), and shadcn/ui components.
What This Skill Does
Guides AI agents through the architecture, conventions, and commands for the DropDead e-commerce platform. Ensures correct patterns for database access, component structure, server actions, and type safety.
Instructions
1. Development Commands
**Starting the Application**
Run `npm run dev` to start the development server on port 3000Run `npm run build` to create a production buildRun `npm start` to start the production serverRun `npm run lint` to check code quality with ESLint**Database Operations**
Run `npx prisma generate` to generate Prisma Client after schema changesRun `npx prisma migrate dev` to create and apply database migrationsRun `npx prisma studio` to open the Prisma Studio GUI for database inspectionRun `npx prisma db seed` to populate the database with sample data from `db/seed.ts`Note: `npm run postinstall` automatically generates Prisma Client after package installation2. Project Architecture Understanding
**Directory Structure**
`src/app/` contains Next.js App Router pages and layouts (routing only, no business logic)`src/components/ui/` contains shadcn/ui primitive components (Button, Card, Sheet, etc.)`src/components/shared/` contains shared business components (Header, Product cards, etc.)`src/lib/actions/` contains server actions for data fetching (e.g., `product.actions.ts`)`src/lib/constants/` defines app-wide constants (APP_NAME, LATEST_PRODUCTS_LIMIT, etc.)`src/lib/utils.ts` provides utility functions (cn for classnames, convertToPlainObject, formatNumberWithDecimal)`src/lib/validators.ts` contains Zod schemas for runtime validation`src/types/` contains TypeScript type definitions`db/` (outside src/) contains Prisma client configuration and seed data`prisma/schema.prisma` defines the database schema**Path Aliases**
ALWAYS use `@/*` for imports mapping to `./src/*`Use `@/db/*` for database-related imports mapping to `./db/*`Example: `import prisma from '@/db/prisma'` (NOT `from '../../db/prisma'`)3. Database Access Pattern
**Critical: Prisma Client Import**
ALWAYS import Prisma client from `@/db/prisma`NEVER import directly from `@prisma/client`The client uses Neon serverless adapter with WebSocket configuration for edge compatibility**Prisma Extensions Applied**
The Prisma client automatically converts `Decimal` types to `string` for `price` and `rating` fieldsWhen passing Prisma objects to client components, use `convertToPlainObject()` from `@/lib/utils`This ensures serialization compatibility between server and client**Example Query**
```typescript
import prisma from '@/db/prisma'
import { convertToPlainObject } from '@/lib/utils'
const products = await prisma.product.findMany()
const plainProducts = products.map(convertToPlainObject)
```
4. Server Actions Pattern
**Creating Server Actions**
Place all data fetching functions in `src/lib/actions/` directoryAdd `'use server'` directive at the top of action filesReturn plain objects (NOT raw Prisma objects with Decimal types)Use Zod validators from `@/lib/validators.ts` for input validation**Example Server Action**
```typescript
'use server'
import prisma from '@/db/prisma'
import { convertToPlainObject } from '@/lib/utils'
export async function getLatestProducts() {
const data = await prisma.product.findMany({
take: LATEST_PRODUCTS_LIMIT,
orderBy: { createdAt: 'desc' }
})
return data.map(convertToPlainObject)
}
```
5. Component Patterns
**Server Components**
Server components can be async functionsFetch data directly using server actions or Prisma queriesWrap async content in `<Suspense>` with a custom `<Loading />` fallbackExample: `src/app/(root)/page.tsx` shows async server component pattern**Client Components**
Add `'use client'` directive at the top of files requiring client-side interactivityUse hooks (useState, useEffect, etc.) only in client componentsReceive data as props from server components (already serialized as plain objects)**Component Organization**
UI primitives (Button, Card, etc.) go in `src/components/ui/`Business components (Header, ProductCard, etc.) go in `src/components/shared/`Page-specific components can be colocated with their routes in `src/app/`6. Styling Conventions
**Tailwind CSS Usage**
Use the `cn()` utility from `@/lib/utils` to merge Tailwind classes conditionallyDark mode is configured via `next-themes` with ThemeProvider in root layoutshadcn/ui components use Class Variance Authority (CVA) for variant patterns**Example**
```typescript
import { cn } from '@/lib/utils'
<div className={cn(
"base-classes",
isActive && "active-classes",
className // allow prop overrides
)} />
```
7. Type Safety Practices
**TypeScript Configuration**
Strict mode is enabledUse custom types from `src/types/` for shared interfacesLeverage Zod schemas from `@/lib/validators.ts` for runtime validation**Prisma Types**
Import types from `@prisma/client` when needed: `import type { Product } from '@prisma/client'`Remember that `price` and `rating` are strings after Prisma extension transformation8. Database Schema Reference
**Product Model**
Primary key: `id` (UUID)Unique constraint: `slug` (used in URLs)Images: `images` (String array for multiple product images)Price: `price` (Decimal, auto-converted to string)Rating: `rating` (Decimal, auto-converted to string)Featured products: `isFeatured` (Boolean) and optional `banner` field9. Environment Variables
**Required in `.env`**
`DATABASE_URL` - PostgreSQL connection string (Neon serverless format)**Optional**
`NEXT_PUBLIC_APP_NAME` - Application name displayed in UI`NEXT_PUBLIC_APP_DESCRIPTION` - Meta description for SEO`SERVER_URL` - Base URL for the application`LATEST_PRODUCTS_LIMIT` - Number of products shown on homepage10. Common Tasks
**Adding a New Product Feature**
1. Update `prisma/schema.prisma` with new fields
2. Run `npx prisma migrate dev --name add_feature_name`
3. Update Zod validators in `src/lib/validators.ts`
4. Create/update server actions in `src/lib/actions/product.actions.ts`
5. Update TypeScript types if needed
6. Update UI components in `src/components/shared/`
**Creating a New Page**
1. Add a new route folder in `src/app/(root)/`
2. Create `page.tsx` as an async server component
3. Import server actions for data fetching
4. Wrap async content in `<Suspense>` with `<Loading />`
5. Use path aliases (`@/`) for all imports
Constraints
NEVER import Prisma client from `@prisma/client` - always use `@/db/prisma`ALWAYS use path aliases (`@/*` and `@/db/*`) for importsALWAYS use `convertToPlainObject()` when passing Prisma objects to client componentsALWAYS add `'use server'` directive to server action filesALWAYS add `'use client'` directive to components using React hooksDatabase schema changes MUST be followed by `npx prisma migrate dev`Server actions MUST return plain objects, not raw Prisma objectsExample Usage
**Scenario: Adding a new "featured products" section**
1. Create server action in `src/lib/actions/product.actions.ts`:
```typescript
'use server'
import prisma from '@/db/prisma'
import { convertToPlainObject } from '@/lib/utils'
export async function getFeaturedProducts() {
const data = await prisma.product.findMany({
where: { isFeatured: true },
take: 4
})
return data.map(convertToPlainObject)
}
```
2. Use in page component `src/app/(root)/page.tsx`:
```typescript
import { getFeaturedProducts } from '@/lib/actions/product.actions'
import ProductCard from '@/components/shared/product-card'
import { Suspense } from 'react'
import Loading from './loading'
export default async function HomePage() {
return (
<Suspense fallback={<Loading />}>
<FeaturedSection />
</Suspense>
)
}
async function FeaturedSection() {
const products = await getFeaturedProducts()
return (
<div className="grid grid-cols-4 gap-4">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
)
}
```