[Nom de la Configuration API Sanity]
[Nom de la Configuration API Sanity]
Documentation technique
Type de ressource : Configuration API Sanity (Client / Token / Requête)
Fichier source :src/lib/sanity.tsou configuration associée
Statut : [Actif / Déprécié / En développement]
1. Vue d’ensemble
1.1. Description
[Description concise du rôle de cette configuration API dans l’architecture du site]
1.2. Objectif
- [Objectif principal : ex. fournir un client Sanity typé pour les requêtes GROQ]
- [Bénéfice pour l’architecture]
1.3. Périmètre concerné
- Environnements : [Development / Staging / Production]
- Couches utilisatrices : [L2 (Astro) / L3 (Workers) / Les deux]
- Types de requêtes : [CDN / Preview / Mutations / etc.]
2. Architecture et flux
2.1. Diagramme de flux
[Astro / Worker] │ ▼[Client Sanity (configuré)] │ • Détection du mode preview │ • Sélection du token approprié │ • Configuration du CDN ▼[Sanity Content Lake API] │ • Requête GROQ │ • Validation des permissions ▼[Réponse JSON typée]2.2. Composants impliqués
| Composant | Rôle | Couche |
|---|---|---|
getSanityClient() |
Factory de client Sanity avec détection de mode | L2 (Astro) |
createClient() |
Client Sanity de base (@sanity/client) | L2/L3 |
sanity-typegen |
Génération automatique de types TypeScript | Build time |
| Variables d’environnement | Configuration des tokens et IDs | Runtime |
3. Configuration
3.1. Variables d’environnement requises
| Variable | Description | Obligatoire | Valeur par défaut |
|---|---|---|---|
PUBLIC_SANITY_PROJECT_ID |
ID du projet Sanity | ✅ | - |
PUBLIC_SANITY_DATASET |
Nom du dataset (ex: production) |
✅ | - |
PUBLIC_SANITY_API_VERSION |
Version de l’API (ex: 2025-01-01) |
✅ | - |
SANITY_API_READ_TOKEN |
Token de lecture (pour preview) | ✅ (en preview) | - |
SANITY_API_WRITE_TOKEN |
Token d’écriture (pour mutations) | ❌ | - |
3.2. Configuration du client (L2 - Astro)
import { createClient, type ClientConfig } from '@sanity/client';import type { AstroGlobal } from 'astro';
export function getSanityClient(astro: AstroGlobal) { const isPreview = astro.cookies.get('sanity-preview')?.value === 'true' || astro.request.headers.get('x-sanity-preview') === 'true';
const config: ClientConfig = { projectId: import.meta.env.PUBLIC_SANITY_PROJECT_ID, dataset: import.meta.env.PUBLIC_SANITY_DATASET, apiVersion: import.meta.env.PUBLIC_SANITY_API_VERSION, useCdn: !isPreview, // Désactive le CDN en preview perspective: isPreview ? 'previewDrafts' : 'published', token: isPreview ? import.meta.env.SANITY_API_READ_TOKEN : undefined, };
return createClient(config);}3.3. Configuration du client (L3 - Workers)
import { createClient } from '@sanity/client';
export interface Env { PUBLIC_SANITY_PROJECT_ID: string; PUBLIC_SANITY_DATASET: string; PUBLIC_SANITY_API_VERSION: string; SANITY_API_READ_TOKEN?: string;}
export function getSanityClient(env: Env, isPreview: boolean = false) { return createClient({ projectId: env.PUBLIC_SANITY_PROJECT_ID, dataset: env.PUBLIC_SANITY_DATASET, apiVersion: env.PUBLIC_SANITY_API_VERSION, useCdn: !isPreview, perspective: isPreview ? 'previewDrafts' : 'published', token: isPreview ? env.SANITY_API_READ_TOKEN : undefined, });}4. Typage et génération automatique
4.1. Configuration de sanity-typegen
{ "path": "./src/**/*.{ts,tsx,astro}", "schema": "./schema.json", "generates": "./src/types/sanity.d.ts"}4.2. Commandes de génération
# Générer le schéma depuis Sanitynpx sanity schema extract --enforce-required-fields
# Générer les types TypeScriptnpx sanity typegen generate4.3. Types générés (exemple)
// src/types/sanity.d.ts (généré automatiquement)export type Post = { _id: string; _type: 'post'; _createdAt: string; _updatedAt: string; title: string; slug: { _type: 'slug'; current: string }; publishedAt: string; status: 'draft' | 'published' | 'archived'; mainImage?: ImageAsset; excerpt?: string; body: PortableTextBlock[]; author?: Author; categories?: Category[]; seo?: SeoObject;};
export type Author = { _id: string; _type: 'author'; name: string; image?: ImageAsset; bio?: string;};
// ... autres types5. Requêtes GROQ
5.1. Requête typée (exemple)
import type { Post } from '../types/sanity';
export const POSTS_QUERY = `*[_type == "post" && status == "published"] { _id, title, slug, publishedAt, mainImage, excerpt} | order(publishedAt desc)`;
export const POST_BY_SLUG_QUERY = `*[_type == "post" && slug.current == $slug][0] { ..., author->{name, image}, categories[]->{title, slug}}`;
// Utilisationconst client = getSanityClient(Astro);const posts = await client.fetch<Post[]>(POSTS_QUERY);const post = await client.fetch<Post>(POST_BY_SLUG_QUERY, { slug: 'mon-article' });5.2. Bonnes pratiques GROQ
- ✅ Toujours typer les résultats avec
client.fetch<T>() - ✅ Utiliser des projections explicites (éviter
*non filtré) - ✅ Filtrer par
status == "published"sauf en mode preview - ✅ Utiliser
order()pour trier les résultats - ✅ Limiter les résultats avec
[0...10]si nécessaire
6. Sécurité
6.1. Gestion des tokens
| Token | Permissions | Stockage | Exposition |
|---|---|---|---|
PUBLIC_SANITY_PROJECT_ID |
Lecture publique | .env |
Côté client ✅ |
PUBLIC_SANITY_DATASET |
Lecture publique | .env |
Côté client ✅ |
SANITY_API_READ_TOKEN |
Lecture des drafts | Cloudflare Secrets | Runtime uniquement ❌ |
SANITY_API_WRITE_TOKEN |
Écriture (mutations) | Cloudflare Secrets | Runtime uniquement ❌ |
6.2. Règles de sécurité
- ✅ Les tokens publics (
PUBLIC_*) peuvent être exposés côté client - ✅ Les tokens privés (
SANITY_API_*) ne doivent jamais être exposés côté client - ✅ Utiliser des tokens avec les permissions minimales nécessaires
- ✅ Rotation régulière des tokens (tous les 90 jours recommandé)
- ✅ Révoquer immédiatement les tokens compromis
6.3. Permissions Sanity
Configuration dans Sanity Studio :
- Settings → API → Tokens
- Créer des tokens avec des scopes spécifiques :
read: Lecture uniquementwrite: Écriture (création, modification, suppression)
7. Performance
7.1. Stratégie de cache
| Mode | useCdn |
Rationale |
|---|---|---|
| Production (SSG) | true |
Contenu mis en cache par Sanity CDN |
| Preview | false |
Contenu draft non caché |
| Mutations | false |
Données fraîches après écriture |
7.2. Optimisation des requêtes
- ✅ Utiliser des projections pour réduire la taille des réponses
- ✅ Filtrer côté serveur plutôt que côté client
- ✅ Mettre en cache les résultats fréquents (Astro
getStaticPaths) - ✅ Utiliser
stega(string encoding) pour les éditeurs visuels si nécessaire
7.3. Limites et quotas
| Limite | Valeur | Rationale |
|---|---|---|
| Taille max requête | 16 KB | Limite Sanity API |
| Taille max réponse | 100 MB | Limite Sanity API |
| Requêtes par seconde | 100 (Free) / 1000 (Pro) | Quota Sanity |
| Temps de réponse | < 5s recommandé | UX optimale |
8. Débogage et troubleshooting
8.1. Problèmes courants
| Symptôme | Cause probable | Solution |
|---|---|---|
| “Missing project ID” | Variable d’env manquante | Vérifier PUBLIC_SANITY_PROJECT_ID |
| “Invalid token” | Token expiré ou incorrect | Régénérer le token dans Sanity Studio |
| “Permission denied” | Token sans les bonnes permissions | Vérifier les scopes du token |
| Contenu draft en production | Mode preview activé par erreur | Vérifier le cookie sanity-preview |
| Types TypeScript incorrects | Schéma Sanity modifié | Régénérer les types avec sanity typegen generate |
8.2. Logs et monitoring
// Logs à vérifier en cas de problèmeconsole.log('Sanity client config', { projectId: config.projectId, dataset: config.dataset, useCdn: config.useCdn, perspective: config.perspective});
// Vérifier les requêtes dans l'onglet Network du navigateur// Vérifier les logs Sanity Studio → Settings → API → Activity8.3. Tests manuels
# Test de requête GROQ via curlcurl "https://[project-id].api.sanity.io/v2025-01-01/data/query/[dataset]?query=*[_type=='post'][0...5]" \ -H "Authorization: Bearer [token]"9. Bonnes pratiques
9.1. Architecture
- ✅ Centraliser la configuration du client dans
src/lib/sanity.ts - ✅ Séparer les requêtes GROQ dans
src/lib/queries.ts - ✅ Toujours typer les résultats avec
sanity-typegen - ✅ Utiliser des factory functions pour créer les clients (flexibilité)
9.2. Code
- ✅ Utiliser
async/awaitpour les requêtes - ✅ Gérer les erreurs avec
try/catch - ✅ Logger les erreurs de requête pour le debugging
- ✅ Ne jamais hardcoder les IDs de projet ou datasets
9.3. Environnements
- ✅ Utiliser des variables d’environnement différentes par environnement
- ✅ Tester en staging avant production
- ✅ Documenter les différences de configuration entre environnements
10. Évolutions et roadmap
10.1. Améliorations planifiées
- [Évolution 1 : ex. Implémentation de revalidation à la demande (ISR)]
- [Évolution 2 : ex. Cache distribué avec Cloudflare KV]
- [Évolution 3 : ex. Monitoring des performances des requêtes]
10.2. Limitations connues
- ❌ Le CDN Sanity ne peut pas être invalidé manuellement (TTL de 60s)
- ❌ Les mutations ne sont pas disponibles côté client (SSG uniquement)
- ❌ Le mode preview désactive le CDN (impact sur les performances)
11. Ressources liées1/2
- Documentation Sanity : API Reference
- Documentation @sanity/client : npm package
- sanity-typegen : Documentation
- DAT L1 : §4.5 - API Sanity et Stratégie de Requêtes
- DAT L2 : §5.2 - Intégration Sanity dans Astro
11. Ressources liées2/2
- Fichiers concernés :
src/lib/sanity.tssrc/lib/queries.tssrc/types/sanity.d.tssanity-typegen.config.json
12. Historique des modifications
| Date | Version | Description | Auteur |
|---|---|---|---|
| YYYY-MM-DD | 1.0 | Création initiale | [Nom] |
| YYYY-MM-DD | 1.1 | [Modification] | [Nom] |