davide db6b727902 test: add component tests (Button, ProductCard) and test suite README
20 component tests covering Button (variants, disabled state, event handlers) and
ProductCard (rendering, price formatting, sale badge, image fallback). README
documents the full suite: 151 tests across 10 files, how to run, mock patterns,
and what's missing by priority (checkout flow, admin routes, more components).
2026-05-19 14:08:07 +02:00

E-commerce Platform

Piattaforma e-commerce containerizzata, avviabile con un singolo comando.

Stack: Next.js 14 · PostgreSQL 16 · Prisma · Stripe · Caddy · Docker Compose


Avvio in locale (test su localhost)

Prerequisiti

  • Docker Desktop installato e avviato
  • Porta 80 libera (nessun altro web server in esecuzione)

1. Clona il repository

git clone <url-repository>
cd ecommerce-platform

2. Crea il file .env

cp .env.example .env

Il file .env di default è già configurato per localhost. Non serve modificare nulla per i primi test.

3. Avvia la piattaforma

docker compose up -d

Il primo avvio richiede 510 minuti: Docker scarica le immagini, installa le dipendenze npm, compila Next.js, esegue le migrazioni e crea l'utente admin.

Segui il progresso con:

docker compose logs -f app

La piattaforma è pronta quando vedi:

✓ Ready in 91ms

4. Apri nel browser

URL Cosa trovi
http://localhost Sito pubblico (vetrina)
http://localhost/admin Dashboard amministratore
http://localhost:8025 Mailpit — cattura le email di test

5. Primo accesso admin

Vai su http://localhost/admin e accedi con:

Email:    admin@example.com
Password: Admin1234!test

Al primo accesso il sistema ti obbliga a cambiare la password.

Requisiti password: minimo 12 caratteri, almeno una maiuscola, una minuscola, un numero e un simbolo.

6. Configura il negozio (ordine consigliato)

  1. Product Types → crea un tipo di prodotto (es. "Prodotto") con gli attributi che vuoi
  2. Categories → crea le categorie
  3. Products → crea un prodotto, assegna tipo e categoria, impostalo su Published
  4. Apri http://localhost → il prodotto appare in homepage

7. Cosa funziona in locale senza configurazione extra

Funzionalità Stato
Admin dashboard completa
Gestione prodotti, categorie, ordini
Registrazione e login clienti
Email (reset password, ecc.) visibili su http://localhost:8025
Pagamenti Stripe ⚠️ richiede chiavi reali (vedi sotto)

Per testare i pagamenti Stripe in locale, inserisci una chiave sk_test_... reale nel .env (gratuita, modalità test su dashboard.stripe.com):

STRIPE_SECRET_KEY=sk_test_la_tua_chiave

Poi riavvia l'app:

docker compose restart app

8. Ferma la piattaforma

docker compose down          # ferma i container, i dati restano
docker compose down -v       # ferma e cancella anche il database

Differenze tra localhost e produzione

Quattro cose cambiano quando si passa da localhost a un dominio reale.

1 — Dominio e HTTPS

Modificare una sola riga nel Caddyfile:

# localhost
localhost { ... }

# produzione
tuodominio.com { ... }

Caddy ottiene e rinnova automaticamente il certificato HTTPS tramite Let's Encrypt. Non serve nessuna configurazione SSL manuale.

2 — Variabili d'ambiente

Cinque variabili da aggiornare nel .env:

Variabile Localhost Produzione
APP_URL http://localhost https://tuodominio.com
AUTH_SECRET qualsiasi stringa openssl rand -hex 32
STRIPE_SECRET_KEY sk_test_... (gratuita) sk_live_...
STRIPE_WEBHOOK_SECRET opzionale obbligatorio
SMTP_* Mailpit locale (porta 8025) provider reale (Resend, Mailgun, SendGrid…)

3 — Server

Serve un VPS Linux con Docker installato (DigitalOcean, Hetzner, OVH, ecc.) e il record DNS del dominio puntato all'IP del server. Il comando di avvio è identico: docker compose up -d.

4 — Backup

In locale i dati si perdono con docker compose down -v. In produzione è necessario un backup automatico del database (vedi sezione Backup database) e conservare il volume uploads che contiene le immagini dei prodotti.


Deploy in produzione

Prerequisiti

  • Server Linux con Docker e Docker Compose v2 (qualsiasi VPS o cloud VM)
  • Dominio con record A puntato all'IP del server
  • Porte 80 e 443 aperte nel firewall del server
  • Account Stripe (per i pagamenti reali)
  • Account SMTP (per le email: Mailgun, Resend, SendGrid, ecc.)

1. Clona il repository sul server

git clone <url-repository>
cd ecommerce-platform

2. Crea e configura .env

cp .env.example .env
nano .env

Modifica questi valori:

# URL pubblico del sito — con https://
APP_URL=https://tuodominio.com

# Genera un segreto casuale: openssl rand -hex 32
AUTH_SECRET=incolla_qui_il_risultato_di_openssl

# Credenziali del primo admin — cambia subito dopo il primo accesso
INITIAL_ADMIN_EMAIL=admin@tuodominio.com
INITIAL_ADMIN_PASSWORD=UnaPasswordSicura1!

# Stripe — usa le chiavi live (non sk_test_)
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxx

# SMTP reale per le email
SMTP_HOST=smtp.tuoprovider.com
SMTP_PORT=587
SMTP_USER=user@tuodominio.com
SMTP_PASSWORD=la_tua_password_smtp
SMTP_FROM=noreply@tuodominio.com

DATABASE_URL non va modificato: usa già il nome del container Docker corretto.

3. Genera AUTH_SECRET

openssl rand -hex 32

Copia l'output nel campo AUTH_SECRET nel file .env.

4. Configura il dominio nel Caddyfile

Apri Caddyfile e sostituisci localhost con il tuo dominio:

tuodominio.com {
    handle /uploads/* {
        root * /srv
        file_server
    }
    encode gzip zstd
    reverse_proxy app:3000
}

Caddy ottiene e rinnova automaticamente il certificato HTTPS tramite Let's Encrypt. Non serve nessuna configurazione SSL manuale.

5. Avvia

docker compose up -d

Attendi che l'app sia pronta:

docker compose logs -f app
# attendi: ✓ Ready in ...ms

Il sito è live su https://tuodominio.com.

6. Configura il webhook Stripe

Nel dashboard Stripe → Webhooks, aggiungi un endpoint:

URL endpoint:  https://tuodominio.com/api/webhooks/stripe

Eventi da ascoltare:
  - checkout.session.completed
  - payment_intent.succeeded
  - payment_intent.payment_failed

Copia il Signing secret (whsec_...) nel .env come STRIPE_WEBHOOK_SECRET, poi:

docker compose restart app

7. Primo accesso e configurazione negozio

  1. Vai su https://tuodominio.com/admin
  2. Accedi con le credenziali del .env
  3. Cambia la password quando richiesto
  4. Configura il negozio in questo ordine:
    • Settings → nome negozio, logo, colori
    • Product Types → tipi di prodotto con attributi personalizzati
    • Categories → categorie prodotto
    • Products → aggiungi i tuoi prodotti
    • Admin Users → aggiungi altri amministratori se necessario

Porte di rete

Porte da aprire nel firewall del server (produzione)

Porta Protocollo Servizio Perché è necessaria
80 TCP Caddy (HTTP) Redirect automatico HTTP → HTTPS e rinnovo certificati Let's Encrypt (ACME challenge)
443 TCP Caddy (HTTPS) Traffico web principale — sito pubblico e pannello admin

Solo queste due porte devono essere aperte verso l'esterno. Tutto il resto è interno a Docker.

Porte interne (rete Docker — non esporre al pubblico)

Porta Servizio Note
3000 Next.js (app) Accessibile solo da Caddy tramite reverse_proxy app:3000
5432 PostgreSQL (db) Accessibile solo dall'app tramite DATABASE_URL
1025 Mailpit SMTP Accessibile solo dall'app per l'invio email

Queste porte non sono pubblicate nel docker-compose.yml (exposeports) e non raggiungibili dall'esterno del server.

Porta solo per sviluppo locale (non aprire in produzione)

Porta Servizio Note
8025 Mailpit UI Interfaccia web per ispezionare le email di test — non deve mai essere esposta in produzione

Riepilogo comandi firewall (UFW — Ubuntu/Debian)

# Abilita solo HTTP e HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Blocca esplicitamente Mailpit dall'esterno (già bloccata di default se non aperta)
sudo ufw deny 8025/tcp

sudo ufw enable
sudo ufw status

Aggiornamenti

git pull
docker compose build app
docker compose up -d

Le migrazioni del database vengono applicate automaticamente all'avvio.


Backup database

Dump manuale:

docker compose exec db pg_dump -U ecommerce ecommerce > backup_$(date +%Y%m%d_%H%M%S).sql

Ripristino:

cat backup_XXXXXXXX_XXXXXX.sql | docker compose exec -T db psql -U ecommerce ecommerce

Backup automatico giornaliero (aggiungi al crontab del server con crontab -e):

0 3 * * * cd /percorso/ecommerce-platform && docker compose exec -T db pg_dump -U ecommerce ecommerce | gzip > /backups/ecommerce_$(date +\%Y\%m\%d).sql.gz

Problemi comuni

Il build impiega molto tempo al primo avvio È normale. npm install + compilazione Next.js richiedono 510 minuti la prima volta. I build successivi sono molto più veloci grazie alla cache Docker.

http://localhost non risponde (502 Bad Gateway) L'app è ancora in fase di avvio. Aspetta qualche secondo e ricarica. Controlla lo stato con:

docker compose logs -f app

Errore "port 80 already in use" Un altro servizio usa la porta 80 (Apache, Nginx, ecc.). Fermalo o cambia la porta nel docker-compose.yml.

Dimentico la password admin Resetta direttamente nel database:

# genera hash bcrypt per la nuova password
docker compose exec app node -e "
const bcrypt = require('bcryptjs');
bcrypt.hash('NuovaPassword1!', 12).then(h => console.log(h));
"
# aggiorna nel db
docker compose exec db psql -U ecommerce ecommerce -c \
  "UPDATE \"User\" SET \"passwordHash\"='HASH_QUI', \"mustChangePassword\"=true WHERE email='admin@example.com';"

Struttura del progetto

ecommerce-platform/
├── docker-compose.yml       Orchestrazione: db, app, caddy, mailpit
├── Caddyfile                Reverse proxy — modifica qui il dominio
├── .env                     Variabili d'ambiente (non committare)
├── .env.example             Template da copiare
└── app/
    ├── Dockerfile           Build multi-stage Next.js
    ├── entrypoint.sh        Sequenza avvio: migrazioni → admin → server
    ├── prisma/
    │   └── schema.prisma    Schema database completo
    ├── scripts/
    │   └── bootstrap-admin.ts  Crea il primo OWNER se non esiste
    └── src/
        ├── app/             Pagine Next.js (App Router)
        │   ├── admin/       Dashboard admin (protetta per ruolo)
        │   ├── api/         API routes (auth, prodotti, ordini, webhook)
        │   └── (storefront) Homepage, catalogo, carrello, checkout
        ├── components/      Componenti React riutilizzabili
        └── lib/             Auth, Prisma client, Stripe, email

Variabili d'ambiente

Variabile Descrizione Locale Produzione
APP_URL URL pubblico del sito http://localhost https://tuodominio.com
DATABASE_URL Connessione PostgreSQL invariato invariato
AUTH_SECRET Segreto sessioni (min 32 char) qualsiasi openssl rand -hex 32
INITIAL_ADMIN_EMAIL Email primo admin qualsiasi la tua email
INITIAL_ADMIN_PASSWORD Password primo admin qualsiasi sicura
STRIPE_SECRET_KEY Chiave Stripe sk_test_... sk_live_...
STRIPE_WEBHOOK_SECRET Segreto webhook Stripe opzionale obbligatorio
SMTP_HOST Server SMTP mailpit provider reale
SMTP_PORT Porta SMTP 1025 587
SMTP_USER Utente SMTP vuoto obbligatorio
SMTP_PASSWORD Password SMTP vuoto obbligatorio
SMTP_FROM Mittente email qualsiasi noreply@tuodominio.com
S
Description
No description provided
Readme 1 MiB
Languages
TypeScript 98.7%
Dockerfile 0.6%
Shell 0.5%
JavaScript 0.2%