2026-05-18 15:25:38 +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 ](https://docs.docker.com/get-docker/ ) installato e avviato
- Porta **80 ** libera (nessun altro web server in esecuzione)
### 1. Clona il repository
``` bash
git clone <url-repository>
cd ecommerce-platform
```
### 2. Crea il file `.env`
``` bash
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
``` bash
docker compose up -d
```
Il primo avvio richiede **5– 10 minuti ** : Docker scarica le immagini, installa le dipendenze npm, compila Next.js, esegue le migrazioni e crea l'utente admin.
Segui il progresso con:
``` bash
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 ](https://dashboard.stripe.com/test/apikeys )):
``` env
STRIPE_SECRET_KEY = sk_test_la_tua_chiave
```
Poi riavvia l'app:
``` bash
docker compose restart app
```
### 8. Ferma la piattaforma
``` bash
docker compose down # ferma i container, i dati restano
docker compose down -v # ferma e cancella anche il database
```
---
2026-05-18 17:55:09 +02:00
## 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 ](#backup-database )) e conservare il volume `uploads` che contiene le immagini dei prodotti.
---
2026-05-18 15:25:38 +02:00
## 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 ](https://stripe.com ) (per i pagamenti reali)
- Account SMTP (per le email: Mailgun, Resend, SendGrid, ecc.)
### 1. Clona il repository sul server
``` bash
git clone <url-repository>
cd ecommerce-platform
```
### 2. Crea e configura `.env`
``` bash
cp .env.example .env
nano .env
```
Modifica questi valori:
``` env
# 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`
``` bash
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 {
2026-05-18 17:55:09 +02:00
handle /uploads/* {
root * /srv
file_server
}
2026-05-18 15:25:38 +02:00
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
``` bash
docker compose up -d
```
Attendi che l'app sia pronta:
``` bash
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 ](https://dashboard.stripe.com/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:
``` bash
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
---
## Aggiornamenti
``` bash
git pull
docker compose build app
docker compose up -d
```
Le migrazioni del database vengono applicate automaticamente all'avvio.
---
## Backup database
**Dump manuale: **
``` bash
docker compose exec db pg_dump -U ecommerce ecommerce > backup_$( date +%Y%m%d_%H%M%S) .sql
```
**Ripristino: **
``` bash
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` ):
``` bash
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 5– 10 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:
``` bash
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:
``` bash
# 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` |