- Document Editorial Fresh design system (fonts, colors, classes) - Add basePath gotchas for middleware and email redirect - Update phase 1 status with design system note Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.2 KiB
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
// 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: truein next.config.ts - Aggiungere location esplicita in 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:
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):
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:
# 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:
// 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():
// 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:
// 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/callbackhttps://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
# 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 |
.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
/* 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
- Niente bordi arrotondati - Stile editoriale con angoli vivi
- Tipografia forte - Fraunces per impatto, DM Sans per leggibilità
- Spazio generoso - Padding abbondante, respiro tra elementi
- Accent limitato - Corallo usato con parsimonia per CTA e emphasis
- Animazioni sottili - fade-up on load, transizioni 200ms
Come Mantenere Coerenza
Quando crei nuove pagine/componenti:
- Usa
font-displayper tutti i titoli - Usa le classi
text-*ebg-*del design system - Bottoni principali con
variant="default"(nero → accent on hover) - Form inputs senza border-radius
- Ogni sezione inizia con
editorial-tag+ titolofont-display
Stato Fasi
- 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