docs: update CLAUDE.md with Italian rule, error workflow, and full data model
Added Italian communication requirement, error-first workflow (report then wait), and missing Prisma models: ProductVariant, PasswordResetToken, Page/PageSection, SiteSettings, AuditLog. Added app/coverage/ to .gitignore.
This commit is contained in:
@@ -6,11 +6,15 @@
|
||||
# Node
|
||||
app/node_modules/
|
||||
node_modules/
|
||||
test/node_modules
|
||||
|
||||
# Next.js build output
|
||||
app/.next/
|
||||
app/out/
|
||||
|
||||
# Test coverage report
|
||||
app/coverage/
|
||||
|
||||
# Prisma generated client (rebuilt on npm install)
|
||||
app/node_modules/.prisma/
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## How to work with the user
|
||||
|
||||
Before implementing any new feature, **always discuss it first**: explain whether it makes sense professionally, how it is typically done in production e-commerce platforms, and propose alternatives if there is a better approach. Only proceed with implementation after the user confirms.
|
||||
|
||||
**Communicate in Italian.** The user speaks Italian — all responses, explanations, and questions must be in Italian.
|
||||
|
||||
**Error handling workflow:** When you find an error (in logs, code, or output), report what you found and stop. Do not propose or implement a fix until the user explicitly asks. Present: what the error is, where it occurs, and what likely caused it — then wait for instructions.
|
||||
|
||||
## Running the project
|
||||
|
||||
```bash
|
||||
# Start everything (first run takes a few minutes to build)
|
||||
docker compose up -d --build
|
||||
|
||||
# Check logs
|
||||
docker compose logs -f app
|
||||
|
||||
# Stop
|
||||
docker compose down
|
||||
```
|
||||
|
||||
The app is available at http://localhost. Admin panel at http://localhost/admin.
|
||||
Default credentials are in `.env` (`INITIAL_ADMIN_EMAIL` / `INITIAL_ADMIN_PASSWORD`).
|
||||
Test emails are visible at http://localhost:8025 (Mailpit).
|
||||
|
||||
## Development commands (run inside `app/`)
|
||||
|
||||
```bash
|
||||
npm run dev # local dev server (port 3000, no Docker)
|
||||
npm run build # production build
|
||||
npx prisma studio # visual DB browser
|
||||
npx prisma migrate dev --name <name> # create a new migration
|
||||
npx prisma migrate deploy # apply migrations (done automatically on container start)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
**Stack:** Next.js 14 App Router · PostgreSQL 16 · Prisma 5 · Stripe · Nodemailer · TailwindCSS · Zod · Docker + Caddy
|
||||
|
||||
**Source root:** `app/src/`
|
||||
|
||||
| Directory | Purpose |
|
||||
|---|---|
|
||||
| `app/api/` | REST API routes — one folder per resource |
|
||||
| `app/admin/` | Admin dashboard pages (role-gated at layout level) |
|
||||
| `app/(storefront)/` | Public-facing pages |
|
||||
| `components/` | Shared React components and UI primitives |
|
||||
| `lib/` | Core utilities (auth, email, storage, Stripe, validation, rate limiting) |
|
||||
| `context/` | Client-side UserContext |
|
||||
|
||||
## Key patterns
|
||||
|
||||
**API routes** follow a consistent shape: validate input with Zod → check auth/role via `getCurrentUser()` → query Prisma → return JSON. Copy an existing route as a starting point.
|
||||
|
||||
**Auth** is session-based (no NextAuth). `lib/auth.ts` handles token creation, hashing (SHA256), and the `getCurrentUser()` helper used in every protected route. Sessions expire after 30 days.
|
||||
|
||||
**Admin protection** is enforced in the admin layout: `CUSTOMER` role is blocked, `ADMIN` and `OWNER` are allowed. A `mustChangePassword` flag redirects new owners to a password-change page before anything else.
|
||||
|
||||
**Validation schemas** live in `lib/validate.ts` (Zod). Add new schemas there; never validate inline in routes.
|
||||
|
||||
**Image uploads** go through `lib/storage.ts`, which validates magic bytes (JPEG/PNG/WebP/ICO) before writing to `/app/public/uploads/<productId>/`. Uploads are stored in a named Docker volume (`uploads`) shared between the `app` and `caddy` containers.
|
||||
|
||||
**Emails** are sent via `lib/email.ts` (Nodemailer). Locally they land in Mailpit; in production, configure SMTP env vars.
|
||||
|
||||
**Rate limiting** is IP-based and backed by the `LoginAttempt` DB table (10 attempts / 15 min). Logic is in `lib/rate-limit.ts`.
|
||||
|
||||
## Data model (high level)
|
||||
|
||||
- **User** → has role (`CUSTOMER` / `ADMIN` / `OWNER`), sessions, orders, reviews
|
||||
- **Product** → belongs to one **ProductType** (defines the attribute schema), many-to-many with **Category**, has **MediaAsset**, **ProductVariant**, **Review**
|
||||
- **ProductType** → defines a JSON schema for product attributes (e.g. "clothing" has size/color)
|
||||
- **ProductVariant** → SKU, price, stock per variante (es. taglia/colore di un prodotto)
|
||||
- **Category** → hierarchical (self-referential `parentId`), many-to-many with Product
|
||||
- **Order** → status state machine (`PENDING → PAID → FULFILLED`, `CANCELLED`, `REFUNDED`), has **OrderItem** and **Payment**
|
||||
- **PasswordResetToken** → token hashed con scadenza per il flusso reset password
|
||||
- **Page** / **PageSection** → CMS minimale per pagine statiche (slug, titolo, sezioni JSON ordinate)
|
||||
- **SiteSettings** — key/value store for shop configuration (branding, etc.)
|
||||
- **AuditLog** — tracks admin actions
|
||||
|
||||
## Environment variables
|
||||
|
||||
Copy `.env.example` to `.env`. For production, generate a strong `AUTH_SECRET` with `openssl rand -hex 32` and replace all placeholder values. The `DATABASE_URL` uses the Docker service name `db` as host — do not change it for containerised deployments.
|
||||
|
||||
## Debugging
|
||||
|
||||
**Check app logs (first thing to do):**
|
||||
```bash
|
||||
docker compose logs -f app # live
|
||||
docker compose logs app --tail=100 # last 100 lines
|
||||
```
|
||||
|
||||
**Common error patterns to look for in logs:**
|
||||
- `EACCES: permission denied` → volume/filesystem permissions issue
|
||||
- `PrismaClientKnownRequestError` → DB constraint violation or bad query
|
||||
- `401 / 403` in API → session expired or role check failing
|
||||
- Silent form failures → always check `res.ok` in `fetch` calls; UI may show success even on API error
|
||||
|
||||
**API errors not surfacing in the UI** are almost always caused by a missing `res.ok` check in the frontend `fetch` call. The pattern to use in every form submit:
|
||||
```ts
|
||||
const res = await fetch('/api/...', { method: 'POST', ... })
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}))
|
||||
setError(data.error || `Errore (${res.status})`)
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
**Database inspection:**
|
||||
```bash
|
||||
# Open Prisma Studio (visual DB browser)
|
||||
cd app && npx prisma studio
|
||||
|
||||
# Or connect directly
|
||||
docker compose exec db psql -U ecommerce ecommerce
|
||||
```
|
||||
|
||||
**Rebuild after code changes:**
|
||||
```bash
|
||||
docker compose up -d --build app # rebuild only the app container
|
||||
```
|
||||
|
||||
**TypeScript errors in IDE but not in build:** likely a missing `node_modules` or stale tsconfig in the IDE. Run `npm install` inside `app/` and restart the IDE TypeScript server.
|
||||
|
||||
## Deployment
|
||||
|
||||
1. Point your domain DNS to the server.
|
||||
2. Set `APP_URL` to `https://yourdomain.com` in `.env`.
|
||||
3. Edit `Caddyfile`: replace `localhost` with your domain.
|
||||
4. `docker compose up -d --build`
|
||||
|
||||
Caddy handles TLS automatically via Let's Encrypt. Ports 80 and 443 must be open on the firewall.
|
||||
Reference in New Issue
Block a user