SaaS B2C / Solo Founder Friendly
-
L'Idée : Le carnet d'entretien numérique et portfolio de restauration transférable pour véhicules de passionnés. C'est un "Digital Twin" administratif.
-
Le Problème : La valeur d'une voiture de collection/sport dépend à 50% de son historique. Actuellement, cet historique est un tas de factures papier en vrac ou un fichier Excel laid. Cela ne rassure pas l'acheteur et fait perdre de la valeur.
-
La Proposition de Valeur : Transformer des factures ennuyeuses en une "Timeline de Valeur" interactive et visuelle, qui sert de preuve ultime lors de la revente.
-
La Cible : Adultes (30-65 ans), propriétaires de Youngtimers, sportives, ou restaurateurs amateurs. Budget moyen/élevé.
-
Fonction : Ajouter un ou plusieurs véhicules.
-
Données : Marque, Modèle, Année, VIN (Numéro série), Kilométrage initial, Photo de couverture.
-
UX : Interface propre, vision globale de la collection.
-
Fonction : Ajouter des événements chronologiques au lieu de dossiers.
-
Types d'événements :
- Entretien (Vidange, freins...)
- Modification (Stage 1, nouvelles jantes...)
- Administratif (Contrôle technique, Assurance)
-
Preuves : Upload de photos et factures (PDF, JPG, PNG) pour chaque événement.
-
Fonction : Générer une URL publique unique (ex: `(https://vin-trace.fr/v/porsche911-vin123).
-
Contenu : Affiche la voiture et sa timeline de manière sexy pour les acheteurs potentiels.
-
Sécurité : Floutage automatique des données sensibles (adresse, nom complet) sur la vue publique.
-
Graphique : Courbe simple "Investissement total sur 2 ans".
- Export PDF : Bouton pour télécharger tout le dossier en un PDF propre (pour impression).
Optimisée pour la vitesse de dev, le coût zéro au lancement, et la performance.
-
Framework : Next.js (App Router).
- Rôle : Gère à la fois le Frontend (React) et le Backend (API Routes). Permet le SSR (référencement) des pages Showroom.
-
Langage : TypeScript.
- Rôle : Évite les bugs bêtes en imposant une structure aux données.
-
Style : Tailwind CSS.
- Rôle : Design ultra-rapide sans écrire de fichiers CSS séparés.
-
Hébergement : Vercel (Plan Hobby Gratuit).
- Rôle : Héberge le site. Déploiement automatique depuis GitHub.
-
Base de Données : Supabase Database (PostgreSQL).
- Rôle : Stocke toutes les infos textuelles (Utilisateurs, Voitures, Events).
-
Stockage Fichiers : Supabase Storage.
- Rôle : Stocke les images et PDF.
-
Authentification : Supabase Auth.
- Rôle : Gère l'inscription, le login, les sessions et la sécurité.
-
Emails : Supabase + Resend (via Edge Functions).
- Rôle : Envoie les mails de bienvenue ou de notifs.
-
Paiement : Polar.sh.
- Rôle : Gère les abonnements.
-
React Ui Library : ShadcnUi
- Rôle : Permet de contruire rapidement l'Ui.
Objectif : Sécuriser les données entrantes et sortantes des composants.
- Comprendre les fichiers .tsx
- Notez que c'est du JSX standard, mais qui refuse de compiler si les types ne sont pas définis.
- Définir des types des Props
- Apprenez à déclarer la structure des données attendues par un composant.
- Syntaxe à maîtriser : Utiliser
typeouinterfacepour définir les propriétés (props).type ButtonProps { label: string, isDisabled?: boolean, onClick: () => void }
- Typer les Hooks (useState)
- Apprenez à forcer le type d'un état local.
- Syntaxe :
const [user, setUser] = useState<UserType | null>(null);
Objectif : Comprendre le routage et le rendu hybride.
- Routing par système de fichiers
- Comprenez que créer un dossier
app/dashboard/page.tsxcrée automatiquement la route URL/dashboard. -
layout.tsxdéfinit le cadre commun qui persiste lors de la navigation.
- Comprenez que créer un dossier
- Server Components (Défaut)
- Rendu sur le serveur (pas de JS envoyé au navigateur).
- Ils peuvent être
asyncet lire la base de données directement via Supabase server client. - Ils ne supportent pas
onClick,useStateouuseEffect.
- Client Components
- Exigent la directive
"use client";en haut du fichier. - Utilisation obligatoire dès qu'il y a de l'interactivité (boutons, formulaires) ou des hooks React.
- Exigent la directive
- Routes Dynamiques (
/[id])- Comprendre comment le dossier entre crochets
[id]permet de capturer un paramètre dans l'URL (ex: l'ID d'une voiture ou d'un événement). - Savoir récupérer ce paramètre dans le Server Component
page.tsxvia l'objetparamspour l'utiliser dans une requête Supabase.
- Comprendre comment le dossier entre crochets
Objectif : Mettre en page sans écrire de CSS.
- Classes Utilitaires
- Comprendre la correspondance :
p-4=padding: 1rem,bg-black=background-color: black.
- Comprendre la correspondance :
- Modèle Flexbox
- Maîtriser l'alignement avec
flex,items-center(axe vertical),justify-between(axe horizontal),gap-4.
- Maîtriser l'alignement avec
- Design Mobile-First
- Les classes de base s'appliquent au mobile.
- Utiliser les préfixes pour les écrans plus larges :
md:flex-row.
Objectif : Centraliser la donnée, les fichiers, l’auth et les actions backend.
- Définition du Schéma (SQL Editor / Migrations)
- Apprenez à créer des tables PostgreSQL pour voitures, événements, utilisateurs.
- Row Level Security (RLS)
- Apprenez à restreindre l’accès aux données par utilisateur.
- Requêtes côté serveur
- Utilisez le client Supabase server-side dans les Server Components Next.js.
- Requêtes côté client
- Utilisez le client browser pour les formulaires interactifs.
- Stockage
- Upload, suppression et récupération d’images/PDF via Supabase Storage.
- Edge Functions (optionnel)
- Permet d’ajouter de la logique backend (ex: envoyer un mail via Resend après un ajout d’événement).
- Gestion d'état globale complexe : Pas de Redux, Zustand ou Context API.
useEffectpour charger des données : Inutile si vous utilisez des Server Components pour charger en SSR.- L'optimisation prématurée : Pas de
useMemoouuseCallback. - L'écriture de requêtes SQL brutes (Supabase abstrait déjà tout).
- Setup : Projet Next.js + Supabase.
- Database : Définir une table
tachessimple. - Lecture : Lire les données dans
page.tsx(Server Component) depuis Supabase. - Écriture : Créer un composant
Formulaire.tsx("use client";) qui ajoute une tâche via le client Supabase. - Test : Vérifier que la nouvelle tâche apparaît après soumission.
[[Todo List VinTrace]]
Rôle
Extension applicative de auth.users.
Centralise les données utilisateur côté produit.
Colonnes
id— uuid
Identifiant utilisateur, clé primaire, lié àauth.users.idemail— text
Email de l’utilisateurfull_name— text | nullable
Nom affichéavatar_url— text | nullable
Image de profilcreated_at— timestamp
Date de création du profil
Relations
- 1–1 avec
auth.users - 1–N avec
vehicles - 1–N avec
maintenance_events - 1–N avec
event_files - 1–N avec
subscriptions
Row Level Security
- Activée
Policies
- Lecture autorisée uniquement à l’utilisateur propriétaire du profil
- Mise à jour autorisée uniquement à l’utilisateur propriétaire du profil
- Aucune suppression autorisée depuis le client
Rôle
Représente un véhicule possédé par un utilisateur.
Supporte une exposition publique via une page showroom.
Colonnes
id— uuid
Identifiant du véhiculeowner_id— uuid
Référence versprofiles.idbrand— text
Marque du véhiculemodel— text
Modèle du véhiculeyear— integer | nullable
Annéevin— text
Numéro de série, uniqueinitial_mileage— integer | nullable
Kilométrage à l’ajoutcover_image_url— text | nullable
Image principaleis_public— boolean
Indique si la page showroom est accessiblepublic_slug— text | nullable
Identifiant public utilisé dans l’URLcreated_at— timestamp
Relations
- N–1 avec
profiles - 1–N avec
maintenance_events - 1–N avec
ownership_transfers
Row Level Security
- Activée
Policies
- Accès complet (lecture, écriture, suppression) réservé au propriétaire
- Lecture publique autorisée uniquement si
is_public = true - Aucune écriture publique possible
Rôle
Événements chronologiques constituant l’historique du véhicule.
C’est le cœur métier.
Colonnes
id— uuid
Identifiant de l’événementvehicle_id— uuid
Véhicule concernéowner_id— uuid
Propriétaire de l’événementtype— text
Valeurs possibles :maintenance,modification,administrativetitle— text
Titre courtdescription— text | nullable
Détailsmileage— integer | nullable
Kilométrage au moment de l’événementcost— numeric | nullable
Coût associéevent_date— date
Date réelle de l’événementcreated_at— timestamp
Relations
- N–1 avec
vehicles - N–1 avec
profiles - 1–N avec
event_files
Row Level Security
- Activée
Policies
- Accès complet réservé au propriétaire
- Aucun accès public direct (la lecture publique passe par la voiture)
Rôle
Fichiers justificatifs associés à un événement.
Colonnes
id— uuid
Identifiant du fichierevent_id— uuid
Événement associéowner_id— uuid
Propriétairefile_url— text
URL Supabase Storagefile_type— text
Valeurs possibles :invoice,photocreated_at— timestamp
Relations
- N–1 avec
maintenance_events - N–1 avec
profiles
Row Level Security
- Activée
Policies
- Accès complet réservé au propriétaire
- Aucun accès public direct
Rôle
Gestion du transfert de propriété d’un véhicule avec son historique.
Colonnes
id— uuid
Identifiant du transfertvehicle_id— uuid
Véhicule concernéfrom_user— uuid
Propriétaire actuelto_email— text
Email du futur propriétairetransfer_token— text
Token unique de validationaccepted— boolean
État du transfertcreated_at— timestampaccepted_at— timestamp | nullable
Relations
- N–1 avec
vehicles - N–1 avec
profiles
Row Level Security
- Activée
Policies
- Gestion complète réservée à l’expéditeur du transfert
- Aucun accès pour le destinataire tant que le token n’est pas validé
Rôle
Représentation locale des abonnements Polar.sh.
Colonnes
id— uuid
Identifiant interneuser_id— uuid
Utilisateur concernéplan— text
Valeurs possibles :free,passionne,collectionneuractive— boolean
État de l’abonnementcurrent_period_end— timestamp | nullable
Fin de période courantecreated_at— timestamp
Relations
- N–1 avec
profiles
Row Level Security
- Activée
Policies
- Lecture autorisée uniquement au propriétaire
- Aucune écriture directe côté client
Rôle
Stockage des images et documents liés aux véhicules.
Structure logique
- user_id /
- vehicle_id /
- cover /
- events /
- event_id /
- vehicle_id /
Accès
- Upload et lecture autorisés uniquement au propriétaire
- Lecture indirecte possible via URLs publiques si la voiture est publique
Principes
- Privé par défaut
- Public uniquement par intention explicite (
is_public) - Aucune policy ambiguë
- Aucun accès croisé entre utilisateurs
- Freemium : 1 voiture, limite de 5 factures (Test).
- Passionné (80€/an) : 2 voitures complètes + Page Showroom + Transfert de propriété.
- Collectionneur (200€/an) : 10 voitures.
Une fois que tu as des utilisateurs.
- V2 - Transfert de Propriété : Permettre de céder la voiture ET son historique numérique au nouvel acheteur (crée une boucle virale d'acquisition).
- V3 - IA OCR : Scanner une facture papier avec le téléphone et laisser l'IA remplir le montant et la date toute seule.
- V4 - Écosystème : Rappels automatiques d'entretien basés sur la date/km.