Document the stack, the dev workflow and the production deployment
README gets step-by-step instructions for both: secrets generation and the local stack on one side, DNS records, firewall, environment variables, TLS and backups on the other. CLAUDE.md records the decisions that are not visible in the code: why the browser never reaches Strapi, why the content model stays this small, and where the public permissions are granted.
This commit is contained in:
@@ -10,17 +10,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## 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
|
||||
Struttura, content type, pagine blog, Docker e Caddy sono in piedi. Restano da fare:
|
||||
sitemap e `robots.txt` dinamici, ricerca, e i test (nessun framework ancora configurato).
|
||||
|
||||
## Architettura
|
||||
|
||||
@@ -32,8 +23,15 @@ Browser → Caddy ─┬─ dominio pubblico → Nuxt 4 (SSR) → REST Strapi
|
||||
- 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`).
|
||||
- **Il browser non parla mai con Strapi.** Le pagine chiamano gli endpoint Nitro in
|
||||
`frontend/server/api/`, che sono l'unico posto dove si costruiscono query Strapi. Così
|
||||
`NUXT_STRAPI_URL` resta l'indirizzo interno Docker, niente CORS e niente token nel client.
|
||||
Se aggiungi una vista, aggiungi l'endpoint lì e tipizza il ritorno in `shared/types/blog.ts`.
|
||||
- Il Markdown dell'articolo è convertito in HTML **nell'endpoint**, non nel componente: il
|
||||
contenuto è già nell'HTML SSR e `marked` resta fuori dal bundle client.
|
||||
- `cms/src/index.ts` (`bootstrap`) dà al ruolo Public solo `find`/`findOne` su Article e Category,
|
||||
e disattiva la registrazione pubblica: non esistono utenti front-end, solo amministratori.
|
||||
Qualsiasi permesso in più va motivato.
|
||||
- Postgres non è esposto pubblicamente. Media su volume persistente, mai binari nel DB.
|
||||
|
||||
## Comandi
|
||||
@@ -52,11 +50,17 @@ npm run develop # Strapi con content-type builder attivo
|
||||
npm run build # admin panel
|
||||
npm run start # produzione
|
||||
|
||||
# stack
|
||||
# stack completo (con Caddy e domini reali)
|
||||
docker compose up -d --build
|
||||
docker compose logs -f cms
|
||||
|
||||
# stack locale senza domini né TLS: porte su localhost, niente Caddy
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build database cms frontend
|
||||
```
|
||||
|
||||
`docker-compose.dev.yml` va passato **sempre esplicitamente**: non è un `override.yml` proprio
|
||||
per non finire per sbaglio in produzione esponendo le porte.
|
||||
|
||||
Nessun test framework è ancora configurato. Se ne aggiungi uno, documenta qui il comando per
|
||||
lanciare **un singolo test**.
|
||||
|
||||
@@ -64,10 +68,13 @@ lanciare **un singolo test**.
|
||||
|
||||
| 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 |
|
||||
| Article | title, slug (UID da title), content (Markdown), cover, category (rel) |
|
||||
| Category | name, slug |
|
||||
| Tag | name, slug |
|
||||
| Author | name, biography, image |
|
||||
|
||||
Deliberatamente minimale: **niente Author** (l'unico autore è l'admin), niente tag, nessun campo
|
||||
SEO separato. La meta description è ricavata dall'inizio del body (`summarise` in
|
||||
`frontend/server/utils/strapi.ts`), la data è il `publishedAt` di Draft & Publish, l'immagine
|
||||
social è la cover. Non reintrodurre questi campi senza che servano davvero.
|
||||
|
||||
Draft & Publish attivo su Article. Le URL pubbliche usano lo **slug**, mai l'id numerico.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user