115 lines
4.9 KiB
Markdown
115 lines
4.9 KiB
Markdown
# CLAUDE.md
|
|||
|
|
|
||
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
|
|
||
|
|
## Interazione
|
||
|
|
|
||
|
|
- L'utente scrive in italiano. **Rispondi in italiano.**
|
||
|
|
- Codice, commenti, nomi di variabili, commit message, log e documentazione tecnica: **in inglese.**
|
||
|
|
- Nei commit **non aggiungere `Co-Authored-By: Claude`** né altri trailer di attribuzione.
|
||
|
|
|
||
|
|
## Stato
|
||
|
|
|
||
|
|
Repository a **stato bootstrap**: contiene solo questo file. Tutto ciò che segue descrive il
|
||
|
|
target, non l'esistente. Verifica sempre cosa esiste prima di assumere.
|
||
|
|
|
||
|
|
Ordine di costruzione:
|
||
|
|
|
||
|
|
1. `frontend/` — Nuxt 4 (`npx nuxi@latest init frontend --package-manager npm --no-install-git`)
|
||
|
|
2. `cms/` — Strapi 5 (`npx create-strapi@latest cms --typescript --dbclient=postgres --no-example --no-git-init`)
|
||
|
|
3. `docker-compose.yml` + `.env.example` — Postgres, cms, frontend
|
||
|
|
4. Content types Strapi + permessi ruolo Public (solo `find`/`findOne`)
|
||
|
|
5. Client Strapi in Nuxt + pagine blog
|
||
|
|
6. `caddy/Caddyfile` + hardening
|
||
|
|
|
||
|
|
## Architettura
|
||
|
|
|
||
|
|
```text
|
||
|
|
Browser → Caddy ─┬─ dominio pubblico → Nuxt 4 (SSR) → REST Strapi
|
||
|
|
└─ sottodominio CMS → Strapi 5 → PostgreSQL
|
||
|
|
```
|
||
|
|
|
||
|
|
- Strapi è la **sola** fonte di verità editoriale. Niente altro backend (no Express/Nest/Fastify):
|
||
|
|
se serve logica server, sta in Nitro (`frontend/server/`) o in un controller Strapi.
|
||
|
|
- I visitatori pubblici non si autenticano mai. Solo editor/admin usano l'auth Strapi.
|
||
|
|
- Nuxt parla con Strapi **server-side** (`STRAPI_URL` interno Docker). Il token privilegiato non
|
||
|
|
raggiunge mai il browser: se serve, sta in `runtimeConfig` (non `public`).
|
||
|
|
- Postgres non è esposto pubblicamente. Media su volume persistente, mai binari nel DB.
|
||
|
|
|
||
|
|
## Comandi
|
||
|
|
|
||
|
|
Package manager: quello del lockfile. Se non esiste ancora → `npm`.
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# frontend/
|
||
|
|
npm run dev # dev server
|
||
|
|
npm run build # build produzione
|
||
|
|
npm run typecheck # nuxi typecheck — obbligatorio prima di dichiarare fatto
|
||
|
|
npm run lint
|
||
|
|
|
||
|
|
# cms/
|
||
|
|
npm run develop # Strapi con content-type builder attivo
|
||
|
|
npm run build # admin panel
|
||
|
|
npm run start # produzione
|
||
|
|
|
||
|
|
# stack
|
||
|
|
docker compose up -d --build
|
||
|
|
docker compose logs -f cms
|
||
|
|
```
|
||
|
|
|
||
|
|
Nessun test framework è ancora configurato. Se ne aggiungi uno, documenta qui il comando per
|
||
|
|
lanciare **un singolo test**.
|
||
|
|
|
||
|
|
## Modelli di contenuto
|
||
|
|
|
||
|
|
| Type | Campi |
|
||
|
|
|---|---|
|
||
|
|
| Article | title, slug (UID da title), excerpt, content (rich text), cover, author (rel), category (rel), tags (rel n:n), publishedDate, seoTitle, seoDescription, seoImage |
|
||
|
|
| Category | name, slug |
|
||
|
|
| Tag | name, slug |
|
||
|
|
| Author | name, biography, image |
|
||
|
|
|
||
|
|
Draft & Publish attivo su Article. Le URL pubbliche usano lo **slug**, mai l'id numerico.
|
||
|
|
|
||
|
|
## Frontend
|
||
|
|
|
||
|
|
Rotte: `/`, `/blog`, `/blog/[slug]`, `/category/[slug]`.
|
||
|
|
|
||
|
|
- SSR o prerender per tutto ciò che è indicizzabile. Mai pagine blog client-only senza motivo scritto.
|
||
|
|
- `<script setup lang="ts">`, Composition API. Convenzioni Nuxt standard (`pages/`, `components/`,
|
||
|
|
`composables/`, `layouts/`, `server/`).
|
||
|
|
- Un solo punto di accesso a Strapi: un composable/util tipizzato. Non sparpagliare `$fetch` nelle pagine.
|
||
|
|
- Tipizza esplicitamente il confine API. Niente `any` — `unknown` + narrowing.
|
||
|
|
- Query Strapi: richiedi solo i campi e le relazioni che servono (`fields`, `populate` mirati).
|
||
|
|
Gestisci sempre 404, lista vuota, errore API.
|
||
|
|
- Ogni articolo indicizzabile: title unico, meta description, canonical, Open Graph, JSON-LD
|
||
|
|
`BlogPosting`, gerarchia heading semantica. Il contenuto deve esistere nell'HTML server-rendered.
|
||
|
|
- Accessibilità non negoziabile: focus visibile, input etichettati, alt significativi, link
|
||
|
|
descrittivi, navigazione da tastiera.
|
||
|
|
|
||
|
|
Il riferimento Hostinger è solo ispirazione visiva. Non copiare codice o asset.
|
||
|
|
|
||
|
|
## Priorità
|
||
|
|
|
||
|
|
Correttezza e integrità dati → sicurezza → semplicità → SEO/a11y → performance.
|
||
|
|
|
||
|
|
Nessuna dipendenza, astrazione o servizio senza un bisogno concreto e attuale. Preferisci i
|
||
|
|
built-in Strapi al reimplementare funzioni CMS in Nuxt.
|
||
|
|
|
||
|
|
## Vincoli
|
||
|
|
|
||
|
|
- Mai committare `.env`, segreti, token, credenziali, chiavi. Mantieni `.env.example` sanificato.
|
||
|
|
- Mai hard-codare domini di produzione, URL privilegiati o credenziali. Vanno in env var.
|
||
|
|
- Non indebolire auth, CORS, TLS o security header per comodità. Least privilege sui ruoli Strapi.
|
||
|
|
- Richiedono **approvazione esplicita**: operazioni distruttive, migrazioni irreversibili, modifiche
|
||
|
|
a dati o configurazione di produzione, cambi di credenziali.
|
||
|
|
- Non riformattare file non correlati, non fare refactor collaterali, non riscrivere la history,
|
||
|
|
non force-push.
|
||
|
|
- Le decisioni architetturali di questo file non si cambiano in silenzio: spiega il trade-off prima.
|
||
|
|
|
||
|
|
## Prima di dichiarare completo
|
||
|
|
|
||
|
|
Lint → test → typecheck → build dell'app toccata, con gli script del `package.json` relativo.
|
||
|
|
Non affermare che un check è passato se non l'hai eseguito. Chiudi riassumendo cosa è cambiato e
|
||
|
|
quali rischi restano aperti.
|