← Tutte le idee Sport e benessere

CalMedi

Gli appuntamenti di Doctolib sincronizzati con Google Calendar

Incasso mensile: 336 USD (fonte indicata nella scheda)

Cosa fa

Uno strumento che copia in automatico gli appuntamenti presi su Doctolib nel calendario Google del medico.

Come guadagna

Ha entrate ricorrenti ogni mese, verificate su TrustMRR. Prezzi e piani esatti sono indicati sul sito del progetto.

Rendilo tuo

  • Per i programmi di prenotazione più usati in Italia.
  • Piccolo problema, ma molto fastidioso: è il tipo di idea che si vende bene.

Le frasi da scrivere all'AI

1. Base del sito e grafica

Crea un'app web in italiano chiamata "Agenda Unica": copia in automatico gli appuntamenti dai sistemi di prenotazione online (che offrono un calendario in formato iCal) nel Google Calendar del medico o del professionista, così ha tutto in un'agenda sola. Usa React, Vite, TypeScript e Tailwind CSS.

Pagine da creare:
1. Pagina iniziale con come funziona e il prezzo
2. Registrazione e collegamento di Google Calendar
3. Aggiungi un'agenda da copiare: incolla il link iCal del sistema di prenotazione
4. Stato della sincronizzazione: ultimo aggiornamento, appuntamenti copiati
5. Impostazioni: calendario di destinazione, cosa mostrare nel titolo

Stile: da studio medico: sfondo bianco, azzurro #0284C7, verde #059669 per "sincronizzato", carattere "Inter", pochissime schermate. 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:
- "collegamenti": link iCal (cifrato), calendario Google di destinazione, ultimo aggiornamento, esito, collegati all'utente
- "token_google": token per Google Calendar, solo lato server

Regole di sicurezza obbligatorie:
- ogni utente vede solo i suoi collegamenti
- link iCal e token Google non sono mai leggibili dal browser
- il piano non si modifica dal browser

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. Copia degli appuntamenti

Molti sistemi di prenotazione danno un link privato al calendario in formato iCal (.ics). L'utente lo incolla, collega Google Calendar (login Google con il solo permesso sul calendario) e sceglie il calendario di destinazione.

Ogni 10 minuti una Edge Function scarica il file iCal, legge gli appuntamenti dei prossimi 60 giorni e li copia in Google Calendar con "events.import" usando l'identificativo dell'appuntamento (codice nei Dettagli tecnici): così un appuntamento spostato si aggiorna e non si duplica, e uno annullato si cancella.

Per la privacy dei pazienti, nel titolo si può scegliere di mostrare solo "Visita" e l'orario, senza nome.

4. Stato e avvisi

Pagina di stato per ogni collegamento: ultimo aggiornamento riuscito, numero di appuntamenti copiati, eventuali errori in italiano ("il link iCal non risponde"). Se la sincronizzazione fallisce per più di un'ora, email di avviso.

Il sito non si collega mai a sistemi di prenotazione con la password del medico: usa solo il link iCal che il sistema stesso fornisce.

5. Pagamenti con Stripe

Aggiungi un abbonamento a 6 € al mese. Gratis l'utente ha: una agenda aggiornata ogni ora. Con il piano Pro sblocca: più agende, aggiornamento ogni 10 minuti, titoli personalizzati e avvisi.

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. Duplicati: sposta e poi annulla un appuntamento nel sistema di prenotazione: in Google Calendar deve spostarsi e poi sparire, senza doppioni.
Correggi quello che non va e scrivimi cosa hai cambiato.

Dettagli tecnici

Dal file iCal a Google Calendar senza doppioni

Legge gli appuntamenti dal file iCal e li importa in Google Calendar usando l'identificativo originale (iCalUID): se l'appuntamento esiste già viene aggiornato, non duplicato.

import ICAL from "npm:ical.js";

type Appuntamento = { uid: string; inizio: string; fine: string; titolo: string; annullato: boolean };

export function leggiIcal(testo: string): Appuntamento[] {
  const calendario = new ICAL.Component(ICAL.parse(testo));
  return calendario.getAllSubcomponents("vevent").map((v) => {
    const e = new ICAL.Event(v);
    return {
      uid: e.uid,
      inizio: e.startDate.toJSDate().toISOString(),
      fine: e.endDate.toJSDate().toISOString(),
      titolo: e.summary ?? "Visita",
      annullato: v.getFirstPropertyValue("status") === "CANCELLED",
    };
  });
}

export async function importaInGoogle(token: string, calendarioId: string, a: Appuntamento, soloOrario: boolean) {
  const url = "https://www.googleapis.com/calendar/v3/calendars/" + encodeURIComponent(calendarioId) + "/events/import";
  const r = await fetch(url, {
    method: "POST",
    headers: { Authorization: "Bearer " + token, "Content-Type": "application/json" },
    body: JSON.stringify({
      iCalUID: a.uid,                                  // la chiave che evita i doppioni
      summary: soloOrario ? "Visita" : a.titolo,
      start: { dateTime: a.inizio },
      end: { dateTime: a.fine },
      status: a.annullato ? "cancelled" : "confirmed",
    }),
  });
  if (!r.ok) throw new Error("Google Calendar ha risposto " + r.status);
}

Collegamenti con dati protetti

Il link iCal e i token stanno in una tabella che il browser non può leggere; l'utente vede solo lo stato.

create table collegamenti (
  id uuid primary key default gen_random_uuid(),
  utente_id uuid not null references auth.users(id) on delete cascade,
  nome text not null,
  calendario_google text not null,
  solo_orario boolean not null default true,
  ultimo_aggiornamento timestamptz,
  esito text,
  appuntamenti_copiati int not null default 0
);
alter table collegamenti enable row level security;
create policy "le mie righe" on collegamenti
  for all using (auth.uid() = utente_id) with check (auth.uid() = utente_id);

-- Dati segreti: nessuna regola = il browser non li legge mai, solo la Edge Function
create table segreti_collegamento (
  collegamento_id uuid primary key references collegamenti(id) on delete cascade,
  link_ical text not null,
  refresh_token_google text not null
);
alter table segreti_collegamento enable row level security;

Pezzi comuni a tutti i progetti

Glossario

Cron
Un'operazione programmata che parte da sola a orari fissi, per esempio ogni lunedì mattina.
iCal (.ics)
Il formato standard dei calendari: quasi tutti i sistemi di prenotazione possono esportare l'agenda così.