Synaplan
기업을 위한 오픈소스 AI 플랫폼
몇 분 만에 체크인·와이파·분리수거·숙박세·지역 안내까지 포함한 디지털 가이드를 만들고 5개 언어와 QR코드로 제공
Crea in pochi minuti una guida digitale per gli ospiti del tuo affitto breve: check-in, Wi-Fi, raccolta differenziata, tassa di soggiorno, consigli locali. Tradotta in 5 lingue, con QR code.
비즈니스TypeScript · PLpgSQLGitHub @jacoposta21-ux온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Web app SaaS per gli host italiani di affitti brevi (Airbnb, Booking): in pochi minuti crea una guida digitale per gli ospiti, tradotta e pensata per l'Italia, condivisibile tramite link e QR code.
Il nome dell'app si cambia con la variabile
NEXT_PUBLIC_APP_NAME.
| Fase | Contenuto | Stato |
|---|---|---|
| 1 | Struttura del progetto, database, autenticazione, dashboard | ✅ |
| 2 | Editor a sezioni, wizard, duplicazione, pagina pubblica /g/[slug], landing completa | ✅ |
| 3 | Generazione AI e traduzioni | ✅ |
| 4 | Pagamenti Stripe, QR code, cartello A5, statistiche | ✅ |
src/
app/
(auth)/login, (auth)/registrati accesso e registrazione (server action)
(app)/dashboard elenco guide dell'host (area protetta)
(app)/guide/nuova scelta: procedura guidata, AI, duplica
(app)/guide/nuova/wizard procedura guidata, una sezione alla volta
(app)/guide/[id]/modifica editor a sezioni con anteprima live su telefono
(app)/guide/[id]/pubblica pagamento, link, QR code, cartello A5, statistiche
api/stripe/webhook conferma dei pagamenti Stripe
api/guide/[id]/qr QR code in PNG
api/guide/[id]/cartello cartello A5 in PDF
g/[slug] guida pubblica per l'ospite (nessun login)
api/visite registrazione anonima delle visite
auth/callback ritorno da Google OAuth / conferma email
auth/esci logout
page.tsx landing page
components/
guide/ vista della guida (pubblica, anteprima, landing)
editor/ editor: form per sezione, consigli locali, impostazioni
wizard/ procedura guidata
ui/ pulsanti, campi, card, avvisi…
data/demo-guide.ts guida dimostrativa di Firenze (seed + landing)
lib/
supabase/ client browser, server, admin e refresh sessione
auth.ts requireHost(), redirect sicuri
guides.ts accesso ai dati delle guide
sections.ts catalogo sezioni e contenuti predefiniti italiani
i18n.ts testi dell'interfaccia in 5 lingue, scelta lingua, fusione traduzioni
guide-actions.ts Server Action: crea, salva, duplica, elimina guida
public-guide.ts lettura in cache della guida pubblica
upload.ts compressione (WebP, max 1600 px) e upload immagini
config.ts nome app, prezzo, URL del sito
types/
guide.ts tipi di dominio (contenuto di ogni sezione)
database.ts tipi delle tabelle Supabase
proxy.ts refresh sessione e protezione delle pagine riservate
supabase/migrations/ schema SQL, RLS, storage
scripts/seed.ts crea la guida demo
/guide/nuova/ai): l'host incolla il testo dell'annuncio e qualche dato
chiave; Claude restituisce, con output strutturato (schema Zod), il contenuto di tutte
le sezioni e qualche luogo consigliato. Il prompt vieta di inventare password, codici,
numeri e locali: i dati mancanti restano vuoti da completare.claude-opus-5-5 (in src/lib/ai.ts), con fallback lato server in caso di
rifiuto dei filtri di sicurezza. Effort medium per la generazione, low per la traduzione.ai_richieste, valori in src/lib/ai-actions.ts).maxDuration = 300 secondi: serve un
piano che lo consenta (sul piano Hobby il limite può essere più basso).Le guide non vengono mai indicizzate dai motori di ricerca (meta noindex e header
X-Robots-Tag), perché contengono password Wi-Fi e istruzioni per entrare in casa.
Il contenuto italiano definisce la struttura (quanti passi, quanti elettrodomestici…);
ogni traduzione contiene solo i testi. Quando una traduzione manca, l'ospite vede il
testo italiano. Alcuni campi sono uguali in tutte le lingue (password Wi-Fi, indirizzo,
colori dei contenitori, numeri di telefono, codice CIN): vedi CAMPI_CONDIVISI in
src/lib/i18n.ts.
unstable_cache) e invalidati a ogni salvataggio dell'editor.public/sw-guida.js) conserva le guide già aperte, che si
riaprono anche senza connessione.| Tabella | Contenuto |
|---|---|
hosts | profilo dell'host (creato automaticamente alla registrazione) |
guides | una guida per appartamento: slug, stato, pagata, colore, logo, copertina, lingue attive, contatto |
sections | sezioni della guida: tipo, ordine, attiva, contenuto (JSON per lingua: { "it": {...}, "en": {...} }) |
places | consigli locali con categoria, descrizione per lingua e link Google Maps |
payments | sessioni Stripe Checkout (scritte solo dal server) |
views | visite alla guida e alle singole sezioni |
Sicurezza (RLS): ogni host vede e modifica solo le proprie guide; le guide pubblicate e pagate sono leggibili da chiunque. Un trigger impedisce all'host di segnare da solo una guida come pagata: lo può fare solo il webhook Stripe (service role).
Requisiti: Node.js 20+ e un progetto Supabase (piano gratuito ok).
npm install
cp .env.example .env.local # poi compila le variabili
Nel pannello Supabase apri SQL Editor e incolla il contenuto di
supabase/migrations/20261026000000_schema_iniziale.sql, oppure con la CLI:
npx supabase link --project-ref <id-progetto>
npx supabase db push
Applica tutte le migrazioni in ordine (20261026…_schema_iniziale.sql,
20261027…_limiti_ai.sql, 20261028…_funzioni_private.sql). Creano tabelle, policy RLS, trigger, il bucket di storage
guide-media e il registro delle richieste AI.
In Supabase → Authentication → URL Configuration:
http://localhost:3000 (in produzione il tuo dominio)http://localhost:3000/auth/callback e https://tuodominio.it/auth/callbackPer l'accesso con Google: Authentication → Providers → Google, inserisci Client ID e
Secret creati su Google Cloud Console (redirect URI: https://<id-progetto>.supabase.co/auth/v1/callback).
npm run seed
Crea l'utente [email protected] (la password viene stampata a terminale, oppure
impostala con DEMO_PASSWORD) e la guida dimostrativa Casa Brunelleschi nel centro di
Firenze, su /g/demo-firenze.
Tariffe, orari ZTL e calendario della raccolta nella guida demo sono indicativi: verificali sempre sul sito del Comune prima di usarli in una guida reale.
sk_test_) in STRIPE_SECRET_KEY.https://<tuo-dominio>/api/stripe/webhookcheckout.session.completed, checkout.session.async_payment_succeeded,
checkout.session.async_payment_failed, checkout.session.expired, charge.refunded
(quest'ultimo rimette in bozza la guida dopo un rimborso totale)whsec_…) in STRIPE_WEBHOOK_SECRET.stripe listen --forward-to localhost:3000/api/stripe/webhook
(stampa un whsec_… temporaneo da mettere in .env.local). Carta di test: 4242 4242 4242 4242.Come funziona: l'host paga su Stripe Checkout (/guide/[id]/pubblica); il webhook, con la
chiave service role, segna la guida come pagata e pubblicata. Anche la pagina di
ritorno verifica la sessione con Stripe, quindi la guida si sblocca subito anche se il
webhook arriva in ritardo. Il trigger SQL impedisce a chiunque altro di segnare una guida
come pagata.
Fatturazione: Checkout non emette fatture. Se ti servono (in Italia di norma sì), attiva
invoice_creationinsrc/lib/payment-actions.ts, Stripe Tax o collega il tuo sistema di fatturazione elettronica.
Termini (/termini), privacy e cookie (/privacy), rimborsi (/rimborsi) e contatti
(/contatti) leggono i dati del titolare da queste variabili:
| Variabile | Esempio |
|---|---|
NEXT_PUBLIC_TITOLARE_NOME | Mario Rossi |
NEXT_PUBLIC_TITOLARE_SEDE | Firenze (facoltativa) |
NEXT_PUBLIC_TITOLARE_PIVA | facoltativa: compare solo se impostata |
NEXT_PUBLIC_EMAIL_CONTATTO | [email protected] |
I testi sono una base: falli rileggere da un professionista prima di vendere.
/admin mostra incassi, pagamenti, guide e host di tutta la piattaforma e permette di
mettere offline una guida. È accessibile solo agli utenti la cui email è in
ADMIN_EMAILS (variabile solo lato server, separata da virgola); per tutti gli altri la
pagina non esiste (404). I dati sono letti con la chiave service role, dopo il controllo.
npm run dev # http://localhost:3000
npm run typecheck # controllo TypeScript
npm run lint
| Variabile | Dove si trova | Note |
|---|---|---|
NEXT_PUBLIC_APP_NAME | — | nome mostrato nell'app |
NEXT_PUBLIC_SITE_URL | — | URL pubblico, usato per link e QR code |
NEXT_PUBLIC_PREZZO_GUIDA_CENTESIMI | — | prezzo di pubblicazione (default 2900 = 29 €) |
NEXT_PUBLIC_SUPABASE_URL | Supabase → Project Settings → API | |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | Supabase → Project Settings → API Keys | va bene anche la vecchia anon key |
SUPABASE_SERVICE_ROLE_KEY | Supabase → Project Settings → API Keys | segreta, solo lato server |
ANTHROPIC_API_KEY | console.anthropic.com | fase 3 |
STRIPE_SECRET_KEY | Stripe → Developers → API keys | fase 4 |
STRIPE_WEBHOOK_SECRET | Stripe → Developers → Webhooks | fase 4 |
NEXT_PUBLIC_SITE_URL = il dominio di produzione).https://<dominio>/auth/callback tra i Redirect URL di Supabase.