# Leopost - Note di Progetto ## Panoramica Social media manager potenziato dall'AI. Gestisce post su multiple piattaforme social. **URL Live:** https://lab.mlhub.it/leopost/ **Repository:** https://git.mlhub.it/Michele/leopost **Supabase Project:** `cizyzbdylxxjjhgnvyub` ## Stack Tecnico - **Frontend:** Next.js 16 con App Router - **Auth:** Supabase Auth (Email/Password + Google OAuth) - **Database:** Supabase Cloud PostgreSQL - **Deployment:** Docker su VPS con nginx reverse proxy ## Configurazione Critica ### Next.js per Subpath Deployment ```typescript // next.config.ts const nextConfig: NextConfig = { basePath: '/leopost', trailingSlash: true, }; ``` ### Variabili Ambiente (.env su VPS) ``` SUPABASE_URL=https://cizyzbdylxxjjhgnvyub.supabase.co SUPABASE_ANON_KEY=... SUPABASE_SERVICE_ROLE_KEY=... APP_URL=https://lab.mlhub.it/leopost ``` --- ## Problemi Riscontrati e Soluzioni ### 1. Build OOM (Out of Memory) **Problema:** Build Next.js killed durante `npm run build` con 512MB RAM limit. **Soluzione:** Aumentare memory limit in docker-compose.yml a 1024MB. ### 2. Redirect Loop HTTP/HTTPS **Problema:** `/leopost` senza trailing slash causava loop redirect e downgrade a HTTP. **Soluzione:** - Aggiungere `trailingSlash: true` in next.config.ts - Aggiungere location esplicita in nginx: ```nginx location = /leopost { return 301 https://$host/leopost/; } ``` ### 3. Middleware Intercetta Tutte le Route **Problema:** Homepage bianca perché il middleware Next.js intercettava anche le pagine statiche. **Soluzione:** Limitare il matcher del middleware solo alle route che richiedono auth check: ```typescript export const config = { matcher: [ '/dashboard/:path*', '/settings/:path*', '/subscription/:path*', '/login', '/login/', '/register', '/register/', ], } ``` **NON includere:** `/`, `/auth/:path*`, pagine statiche pubbliche. ### 4. OAuth 502 Bad Gateway - Header Troppo Grandi (CRITICO) **Problema:** Google OAuth callback restituiva 502 Bad Gateway. **Causa:** Supabase Auth setta cookie JWT molto grandi (~4KB) nella risposta. I buffer nginx di default sono troppo piccoli. **Soluzione - ENTRAMBI i livelli nginx richiedono configurazione:** **A) lab-router** (`/opt/lab-router/projects/leopost.conf`): ```nginx location /leopost/ { proxy_pass http://lab-leopost-app:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header Connection ""; # CRITICO per Supabase Auth proxy_buffer_size 256k; proxy_buffers 8 256k; proxy_busy_buffers_size 512k; } ``` **B) NPM (Nginx Proxy Manager)** - file `/data/nginx/custom/server_proxy.conf`: ```nginx # Large buffer sizes for Supabase Auth JWT cookies proxy_buffer_size 256k; proxy_buffers 8 256k; proxy_busy_buffers_size 512k; ``` **Importante:** Il 502 può venire da ENTRAMBI i nginx nella catena: ``` Browser → NPM → lab-router → app ``` Se solo lab-router ha i buffer grandi ma NPM no, il 502 viene da NPM. ### 5. OAuth Redirect URL Errati **Problema:** Dopo Google auth, redirect a localhost o URL senza basePath. **Soluzione:** Usare `NEXT_PUBLIC_APP_URL` per costruire redirect URL dinamici: ```typescript // src/app/auth/callback/route.ts const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://lab.mlhub.it/leopost' return NextResponse.redirect(`${baseUrl}${next}`) ``` ### 6. Middleware Redirect Senza basePath **Problema:** Middleware redirect a `/login/` invece di `/leopost/login/` → 404. **Causa:** `new URL('/login/', request.url)` non include il basePath. **Soluzione:** Usare `request.nextUrl.clone()`: ```typescript // middleware.ts // ❌ SBAGLIATO const redirectUrl = new URL('/login/', request.url) // ✅ CORRETTO const redirectUrl = request.nextUrl.clone() redirectUrl.pathname = '/login/' return NextResponse.redirect(redirectUrl) ``` ### 7. Email Conferma Redirect Errato **Problema:** Link conferma email reindirizza a `lab.mlhub.it/auth/callback` senza basePath. **Causa:** `window.location.origin` non include basePath. **Soluzione:** Usare `NEXT_PUBLIC_APP_URL`: ```typescript // src/components/auth/register-form.tsx const appUrl = process.env.NEXT_PUBLIC_APP_URL || window.location.origin await supabase.auth.signUp({ email, password, options: { emailRedirectTo: `${appUrl}/auth/callback/`, } }) ``` --- ## Configurazione Supabase Dashboard ### Authentication > URL Configuration - **Site URL:** `https://lab.mlhub.it/leopost` - **Redirect URLs:** - `https://lab.mlhub.it/leopost/auth/callback` - `https://lab.mlhub.it/leopost/auth/callback/` ### Authentication > Providers > Google - Abilitare Google provider - Configurare Client ID e Client Secret da Google Cloud Console - Authorized redirect URI in Google: `https://cizyzbdylxxjjhgnvyub.supabase.co/auth/v1/callback` --- ## Comandi Utili ```bash # Deploy aggiornamenti cd "D:\Michele\Progetti\Claude\VPS echosystem\lab\leopost" git add . && git commit -m "Update" && git push origin main ssh mic@72.62.49.98 "cd /opt/lab-leopost && git pull && docker compose restart" # Verificare log container ssh mic@72.62.49.98 "docker logs --tail 50 lab-leopost-app" # Verificare log nginx lab-router ssh mic@72.62.49.98 "docker logs --tail 50 lab-router" # Verificare log NPM (per errori 502) ssh mic@72.62.49.98 "docker exec nginx-proxy-app-1 tail -30 /data/logs/proxy-host-8_error.log" ``` --- ## Design System: "Editorial Fresh" Il progetto usa un design system personalizzato chiamato "Editorial Fresh" - ispirato al design editoriale/magazine con tipografia forte e layout distintivo. ### Font | Tipo | Font | Uso | |------|------|-----| | Display | **Fraunces** | Titoli, heading (serif con carattere) | | Body | **DM Sans** | Testo, paragrafi, UI | ```css .font-display { font-family: var(--font-display); } .font-body { font-family: var(--font-body); } ``` ### Palette Colori | Nome | Valore | CSS Variable | Uso | |------|--------|--------------|-----| | Cream | `#FFFBF5` | `--color-cream` | Background principale | | Cream Dark | `#F5F0E8` | `--color-cream-dark` | Background secondario | | Ink | `#1A1A1A` | `--color-ink` | Testo principale, bottoni | | Ink Light | `#4A4A4A` | `--color-ink-light` | Testo secondario | | Ink Muted | `#7A7A7A` | `--color-ink-muted` | Testo disabilitato | | Accent | `#E85A4F` | `--color-accent` | CTA, elementi distintivi (corallo) | | Success | `#2D7A4F` | `--color-success` | Conferme | | Error | `#C53030` | `--color-error` | Errori | ### Classi Utility Custom ```css /* Testi */ .text-accent /* Corallo */ .text-muted /* Grigio chiaro */ .text-ink /* Nero */ .text-ink-light /* Grigio scuro */ /* Background */ .bg-cream /* Sfondo principale */ .bg-cream-dark /* Sfondo alternativo */ .bg-accent-light /* Sfondo accent leggero */ /* Elementi editoriali */ .editorial-tag /* Tag uppercase corallo (SOCIAL MEDIA MANAGER) */ .editorial-line /* Linea decorativa 60px × 3px corallo */ .card-editorial /* Card con barra accent in cima */ ``` ### Componenti | Componente | File | Note | |------------|------|------| | Button | `src/components/ui/button.tsx` | Varianti: default, outline, ghost, accent | | Input | `src/components/ui/input.tsx` | Bordi quadrati, focus nero | | Card Editorial | CSS class | Bordo top accent, padding 2rem | ### Principi di Design 1. **Niente bordi arrotondati** - Stile editoriale con angoli vivi 2. **Tipografia forte** - Fraunces per impatto, DM Sans per leggibilità 3. **Spazio generoso** - Padding abbondante, respiro tra elementi 4. **Accent limitato** - Corallo usato con parsimonia per CTA e emphasis 5. **Animazioni sottili** - fade-up on load, transizioni 200ms ### Come Mantenere Coerenza Quando crei nuove pagine/componenti: 1. Usa `font-display` per tutti i titoli 2. Usa le classi `text-*` e `bg-*` del design system 3. Bottoni principali con `variant="default"` (nero → accent on hover) 4. Form inputs senza border-radius 5. Ogni sezione inizia con `editorial-tag` + titolo `font-display` --- ## Stato Fasi - [x] **Fase 1:** Autenticazione (Email/Password + Google OAuth) + Design System - [ ] **Fase 2:** Dashboard e gestione account social - [ ] **Fase 3:** Creazione e scheduling post - [ ] **Fase 4:** Integrazione AI per generazione contenuti