ConvertLabs
Prenotazioni online e marketing per chi lavora sul territorio
Incasso mensile: 28.000 USD (fonte indicata nella scheda)
Cosa fa
Software per attività locali di servizi: i clienti prenotano online, l'attività gestisce il calendario e manda promemoria e promozioni ai clienti.
Come guadagna
Abbonamento mensile per le attività.
Rendilo tuo
- Un solo settore: parrucchieri, centri estetici o officine, con funzioni su misura.
- Promemoria su WhatsApp invece che per email: in Italia funzionano molto meglio.
- Richiesta automatica della recensione Google dopo l'appuntamento.
Le frasi da scrivere all'AI
1. Base del sito e grafica
Crea un'app web in italiano chiamata "Prenotafacile": permette a parrucchieri, centri estetici e officine di ricevere prenotazioni online, con promemoria ai clienti e richiesta di recensione. Usa React, Vite, TypeScript e Tailwind CSS.
Pagine da creare:
1. Pagina iniziale per le attività, con vantaggi, esempio e prezzi
2. Registrazione e configurazione guidata dell'attività (servizi, orari, chiusure)
3. Pagina pubblica di prenotazione /:slug
4. Calendario settimanale dell'attività
5. Elenco clienti
Stile: fresco e semplice: sfondo bianco, accento turchese #0D9488, testo #0F172A, carattere "DM Sans", pulsanti degli orari grandi come piastrelle da toccare. Nessuna immagine generica di stock.
Tutto deve funzionare perfettamente da telefono. Tutti i testi in italiano, chiari e senza parole tecniche.
2. Database, account e sicurezza
Collega il progetto a Supabase e attiva la registrazione con email e password.
Crea queste tabelle:
- "attivita": nome, indirizzo pubblico (slug), telefono, orari di apertura, collegata al titolare
- "servizi": nome, durata in minuti, prezzo
- "prenotazioni": servizio, nome e telefono del cliente, inizio e fine, stato
Regole di sicurezza obbligatorie:
- la pagina dell'attività e i servizi sono pubblici
- chiunque può prenotare un orario libero, ma non vede le prenotazioni degli altri
- il database deve rendere impossibile prenotare due volte lo stesso orario
- solo il titolare vede e gestisce le prenotazioni
Usa esattamente il codice SQL che trovi nei "Dettagli tecnici" di questa scheda: eseguilo nel SQL Editor di Supabase prima di continuare, poi collega le pagine alle tabelle.
3. La pagina di prenotazione
Crea la pagina pubblica /:slug: nome, foto e indirizzo dell'attività, poi tre passaggi: (1) scegli il servizio, (2) scegli il giorno da un calendario delle prossime 3 settimane e un orario libero, mostrato come piastrelle, (3) nome, telefono ed eventuali note.
Gli orari liberi si calcolano da: orari di apertura, durata del servizio, prenotazioni esistenti e chiusure straordinarie. Se due clienti prenotano lo stesso orario nello stesso momento, il database accetta solo il primo (vincolo nei Dettagli tecnici) e il secondo vede "Questo orario è appena stato preso, scegline un altro".
Dopo la prenotazione: pagina di conferma con il pulsante "Aggiungi al calendario" e un link per annullare fino a 24 ore prima.
4. Calendario, promemoria e recensioni
Crea il calendario settimanale del titolare, con le prenotazioni colorate per servizio, la possibilità di spostarle trascinando e di aggiungere prenotazioni prese al telefono.
Ogni giorno alle 18 invia ai clienti del giorno dopo un promemoria (email o SMS) con il link per annullare. Due ore dopo l'appuntamento invia un messaggio di ringraziamento con il link per lasciare una recensione su Google.
Elenco clienti con numero di visite, ultima visita e servizi preferiti.
5. Pagamenti con Stripe
Aggiungi un abbonamento a 19 € al mese con 14 giorni di prova. Gratis l'utente ha: 30 prenotazioni al mese e nessun promemoria automatico. Con il piano Pro sblocca: prenotazioni illimitate, promemoria automatici, richiesta di recensioni e più operatori.
A pagamento riuscito il webhook porta l'utente al piano Pro; se l'abbonamento viene disdetto o non rinnovato lo riporta al piano gratuito.
Per la sessione di pagamento e il webhook segui la guida "Pagamenti con Stripe" di Fattibile.
6. Controlli specifici di questo progetto
Oltre ai controlli della guida "Controllo finale", verifica in particolare:
1. Doppie prenotazioni: apri la stessa pagina in due finestre e prenota lo stesso orario quasi insieme: solo una prenotazione deve riuscire.
Correggi quello che non va e scrivimi cosa hai cambiato.
Dettagli tecnici
Tabelle con il blocco delle doppie prenotazioni
Il vincolo "exclude" rende impossibile, a livello di database, avere due prenotazioni che si sovrappongono.
create extension if not exists btree_gist;
create table attivita (
id uuid primary key default gen_random_uuid(),
utente_id uuid not null references auth.users(id) on delete cascade,
slug text not null unique,
nome text not null,
telefono text,
orari jsonb not null -- es. {"lun": [["09:00","13:00"],["15:00","19:00"]], ...}
);
create table servizi (
id uuid primary key default gen_random_uuid(),
attivita_id uuid not null references attivita(id) on delete cascade,
nome text not null,
durata_minuti int not null check (durata_minuti between 5 and 480),
prezzo_centesimi int not null default 0
);
create table prenotazioni (
id uuid primary key default gen_random_uuid(),
attivita_id uuid not null references attivita(id) on delete cascade,
servizio_id uuid not null references servizi(id),
cliente_nome text not null,
cliente_telefono text not null,
periodo tstzrange not null,
stato text not null default 'confermata' check (stato in ('confermata', 'annullata')),
-- Due prenotazioni confermate della stessa attività non possono sovrapporsi
exclude using gist (attivita_id with =, periodo with &&) where (stato = 'confermata')
);Regole di sicurezza
Pagina e servizi pubblici; i clienti prenotano senza vedere le prenotazioni degli altri; il titolare gestisce tutto.
alter table attivita enable row level security;
alter table servizi enable row level security;
alter table prenotazioni enable row level security;
create policy "attivita pubbliche" on attivita for select using (true);
create policy "gestisco la mia attivita" on attivita
for all using (auth.uid() = utente_id) with check (auth.uid() = utente_id);
create policy "servizi pubblici" on servizi for select using (true);
create policy "gestisco i miei servizi" on servizi for all
using (exists (select 1 from attivita a where a.id = attivita_id and a.utente_id = auth.uid()))
with check (exists (select 1 from attivita a where a.id = attivita_id and a.utente_id = auth.uid()));
create policy "chiunque prenota" on prenotazioni for insert with check (stato = 'confermata');
create policy "il titolare vede e gestisce" on prenotazioni for all
using (exists (select 1 from attivita a where a.id = attivita_id and a.utente_id = auth.uid()));
-- Per mostrare gli orari occupati senza esporre nomi e telefoni
create function orari_occupati(attivita uuid, giorno date) returns setof tstzrange
language sql security definer set search_path = public as $
select periodo from prenotazioni
where attivita_id = attivita and stato = 'confermata'
and periodo && tstzrange(giorno::timestamptz, (giorno + 1)::timestamptz);
$;
Pezzi comuni a tutti i progetti
Glossario
- JSONB
- Un tipo di colonna che contiene dati strutturati flessibili, come un piccolo documento.
- Cron
- Un'operazione programmata che parte da sola a orari fissi, per esempio ogni lunedì mattina.
- Slug
- La parte finale e leggibile dell'indirizzo di una pagina, es. /pizzeria-da-mario.