# 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 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 ``` --- ## 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. --- ## 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 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 { 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 ```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` |