CRITICAL: Use bun, NOT npm or yarn or pnpm
- Install dependencies:
bun installorbun add <package> - Run scripts:
bun run <script> - Check lock file:
bun.lock(NOTpackage-lock.json)
This is a Bun project. Using npm will create package-lock.json and fuck everything up.
# Development server
bun run dev
# Production build
bun run build
# Linting
bun run lint
# Type checking (if available)
bun run typecheck/src/app/- Next.js app router pages/src/components/- React components/src/data/- Product data and types/src/lib/- Utilities, validation, Stripe/src/app/api/stripe/- Stripe API routes
- Framework: Next.js 16 (App Router)
- Package Manager: Bun
- Validation: Zod (schema-first, types derived from schemas)
- Payments: Stripe (with idempotency keys)
- Styling: Tailwind CSS
- UI Components: shadcn/ui
- Type Safety: All types should be derived from Zod schemas where possible (see
src/lib/validation.ts) - Error Handling: Use error IDs for server errors, return them to client for support
- Cart Validation: Cart items validated on client load and server API
- Stripe:
- Uses idempotency keys (UUID v4)
- Server validates product prices against catalog
- Environment variables in
.env.local
Required in .env.local:
STRIPE_SECRET_KEY- Stripe secret keyNEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY- Stripe publishable key (client-side)STRIPE_WEBHOOK_SECRET- For webhook verification
POST /api/stripe/payment-intent- Creates payment intent with validationPOST /api/stripe/webhook- Handles Stripe webhooks
Server:
const errorId = crypto.randomUUID();
console.error(`[ERROR ${errorId}] Message`, error);
return NextResponse.json({ error: "User message", errorId }, { status: 500 });Client:
if (data.errorId) {
showError(`${data.error} Error ID: ${data.errorId}`);
}