API serverless pour Kryptosphere, déployée sur Vercel avec Neon Postgres.
Stack : Node.js · TypeScript · Hono · Prisma · Neon (PostgreSQL) · Neon Auth (Better Auth) · Vercel Blob
npm install
cp env.example .env
# Remplir .env avec les vraies valeurs (voir section Variables d'environnement)
npm run db:generate
npm run db:push
npm run dev # Node server sur http://localhost:3000| Variable | Description |
|---|---|
DATABASE_URL |
Connection string Neon — branch dev en local, kryptosphere_db en prod |
NEON_AUTH_JWKS_URL |
JWKS endpoint Neon Auth pour vérifier les JWT — Neon Console → Auth → Configuration |
SETUP_SECRET |
Secret one-time pour promouvoir le premier super admin — openssl rand -base64 32 |
BLOB_READ_WRITE_TOKEN |
Token Vercel Blob pour l'upload d'images |
Voir env.example pour les formats.
- Un projet Neon avec Neon Auth activé
- Un branch Neon
devcréé depuisproduction(hérite du schémaneon_auth) DATABASE_URLpointant sur le branchdev
npm run dev
# API disponible sur http://localhost:3000npm run dev démarre un serveur Node.js via tsx watch avec hot-reload.
Le fichier api/[[...route]].ts reste l'entrée Vercel utilisée en production.
GET http://localhost:3000/api/health
À faire une seule fois après le premier db:push sur une nouvelle base.
1. Créer un compte via Neon Auth
Invoke-RestMethod `
-Uri "<NEON_AUTH_BASE_URL>/sign-up/email" `
-Method Post `
-ContentType "application/json" `
-Headers @{ "Origin" = "http://localhost:3000" } `
-Body '{"email":"toi@example.com","password":"MotDePasse!","name":"Yohan"}'Utiliser curl sur linux.
<NEON_AUTH_BASE_URL> = Auth URL dans Neon Console → Auth → Configuration.
Récupère le token dans la réponse.
2. Promouvoir en super admin
Invoke-RestMethod `
-Uri "http://localhost:3000/api/setup" `
-Method Post `
-Headers @{
"Authorization" = "Bearer <token>"
"x-setup-secret" = "<SETUP_SECRET>"
}Retourne 403 si un super admin existe déjà.
{ "status": "ok", "db": "up", "timestamp": "...", "uptime": 42, "responseTimeMs": 8 }Retourne l'utilisateur courant synchronisé depuis Neon Auth.
Authorization: Bearer <jwt>
{ "type": "main", "year": 2025 }type : "main" | "chapter". chapterId obligatoire si type = "chapter".
Upload multipart :
file: fichier imagekey: identifiant uniquealtText(optionnel)
Réponse 201 :
{ "image": { "id": "...", "key": "...", "url": "..." }, "blob": { "url": "..." } }| Commande | Description |
|---|---|
npm run dev |
Serveur Node local avec hot-reload |
npm run build |
Compilation TypeScript |
npm run db:generate |
Génère le client Prisma |
npm run db:push |
Applique le schéma Prisma (dev) |
npm run db:migrate |
Migrations Prisma (prod) |
kryptosphere-api/
├── api/
│ ├── [[...route]].ts # Catch-all Vercel → entrée Hono (prod)
│ └── routes/
│ ├── health.router.ts
│ ├── auth.router.ts
│ ├── board.router.ts
│ ├── images.router.ts
│ └── setup.router.ts
├── app.ts # App Hono partagée (dev + prod)
├── server.ts # Serveur Node local (dev uniquement)
├── lib/
│ ├── db.ts # Client Prisma singleton (adaptateur Neon)
│ └── middleware.ts # Auth JWT (JWKS) + role guard
├── services/postgres/ # DAO layer — un service par entité
├── models/ # Interfaces TypeScript
├── prisma/
│ ├── schema.prisma
│ └── prisma.config.ts # Config Prisma 7 (adaptateur Neon)
└── env.example
Voir DEPLOYMENT.md.