Les fondations techniques
Stack recommandée pour un MVP
- Backend : FastAPI (Python) ou Next.js API routes
- Frontend : Next.js ou React + Vite
- Base de données : PostgreSQL (Supabase ou Neon)
- Auth : Clerk, Auth0, ou Supabase Auth
- Paiements : Stripe
- Hébergement : Vercel, Railway, ou Render
Architecture multi-tenant
Trois approches possibles :
1. Colonne tenant_id (recommandé pour MVP)
-- Chaque table a une colonne organization_id
CREATE TABLE projects (
id UUID PRIMARY KEY,
organization_id UUID NOT NULL REFERENCES organizations(id),
name VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW()
);
-- Index pour les requêtes filtrées
CREATE INDEX idx_projects_org ON projects(organization_id);
2. Schema par tenant
Meilleure isolation mais plus complexe à gérer.
3. Base de données par tenant
Isolation maximale, pour les clients enterprise.
Authentification et autorisation
# Exemple avec FastAPI et JWT
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer
security = HTTPBearer()
async def get_current_user(token = Depends(security)):
user = verify_jwt(token.credentials)
if not user:
raise HTTPException(401, "Invalid token")
return user
async def get_current_org(user = Depends(get_current_user)):
# Récupérer l'organisation de l'utilisateur
return user.organization_id
@app.get("/projects")
async def list_projects(org_id = Depends(get_current_org)):
return await db.projects.filter(organization_id=org_id).all()
Intégration Stripe
Modèle de données
CREATE TABLE subscriptions (
id UUID PRIMARY KEY,
organization_id UUID REFERENCES organizations(id),
stripe_customer_id VARCHAR(255),
stripe_subscription_id VARCHAR(255),
plan VARCHAR(50), -- 'free', 'pro', 'enterprise'
status VARCHAR(50), -- 'active', 'canceled', 'past_due'
current_period_end TIMESTAMP
);
Webhooks Stripe
@app.post("/webhooks/stripe")
async def stripe_webhook(request: Request):
payload = await request.body()
sig = request.headers.get("stripe-signature")
try:
event = stripe.Webhook.construct_event(
payload, sig, STRIPE_WEBHOOK_SECRET
)
except ValueError:
raise HTTPException(400, "Invalid payload")
if event.type == "customer.subscription.updated":
subscription = event.data.object
await update_subscription(
stripe_subscription_id=subscription.id,
status=subscription.status,
plan=subscription.items.data[0].price.lookup_key
)
return {"status": "ok"}
Feature flags et plans
PLAN_LIMITS = {
"free": {"projects": 3, "api_calls": 100},
"pro": {"projects": 50, "api_calls": 10000},
"enterprise": {"projects": -1, "api_calls": -1} # -1 = illimité
}
async def check_limit(org_id: str, feature: str):
subscription = await get_subscription(org_id)
limit = PLAN_LIMITS[subscription.plan][feature]
if limit == -1:
return True
current_usage = await get_usage(org_id, feature)
if current_usage >= limit:
raise HTTPException(403, f"Plan limit reached for {feature}")
return True
Emails transactionnels
Services recommandés : Resend, Postmark, ou SendGrid.
import resend
resend.api_key = "re_xxxxx"
def send_welcome_email(email: str, name: str):
resend.Emails.send({
"from": "AI Labs Audit ",
"to": email,
"subject": "Bienvenue sur AI Labs Audit",
"html": render_template("welcome.html", name=name)
})
Monitoring et analytics
- Errors : Sentry
- Analytics : PostHog ou Plausible
- Uptime : BetterUptime ou UptimeRobot
- Logs : Axiom ou Papertrail
Checklist avant le lancement
- HTTPS partout
- Rate limiting sur les APIs
- Backup automatique de la DB
- Mentions légales et CGV
- Politique de confidentialité (RGPD)
- Page de statut
- Documentation utilisateur
- Support client (email ou chat)
Conseil : Lancez tôt, même imparfait. Les premiers utilisateurs vous donneront un feedback invaluable. J'ai lancé AI Labs Audit avec 30% des features prévues - et les utilisateurs m'ont guidé vers ce qui comptait vraiment.
Coûts typiques au lancement
- Hébergement : 0-50€/mois (tiers gratuits disponibles)
- Base de données : 0-25€/mois
- Emails : 0-20€/mois
- Domaine : 15€/an
- Stripe : 1.4% + 0.25€ par transaction
Total MVP : 0-100€/mois est réaliste.
Conclusion
Créer un SaaS n'a jamais été aussi accessible. Les outils modernes permettent de lancer un produit professionnel avec un investissement minimal. La clé : commencer simple, valider le marché, puis itérer.
Vous avez une idée de SaaS ? Découvrez mes services de création SaaS ou contactez-moi pour en discuter.