Docs/Componenti
// componente
Button Lead
Form da una riga per raccogliere email: input + bottone. Lo usi quando il prodotto non è ancora pronto e vuoi una waitlist, o per regalare un lead magnet. Al submit fa un POST su /api/lead, mostra un toast di conferma e si disabilita da solo. È un client component (ha "use client", usa useState e useRef).
File
components/ButtonLead.tsx
Uso base
import ButtonLead from "@/components/ButtonLead";
<ButtonLead />
// oppure centrato e più largo
<ButtonLead extraStyle="mx-auto max-w-sm" />Props
extraStyle?: string— classi extra appese al<form>. Il form ha giàw-full max-w-xs space-y-3, quindi qui ci metti allineamento, margini o unmax-w-diverso.
Non ci sono altre props: il testo del bottone (“Entra in waitlist”), il placeholder (“La tua email”) e il messaggio di successo sono scritti dentro il componente.
Il giro completo
Il submit chiama apiClient.post("/lead", { email }). apiClient è l'istanza axios in libs/api.ts con baseURL: "/api": gli errori vengono già mostrati come toast, quindi il componente non gestisce il caso di errore a mano.
Dall'altra parte, app/api/lead/route.ts valida solo la presenza dell'email (400 se manca) e poi restituisce un oggetto vuoto. La riga che salva il lead è commentata: di default l'email non viene scritta da nessuna parte. Sta a te decommentarla.
export async function POST(req: NextRequest) {
const body = await req.json();
if (!body.email) {
return NextResponse.json({ error: "Email is required" }, { status: 400 });
}
try {
// scommenta per salvare davvero il lead
const supabase = createClient();
await supabase.from("leads").insert({ email: body.email });
return NextResponse.json({});
} catch (e) {
console.error(e);
return NextResponse.json({ error: e.message }, { status: 500 });
}
}Personalizzare
- Salvare il lead: crea una tabella
leadssu Supabase e decommenta le due righe qui sopra (compreso l'import dicreateClientin cima al file). Vedi Database. - Email di benvenuto: dentro il
trypuoi chiamaresendEmaildalibs/resend. Vedi Email. - Copy: cambia il testo del bottone, il
placeholdere il messaggio ditoast.successdirettamente nel componente. - Stile: l'input usa
input-brutale il bottonebtn-brutal-primary, entrambe definite inapp/globals.css. Passa abtn-brutal-mustardse ti serve più contrasto. - Riabilitare il form: dopo un invio riuscito
isDisabledrestatrueper sempre. Se vuoi permettere più invii, togli quella riga.