AbMaxx
Una foto degli addominali, un voto e un piano di allenamento
Incasso mensile: 19.000 USD (fonte indicata nella scheda)
Cosa fa
App in abbonamento: l'utente scatta una foto, l'AI analizza gli addominali, dà un punteggio e crea un piano di allenamento personalizzato da seguire, con i progressi nel tempo.
Come guadagna
Abbonamento nell'app.
Rendilo tuo
- Allenamenti per un obiettivo diverso: postura, glutei, corsa.
- Confronto prima/dopo ogni 2 settimane, che è quello che motiva a restare.
- Attenzione: niente promesse mediche o di dimagrimento garantito; sotto i 18 anni non deve essere usabile.
Le frasi da scrivere all'AI
1. Base del sito e grafica
Crea un'app web in italiano chiamata "Core Check": analizza con l'AI una foto del busto, dà un voto agli addominali e crea un piano di allenamento di 30 giorni con i progressi nel tempo. Usa React, Vite, TypeScript e Tailwind CSS.
Pagine da creare:
1. Pagina iniziale con come funziona, esempio di analisi e prezzi
2. Registrazione con conferma dell'età (solo maggiorenni)
3. Nuova analisi: caricamento della foto con le istruzioni per scattarla bene
4. Risultato: voto, punti di forza, cosa migliorare, piano
5. Progressi: confronto prima/dopo e storico
Stile: atletico e motivante: sfondo scuro #0F172A, verde energia #22C55E, bianco per i testi, carattere "Outfit", numeri grandi e barre di progresso. 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:
- "analisi": foto nello Storage, voto, punti di forza, cose da migliorare, data, collegate all'utente
- "piani": gli esercizi dei 30 giorni e quelli completati
Regole di sicurezza obbligatorie:
- ogni utente vede solo le sue analisi, foto e piani
- le foto stanno in uno spazio privato
- 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. L'analisi della foto
Nella pagina "Nuova analisi" spiega come scattare la foto (luce frontale, busto in piedi, stessa posizione ogni volta) e accetta solo immagini fino a 8 MB.
La Edge Function "analisi" (nei Dettagli tecnici) invia la foto a Claude, che la guarda e restituisce in JSON: un voto da 1 a 10, 3 punti di forza, 3 cose da migliorare e il livello consigliato del piano. Rifiuta le foto non adatte (non un busto, più persone, minorenni) con un messaggio gentile.
Poi crea un piano di 30 giorni di esercizi a corpo libero adatti al livello, con video o disegni per ogni esercizio, da spuntare giorno per giorno.
Mostra sempre l'avviso: "Questa analisi è una stima a scopo motivazionale e non sostituisce un medico o un personal trainer".
4. Progressi nel tempo
Ogni 14 giorni invita a una nuova foto. Nella pagina progressi mostra: le foto affiancate prima/dopo con un cursore, il grafico del voto nel tempo, i giorni del piano completati e la serie di giorni consecutivi.
Permetti di cancellare in qualsiasi momento tutte le foto e le analisi con un solo pulsante.
5. Pagamenti con Stripe
Aggiungi un abbonamento a 4,99 € al mese. Gratis l'utente ha: una sola analisi e la prima settimana del piano. Con il piano Pro sblocca: un'analisi ogni 14 giorni, il piano completo e il confronto prima/dopo.
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. Età e salute: verifica che senza la conferma della maggiore età non si possa caricare una foto, e che in nessun testo ci siano promesse di dimagrimento o risultati garantiti.
Correggi quello che non va e scrivimi cosa hai cambiato.
Dettagli tecnici
Analisi della foto con Claude
Claude guarda la foto e restituisce un giudizio strutturato. La chiave dell'AI resta sul server; la foto viene letta dallo Storage privato.
// supabase/functions/analisi/index.ts (parte centrale)
import Anthropic from "npm:@anthropic-ai/sdk";
import { encodeBase64 } from "jsr:@std/encoding/base64";
const claude = new Anthropic({ apiKey: Deno.env.get("ANTHROPIC_API_KEY")! });
export async function analizzaFoto(foto: Uint8Array, tipo: "image/jpeg" | "image/png") {
const risposta = await claude.beta.messages.create({
model: "claude-opus-5",
max_tokens: 16000,
betas: ["server-side-fallback-2026-07-01"],
fallbacks: "default",
system: "Valuti in modo motivante e rispettoso la definizione degli addominali in una foto. " +
"Se la foto non mostra il busto di un adulto, o ci sono più persone, rispondi {\"valida\": false}. " +
"Altrimenti rispondi solo con JSON: {\"valida\": true, \"voto\": 1-10, \"forza\": [3 frasi], " +
"\"migliorare\": [3 frasi], \"livello\": \"principiante\"|\"intermedio\"|\"avanzato\"}. " +
"Niente consigli medici o alimentari estremi.",
messages: [{
role: "user",
content: [
{ type: "image", source: { type: "base64", media_type: tipo, data: encodeBase64(foto) } },
{ type: "text", text: "Analizza questa foto." },
],
}],
});
if (risposta.stop_reason === "refusal") return { valida: false };
const testo = risposta.content.filter((b) => b.type === "text").map((b) => b.text).join("");
return JSON.parse(testo);
}Tabelle e Storage privato
Analisi, piani e uno spazio privato per le foto, una cartella per utente.
create table analisi (
id uuid primary key default gen_random_uuid(),
utente_id uuid not null references auth.users(id) on delete cascade,
foto_path text not null,
voto int check (voto between 1 and 10),
punti_forza text[] not null default '{}',
da_migliorare text[] not null default '{}',
creato_il timestamptz not null default now()
);
create table piani (
id uuid primary key default gen_random_uuid(),
utente_id uuid not null references auth.users(id) on delete cascade,
livello text not null,
esercizi jsonb not null, -- 30 giorni di esercizi
giorni_completati int[] not null default '{}'
);
alter table analisi enable row level security;
create policy "le mie righe" on analisi
for all using (auth.uid() = utente_id) with check (auth.uid() = utente_id);
alter table piani enable row level security;
create policy "le mie righe" on piani
for all using (auth.uid() = utente_id) with check (auth.uid() = utente_id);
insert into storage.buckets (id, name, public) values ('foto-busto', 'foto-busto', false);
create policy "solo la mia cartella" on storage.objects for all to authenticated
using (bucket_id = 'foto-busto' and (storage.foldername(name))[1] = auth.uid()::text)
with check (bucket_id = 'foto-busto' and (storage.foldername(name))[1] = auth.uid()::text);
Pezzi comuni a tutti i progetti
Glossario
- Storage
- Lo spazio di Supabase dove si salvano i file, come foto e audio, con le sue regole di accesso.
- JSONB
- Un tipo di colonna che contiene dati strutturati flessibili, come un piccolo documento.