Next.js 15 e-commerce app (storefront + admin dashboard) built with TypeScript, Prisma, and PostgreSQL.
- Storefront: product listing, product detail, cart, checkout (Xendit Payment Request)
- Admin: products, categories, brands, locations, orders, customers
- Auth: Lucia sessions (superadmin + customer)
- Image uploads: local storage under
public/uploads/*(gitignored)
- Next.js 15 (App Router) + React 19
- TypeScript
- Prisma + PostgreSQL
- Lucia Auth
- Tailwind CSS + Radix UI (shadcn/ui)
- Zod validation
- Xendit (
xendit-node) - oxlint / oxfmt (lint/format)
pnpm installCreate .env from .env.example.
Required:
DATABASE_URLXENDIT_SECRET_KEYNEXT_PUBLIC_REDIRECT_URL
Recommended:
XENDIT_WEBHOOK_CALLBACK_TOKEN(validate webhook requests)
Optional:
NEXT_PUBLIC_FAILURE_RETURN_URL
pnpm prisma migrate devOptional seed:
pnpm prisma:seedpnpm devOpen http://localhost:3000.
The app exposes:
POST /api/order/status
This endpoint:
- Accepts
reference_id/referenceId(also supports nesteddata.reference_id/data.referenceId) - Updates the
order.statusby matchingorder.code - If
XENDIT_WEBHOOK_CALLBACK_TOKENis set, it requires headerx-callback-tokento match - Ignores unsupported events (expects
payment.succeeded)
Configure your Xendit dashboard webhook URL to:
https://<your-domain>/api/order/status
pnpm dev: start dev serverpnpm build: build for productionpnpm start: run production serverpnpm lint: oxlintpnpm lint:fix: oxlint autofixpnpm format: oxfmt writepnpm type-check:tsc --noEmit
src/
app/ Next.js routes (App Router)
(admin)/ Admin dashboard
(customer)/ Storefront
api/ Route handlers
components/ Shared UI
lib/ Utilities (auth, prisma, uploads, xendit)
type/ Shared TS types