Meilleure pile technologique pour sites d'annuaires et de places de marché en 2026
Traduire l'article markdown suivant en français.
Règles :
- Préservez TOUTE la mise en forme markdown (##, ###, **, __,
code,blocks, tables, liens) - Gardez inchangés tous les URLs, extraits de code, noms de marques et termes techniques
- Traduisez les en-têtes, la prose et les éléments de liste
- Retournez UNIQUEMENT le markdown traduit. Pas de préambule, pas d'explication.
La plupart des articles « meilleure pile technologique » donnent l'impression que quelqu'un a parcouru Product Hunt un après-midi et a écrit ses conclusions. Ils vous diront d'utiliser React et peut-être Postgres, d'ajouter Stripe, et c'est tout. C'est peu utile quand vous essayez de construire un site d'annuaire avec 137 000 pages de listes qui doivent se charger rapidement, supporter la géo-recherche dans un rayon de 50 miles, et permettre aux utilisateurs de trouver des résultats en utilisant des requêtes en langage naturel.
J'ai passé les deux dernières années à construire exactement ces types de sites. Pas des projets jouets -- des plateformes d'annuaires et de marchés de production gérant des centaines de milliers d'enregistrements, le traitement des paiements multi-pays (y compris les beaux cas limites comme les devises sans décimales), et des systèmes de recherche qui combinent la recherche en texte intégral, l'IA sémantique et les requêtes géographiques simultanément. Cet article parcourt chaque couche de la pile que nous utilisons chez Social Animal, pourquoi nous avons choisi chaque élément, et les données de production qui soutiennent ces décisions.
Table des matières
- Pourquoi les sites d'annuaires et de marchés sont architecturalement uniques
- Aperçu de la pile à 10 couches
- Couche 1 : Frontend -- Next.js 15
- Couche 2 : Base de données -- Supabase PostgreSQL
- Couche 3 : Authentification -- Supabase Auth
- Couche 4 : Paiements -- Stripe Connect
- Couche 5 : Recherche -- Le modèle de triple recherche
- Couche 6 : Médias -- Supabase Storage + Next.js Image
- Couche 7 : Hébergement -- Vercel
- Couche 8 : Email -- Brevo API
- Couche 9 : IA -- Claude API
- Couche 10 : Surveillance -- Vercel Analytics + PostHog
- Tableau de comparaison de la pile complète
- Ce que cette pile coûte en production
- FAQ

Pourquoi les sites d'annuaires et de marchés sont architecturalement uniques
Les sites d'annuaires et de marchés semblent simples en surface. Énumérez quelques choses, laissez les gens chercher, peut-être traitez un paiement. Mais dès que vous commencez à en construire un avec de vraies données, vous rencontrez des problèmes pour lesquels les architectures SaaS standard ne vous préparent pas.
D'abord, il y a le problème du nombre de pages. Un annuaire avec 100K+ listes a besoin de 100K+ pages. Vous ne pouvez pas les rendre côté serveur à chaque demande, et vous ne pouvez pas les générer statiquement au moment de la compilation (vos compilations prendraient des heures). Vous avez besoin de quelque chose de plus intelligent -- Incremental Static Regeneration (ISR) ou revalidation à la demande.
Deuxièmement, la recherche est multi-dimensionnelle. Les utilisateurs veulent chercher par texte (« thérapeute familial »), par sens (« quelqu'un qui aide avec l'anxiété relationnelle »), et par localisation (« à moins de 20 miles d'Austin »). La plupart des piles gèrent l'une de ces trois. Gérer les trois simultanément nécessite une architecture de base de données spécifique.
Troisièmement, les marchés ont une complexité de paiement qui va bien au-delà d'un simple paiement. Vous traitez les commissions de plateforme, les niveaux d'abonnement, la tarification multi-devises et les différences réglementaires entre les pays. Si vous vous trompez sur l'un de ces points, vous perdez de l'argent ou vous enfreignez les lois.
Ces contraintes ont façonné chaque décision dans notre pile. Parcourons chaque couche.
Aperçu de la pile à 10 couches
Avant de plonger en profondeur, voici l'image complète :
| Couche | Outil | Pourquoi |
|---|---|---|
| Frontend | Next.js 15 (App Router) | ISR pour 100K+ pages, Server Components |
| Base de données | Supabase PostgreSQL | pgvector + PostGIS + full-text dans une seule DB |
| Auth | Supabase Auth | Row-Level Security, accès basé sur les rôles |
| Paiements | Stripe Connect | Commissions de marché, multi-devises |
| Recherche | Modèle triple (tsvector + pgvector + PostGIS) | Texte + sémantique + géo simultanément |
| Médias | Supabase Storage + Next.js Image | Livraison optimisée, uploads simples |
| Hébergement | Vercel | Déploiement edge, support ISR, URLs de prévisualisation |
| Brevo API | Transactionnel + marketing depuis les API routes | |
| IA | Claude API | Recherche sémantique, enrichissement de contenu, chatbots |
| Surveillance | Vercel Analytics + PostHog | Suivi du trafic et du comportement des utilisateurs |
Chaque couche ici s'exécute en production sur plusieurs projets. Laissez-moi vous montrer à quoi cela ressemble réellement.
Couche 1 : Frontend -- Next.js 15
Nous avons construit des sites d'annuaires avec à la fois Next.js et Astro. Les deux sont excellents. Mais pour les annuaires et les marchés spécifiquement, Next.js 15 avec l'App Router gagne grâce à une fonctionnalité : Incremental Static Regeneration.
Voici le scénario réel. L'un de nos projets d'annuaire rend 137 000 pages de listes. Un autre en gère 91 000. Vous ne pouvez pas générer statiquement toutes ces pages au moment de la compilation -- la compilation prendrait une éternité et vous dépasseriez les limites d'exécution de fonction de Vercel. Et vous ne pouvez pas les rendre côté serveur à chaque demande parce que vos coûts de serveur seraient absurdes et votre Time to First Byte en souffrirait.
ISR vous offre le meilleur des deux mondes. Le premier visiteur d'une page déclenche un rendu serveur, qui est mis en cache à la périphérie. Les visiteurs suivants obtiennent la version statique. Vous définissez un intervalle de revalidation (nous utilisons généralement 3600 secondes pour les pages de listes), et le cache s'actualise en arrière-plan.
// app/listings/[slug]/page.tsx
export const revalidate = 3600; // Revalider toutes les heures
export async function generateStaticParams() {
// Ne pré-générer que les 1000 listes les plus consultées
const { data } = await supabase
.from('listings')
.select('slug')
.order('view_count', { ascending: false })
.limit(1000);
return data?.map((listing) => ({ slug: listing.slug })) ?? [];
}
export default async function ListingPage({ params }: { params: { slug: string } }) {
const { data: listing } = await supabase
.from('listings')
.select('*, categories(*), reviews(*)')
.eq('slug', params.slug)
.single();
// Server Component -- pas de JavaScript client envoyé pour cela
return <ListingDetail listing={listing} />;
}
Les Server Components sont l'autre grand avantage. Les pages de détails des listes sont principalement du contenu statique -- nom, description, photos, avis. Il n'y a aucune raison d'envoyer l'exécution de React au client pour cela. Les Server Components se rendent sur le serveur et envoient du HTML pur. Vos pages de listes se chargent rapidement et votre paquet JavaScript reste petit.
Nous utilisons les Client Components avec parcimonie : la barre de recherche, les cartes interactives, les formulaires de réservation et tout ce qui nécessite une interaction utilisateur. Tout le reste reste sur le serveur.
Pourquoi pas Astro ?
Astro est fantastique pour les annuaires riches en contenu où l'interactivité est minimale. Nous l'avons utilisé pour les sites de documentation et les projets centrés sur le contenu. Mais les sites de marché ont besoin d'états authentifiés, de fonctionnalités en temps réel et de formulaires complexes. Next.js gère ceux-ci plus naturellement. Si votre annuaire est principalement en lecture seule (pensez : un annuaire commercial statique), Astro vaut la peine d'être considéré -- consultez nos capacités de développement Astro.

Couche 2 : Base de données -- Supabase PostgreSQL
C'est le choix le plus partial de la pile, et celui dont je suis le plus confiant. Supabase vous donne PostgreSQL avec toutes ses extensions -- et pour les sites d'annuaires/marchés, trois extensions importent énormément : pgvector, PostGIS, et la recherche en texte intégral intégrée de PostgreSQL.
Sur nos projets d'annuaire, nous gérons 253 000+ enregistrements dans Supabase. Cela inclut les listes, les profils utilisateur, les avis, les réservations et les données d'abonnement. PostgreSQL gère cela sans transpirer -- il est conçu pour des ensembles de données des ordres de grandeur plus grands.
L'insight réel est ceci : en gardant la recherche en texte intégral, les embeddings vectoriels et les données géographiques dans la même base de données, vous évitez la complexité architecturale de synchroniser les données entre plusieurs services. Vous n'avez pas besoin d'Elasticsearch pour la recherche textuelle. Vous n'avez pas besoin de Pinecone pour la recherche vectorielle. Vous n'avez pas besoin d'un service géo séparé. Une base de données. Une source unique de vérité.
-- Une seule requête qui combine la recherche textuelle, la similarité vectorielle et la proximité géographique
SELECT
l.id,
l.name,
l.description,
ts_rank(l.search_vector, plainto_tsquery('english', 'family therapist')) AS text_rank,
1 - (l.embedding <=> $1::vector) AS semantic_similarity,
ST_Distance(
l.location::geography,
ST_MakePoint(-97.7431, 30.2672)::geography
) / 1609.34 AS distance_miles
FROM listings l
WHERE
l.search_vector @@ plainto_tsquery('english', 'family therapist')
AND ST_DWithin(
l.location::geography,
ST_MakePoint(-97.7431, 30.2672)::geography,
80467 -- 50 miles en mètres
)
ORDER BY
(text_rank * 0.3) + (semantic_similarity * 0.5) + ((1 - distance_miles/50) * 0.2) DESC
LIMIT 20;
C'est une seule requête. Classement en texte intégral, scoring de similarité sémantique et filtrage de distance géographique -- tout cela se passe dans PostgreSQL. Essayez de faire cela sur trois services séparés et de garder les résultats cohérents.
Pour une plongée plus profonde sur les options de base de données pour les annuaires, consultez notre comparaison CMS headless et base de données.
Supabase Row-Level Security
RLS mérite sa propre mention car elle résout un problème qui afflige les backends de marché : le contrôle d'accès aux données au niveau de la base de données. Au lieu d'écrire des vérifications d'autorisation dans chaque point d'extrémité d'API, vous définissez des politiques sur la base de données elle-même.
-- Les thérapeutes ne peuvent voir que leurs propres dossiers clients
CREATE POLICY "therapists_own_clients" ON client_records
FOR SELECT USING (
auth.uid() = therapist_id
OR auth.jwt() ->> 'role' = 'admin'
);
Même si vous avez un bug dans votre code API qui expose accidentellement une requête, RLS empêche l'accès non autorisé aux données. Pour les sites de marché gérant des données utilisateur sensibles, c'est non négociable.
Couche 3 : Authentification -- Supabase Auth
Puisque nous sommes déjà dans l'écosystème Supabase pour la base de données, utiliser Supabase Auth est un ajustement naturel. Mais la vraie raison pour laquelle nous l'utilisons pour les marchés est l'accès basé sur les rôles qui s'intègre directement avec RLS.
L'un de nos projets de marché exécute l'authentification basée sur les rôles sur trois types d'utilisateurs distincts : administrateurs, fournisseurs de services et clients. Chaque rôle voit des données différentes, a des permissions différentes et accède à des fonctionnalités différentes. Un autre projet exécute un système d'adhésion à 4 niveaux où chaque niveau déverrouille progressivement plus de fonctionnalités.
L'implémentation stocke le rôle de l'utilisateur dans les métadonnées de son JWT, ce qui signifie que les politiques RLS peuvent le référencer sans requêtes de base de données supplémentaires :
// Attribution de rôle lors de l'inscription
const { data, error } = await supabase.auth.signUp({
email,
password,
options: {
data: {
role: 'therapist',
tier: 'professional'
}
}
});
Supabase Auth supporte les fournisseurs OAuth (Google, Apple, etc.), les liens magiques et email/mot de passe -- tout immédiatement disponible. Pour les marchés B2C, la connexion sociale est pratiquement obligatoire. Nous avons vu les taux de conversion d'inscription augmenter de 30 à 40% lorsque Google OAuth est disponible aux côtés d'email/mot de passe.
Couche 4 : Paiements -- Stripe Connect
Le traitement des paiements est où les projets de marché deviennent vraiment compliqués. Il y a une grande différence entre « accepter un paiement » et « accepter un paiement, prélever une commission de plateforme, gérer les remboursements, gérer les abonnements sur 30 pays, et traiter les devises sans décimales ».
Stripe Connect gère le flux de paiement du marché -- la division entre la plateforme et le fournisseur de services. L'un de nos projets traite les commissions sur chaque transaction, en acheminant automatiquement les frais de la plateforme et la part du fournisseur.
Mais le côté abonnement est où cela devient intéressant. Nous exécutons un système d'abonnement à 4 niveaux avec tarification régionale sur 30+ pays. Cela signifie maintenir des objets de prix Stripe séparés pour différentes régions de devises.
Le bug de devises sans décimales
C'est une histoire que je partage parce qu'elle nous a sauvés (ainsi que notre client) de l'argent réel. Stripe gère la plupart des devises dans leur unité la plus petite -- donc 10,00 $ USD est 1000 (centimes). Mais certaines devises comme le Yen japonais (JPY) et le Won coréen (KRW) n'ont pas d'unités décimales. ¥1000 est juste 1000, pas 100000.
Si votre code multiplie aveuglément par 100 pour convertir en unité la plus petite, vous facturerez aux utilisateurs japonais 100 fois le montant prévu. Nous l'avons attrapé en test, mais j'ai vu des marchés de production qui ne l'ont pas fait.
const ZERO_DECIMAL_CURRENCIES = [
'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW',
'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'
];
function formatAmountForStripe(amount: number, currency: string): number {
if (ZERO_DECIMAL_CURRENCIES.includes(currency.toUpperCase())) {
return Math.round(amount);
}
return Math.round(amount * 100);
}
Exclusions d'essai régional
Un autre problème : nous avons dû exclure certains pays d'Asie du Sud-Est des offres d'essai gratuit parce que les taux de fraude rendaient les essais économiquement non viables dans ces régions. L'API de Stripe vous permet de configurer cela avec des vérifications de localisation fiscale des clients, mais vous devez savoir que c'est un problème en premier lieu. C'est le genre de chose que vous n'apprenez qu'en exécutant un marché multi-pays en production.
Couche 5 : Recherche -- Le modèle de triple recherche
C'est probablement le modèle architectural le plus précieux de cet article. La plupart des sites d'annuaires offrent une recherche textuelle basique. Les bons ajoutent le filtrage de localisation. Nous exécutons les trois types de recherche simultanément et fusionnons les résultats.
Recherche en texte intégral (PostgreSQL tsvector) : Gère la correspondance de mots-clés exacts et enracinés. Quand quelqu'un cherche « plombier », cela correspond également à « plomberie ». Rapide, bien compris, intégré dans Postgres.
Recherche sémantique (pgvector + embeddings Claude) : Gère les requêtes basées sur le sens. « Quelqu'un qui peut m'aider à me sentir moins anxieux au sujet de ma relation » ne contient pas le mot « thérapeute », mais la recherche sémantique comprend l'intention. Nous générons des embeddings pour chaque liste en utilisant l'API Claude et les stockons en tant que vecteurs dans pgvector.
Recherche géographique (PostGIS) : Gère les requêtes de proximité. « À moins de 25 miles du centre-ville de Chicago » devient une requête spatiale qui est indexée et rapide.
La fusion est où cela devient intéressant. Nous pondérons chaque type de recherche différemment en fonction de la requête :
interface SearchWeights {
textWeight: number;
semanticWeight: number;
geoWeight: number;
}
function calculateWeights(query: string, hasLocation: boolean): SearchWeights {
const isNaturalLanguage = query.split(' ').length > 4;
if (hasLocation && isNaturalLanguage) {
return { textWeight: 0.2, semanticWeight: 0.5, geoWeight: 0.3 };
} else if (hasLocation) {
return { textWeight: 0.4, semanticWeight: 0.2, geoWeight: 0.4 };
} else if (isNaturalLanguage) {
return { textWeight: 0.2, semanticWeight: 0.7, geoWeight: 0.1 };
}
return { textWeight: 0.7, semanticWeight: 0.2, geoWeight: 0.1 };
}
Les requêtes courtes par mots-clés s'appuient sur la recherche en texte intégral. Les requêtes plus longues en langage naturel s'appuient sur la recherche sémantique. Les requêtes avec une composante de localisation augmentent le poids géographique. L'un de nos sites d'annuaire exécute ce modèle triple sur 137K+ listes, et les résultats de recherche sont notablement meilleurs que les concurrents utilisant la correspondance textuelle basique.
Couche 6 : Médias -- Supabase Storage + Next.js Image
Les sites d'annuaires sont riches en images. Photos de listes, photos de profil, logos -- cela s'accumule. Nous utilisons Supabase Storage pour les uploads et le composant <Image> de Next.js pour une livraison optimisée.
La configuration clé est de configurer des buckets Supabase Storage avec des politiques d'accès appropriées (publique pour les photos de listes, privée pour les documents utilisateur) et d'utiliser l'optimisation d'image Next.js pour servir les formats WebP/AVIF aux bonnes dimensions :
<Image
src={`${process.env.NEXT_PUBLIC_SUPABASE_URL}/storage/v1/object/public/listings/${listing.image_path}`}
alt={listing.name}
width={800}
height={600}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
loading="lazy"
/>
Next.js gère la conversion de format, le redimensionnement et la mise en cache automatiquement lorsque déployé sur Vercel. Nous avons observé des réductions de charge utile d'images de 60 à 70% par rapport à la livraison directe des uploads originaux.
Couche 7 : Hébergement -- Vercel
Tous nos sites d'annuaires et de marchés de production s'exécutent sur Vercel. La raison est simple : Vercel est où Next.js fonctionne mieux. ISR, Server Components, edge middleware, URLs de prévisualisation -- tout fonctionne sans configuration.
Pour les sites d'annuaires spécifiquement, le réseau edge importe. Un utilisateur à Tokyo cherchant un annuaire devrait obtenir les pages de listes mises en cache à partir d'un nœud edge à proximité, pas d'un serveur en Virginie. Le edge caching de Vercel rend cela automatique pour les pages ISR.
Les déploiements de prévisualisation sont aussi énormes pour les projets de marché avec de multiples parties prenantes. Chaque pull request obtient sa propre URL. Le client peut examiner la nouvelle interface de recherche sur une URL réelle avec des données réelles avant que quoi que ce soit ne se retrouve en production.
Le plan Pro de Vercel à 20 $/mois par membre d'équipe couvre la plupart des projets d'annuaire. Les sites plus grands (100K+ pages) peuvent avoir besoin du plan Entreprise pour des limites ISR plus élevées et un support dédié.
Couche 8 : Email -- Brevo API
L'email dans les projets de marché se divise en deux catégories : transactionnel (confirmations de réservation, réinitialisations de mot de passe, reçus de paiement) et marketing (bulletins d'information, annonces de fonctionnalités, réengagement).
Nous utilisons Brevo (anciennement Sendinblue) pour les deux, appelé depuis les API routes Next.js :
// app/api/send-booking-confirmation/route.ts
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
const { to, bookingDetails } = await request.json();
const response = await fetch('https://api.brevo.com/v3/smtp/email', {
method: 'POST',
headers: {
'api-key': process.env.BREVO_API_KEY!,
'content-type': 'application/json',
},
body: JSON.stringify({
to: [{ email: to }],
templateId: 12, // Modèle de confirmation de réservation
params: bookingDetails,
}),
});
return NextResponse.json({ success: response.ok });
}
Le tier gratuit de Brevo gère 300 emails/jour, ce qui est suffisant pour les marchés en début de phase. Leurs plans payants commencent à 9 $/mois pour 5 000 emails. Comparé à SendGrid ou Mailgun, nous avons trouvé les taux de livraison de Brevo comparables et la tarification plus prévisible pour les projets en croissance.
Couche 9 : IA -- Claude API
L'IA n'est pas un gimmick dans notre pile d'annuaire -- c'est un composant d'infrastructure fondamentale qui gère trois emplois distincts.
Embeddings de recherche sémantique : Chaque liste obtient un embedding généré par Claude qui capture son sens. Cela alimente la couche de recherche sémantique décrite ci-dessus.
Enrichissement de contenu : Pour les annuaires avec des listes soumises par l'utilisateur, la qualité varie énormément. Nous utilisons Claude pour normaliser les descriptions, extraire les données structurées (heures, spécialités, zones de service), et générer des résumés SEO-friendly.
Fonctionnalités interactives : L'un de nos projets exécute ce que nous appelons un « Oracle Council » -- cinq personnalités IA distinctes que les utilisateurs peuvent consulter pour différents types de conseils. Chaque personnalité a son propre prompt système, personnalité et domaine d'expertise. C'est un peu farfelu, mais cela stimule l'engagement significatif et est l'une des fonctionnalités les plus populaires du site.
Tarification de l'API Claude à partir de 2025-2026 : Claude 3.5 Sonnet coûte 3 $ par million de tokens d'entrée et 15 $ par million de tokens de sortie. Pour la génération d'embeddings sur un annuaire de 100K listes, le coût unique est d'environ 50-80 $. Les coûts continus pour les requêtes de recherche et les interactions de chatbot s'élèvent généralement à 100-300 $/mois selon le trafic.
Couche 10 : Surveillance -- Vercel Analytics + PostHog
Vous avez besoin de deux types de surveillance pour les sites d'annuaires : les métriques de performance et l'analyse du comportement des utilisateurs.
Vercel Analytics vous donne Web Vitals (LCP, CLS, INP), le suivi des utilisateurs réels et les données de trafic. Il est intégré dans le tableau de bord Vercel et ne nécessite aucune configuration. Pour les sites d'annuaires, nous surveillons de près LCP sur les pages de listes -- s'il dépasse 2,5 secondes, nous savons que quelque chose ne va pas avec notre configuration ISR ou notre optimisation d'images.
PostHog gère l'analyse du produit : quelles requêtes de recherche ne retournent aucun résultat (pour que nous sachions quelles lacunes de contenu combler), quelles catégories de listes obtiennent le plus de vues, où les utilisateurs abandonnent dans la réservation ou le flux d'inscription. Le tier gratuit de PostHog couvre jusqu'à 1 million d'événements par mois, ce qui gère la plupart des marchés en début de phase.
La combinaison vous donne à la fois « le site est-il rapide ? » et « les utilisateurs trouvent-ils ce qu'ils cherchent ? » -- deux questions très différentes mais tout aussi importantes.
Tableau de comparaison de la pile complète
| Couche | Notre choix | Alternative | Pourquoi nous avons choisi le nôtre |
|---|---|---|---|
| Frontend | Next.js 15 | Astro, Remix | ISR pour 100K+ pages |
| Base de données | Supabase PostgreSQL | PlanetScale, Neon | pgvector + PostGIS dans une seule DB |
| Auth | Supabase Auth | Clerk, Auth.js | Intégration native RLS |
| Paiements | Stripe Connect | Paddle, LemonSqueezy | Divisions de marché, multi-devises |
| Recherche | Modèle triple (in-DB) | Algolia, Elasticsearch | Pas de sync externe, coût inférieur |
| Médias | Supabase Storage | Cloudinary, S3 | Même écosystème, facturation plus simple |
| Hébergement | Vercel | Netlify, AWS Amplify | Meilleur support ISR pour Next.js |
| Brevo API | SendGrid, Resend | Ratio prix/délivrabilité | |
| IA | Claude API | OpenAI, Gemini | Meilleur raisonnement pour tâches de contenu |
| Surveillance | Vercel + PostHog | Datadog, Mixpanel | Les tiers gratuits couvrent la croissance précoce |
Ce que cette pile coûte en production
Parlons des chiffres réels pour un site d'annuaire avec ~50K listes et trafic modéré (50K visiteurs mensuels) :
| Service | Plan | Coût mensuel |
|---|---|---|
| Vercel | Pro | 20 $ |
| Supabase | Pro | 25 $ |
| Stripe | Pay-as-you-go | 2,9 % + 30¢ par transaction |
| Brevo | Starter | 9 $ |
| Claude API | Basé sur l'utilisation | ~150 $ |
| PostHog | Tier gratuit | 0 $ |
| Coûts fixes totaux | ~204 $/mois |
C'est remarquablement abordable pour une plateforme de marché de production. Le plan Pro de Supabase vous donne 8 Go d'espace de base de données, 250 Go de bande passante et 100 Go de stockage -- plus que suffisant pour un annuaire avec 50K listes.
À mesure que vous évoluez au-delà de 100K listes et vers un trafic plus élevé, attendez-vous à ce que les coûts augmentent à environ 500-800 $/mois. Toujours dramatiquement moins cher que l'approche ancienne d'exécution de serveurs dédiés, de clusters Elasticsearch gérés et de bases de données vectorielles séparées.
Si vous planifiez un projet d'annuaire ou de marché et souhaitez comprendre la tarification plus en détail, consultez notre page de tarification ou contactez-nous pour une estimation spécifique au projet.
FAQ
Quelle est la meilleure base de données pour un site d'annuaire en 2026 ?
PostgreSQL via Supabase est notre meilleure recommandation. La combinaison de pgvector pour la recherche sémantique, PostGIS pour les requêtes géographiques et la recherche en texte intégral intégrée signifie que vous pouvez gérer les trois dimensions de recherche sans services externes. Avec 253K+ enregistrements sur nos projets de production, elle gère les données à l'échelle d'un annuaire sans problème. Les alternatives comme PlanetScale (basées sur MySQL) manquent de support PostGIS, rendant la recherche géographique beaucoup plus difficile.
Next.js peut-il gérer 100 000+ pages pour un site d'annuaire ?
Oui, mais vous avez besoin d'ISR (Incremental Static Regeneration). Vous ne générez pas toutes les 100K pages au moment de la compilation. Au lieu de cela, vous pré-générez vos pages à plus fort trafic (peut-être les top 1 000-5 000) et laissez ISR générer le reste à la demande. Nous avons fait cela avec 137K pages en production. La clé est de définir les intervalles de revalidation appropriés -- nous utilisons 3600 secondes (1 heure) pour les pages de listes et des intervalles plus courts pour les pages de catégorie/recherche.
Comment fonctionne la recherche sémantique dans un site d'annuaire ?
Chaque liste est convertie en un vecteur numérique (un « embedding ») qui capture son sens en utilisant un modèle IA comme Claude. Quand un utilisateur recherche en langage naturel -- « quelqu'un qui aide les enfants avec le TDAH » -- cette requête est également convertie en un vecteur. La base de données trouve les listes dont les vecteurs sont mathématiquement proches du vecteur de la requête en utilisant l'opérateur de similarité cosinus de pgvector. Cela fonctionne même si la liste ne contient pas les mots exacts de la requête de recherche.
Stripe Connect est-il nécessaire pour un marché, ou puis-je utiliser Stripe ordinaire ?
Si votre marché implique des paiements entre acheteurs et vendeurs (ou clients et fournisseurs de services), vous avez besoin de Stripe Connect. Stripe ordinaire vous permet uniquement d'accepter des paiements sur votre propre compte. Connect gère la division -- en prélevant une commission de la plateforme et en acheminant le reste au fournisseur de services. Il gère également les rapports 1099 pour les vendeurs basés aux États-Unis, ce qui est une obligation de conformité que vous ne voulez pas construire vous-même.
Combien coûte la construction d'un site d'annuaire à partir de zéro ?
En utilisant la pile décrite ici, vos coûts d'infrastructure continus commencent à environ 200 $/mois pour un annuaire de taille moyenne. Les coûts de développement varient largement en fonction des fonctionnalités, mais un annuaire prêt pour la production avec recherche, comptes utilisateur et gestion des listes nécessite généralement 8-16 semaines de travail. Un marché complet avec paiements, réservations et abonnements ajoute 4-8 semaines supplémentaires. Vous pouvez explorer nos capacités de développement d'annuaires et de marchés pour plus de détails.
Devrais-je utiliser Algolia ou Elasticsearch à la place de la recherche dans la base de données ?
Pour la plupart des sites d'annuaires, non. La complexité de synchroniser les données entre votre base de données principale et un service de recherche séparé crée des bugs, ajoute de la latence et augmente les coûts. Algolia facture en fonction des opérations de recherche -- à grande échelle, cela devient coûteux rapidement (leur tarification commence à 1 $/1 000 requêtes de recherche sur le plan Build). Les capacités de recherche intégrées de PostgreSQL, en particulier combinées avec pgvector, gèrent bien la recherche à l'échelle d'un annuaire. L'exception : si vous avez besoin de tolérance aux fautes de frappe et de filtrage à facettes avec des temps de réponse sub-10ms sur des millions d'enregistrements, Algolia vaut la complexité.
Quelle est la différence entre la construction d'un annuaire et un marché ?
Un annuaire énumère les choses et permet aux utilisateurs de les trouver. Un marché ajoute des transactions -- paiements, réservations, commissions et souvent des interactions bidirectionnelles entre fournisseurs et consommateurs. La pile technologique est largement la même, mais les marchés ajoutent Stripe Connect (ou équivalent), des rôles auth plus complexes et des flux d'email transactionnel. Le schéma de base de données devient également plus complexe avec les tables de commandes, factures et suivi des paiements.
Puis-je ajouter des fonctionnalités IA à un site d'annuaire existant ?
Absolument. La couche IA dans notre pile est supplémentaire, pas fondamentale. Vous pouvez ajouter la recherche sémantique en générant des embeddings pour vos listes existantes (un travail batch unique), en les stockant dans une colonne pgvector et en ajoutant un point de terminaison de recherche sémantique aux côtés de votre recherche textuelle existante. Les fonctionnalités d'enrichissement de contenu et de chatbot peuvent être ajoutées en tant que routes API indépendantes. La partie la plus difficile est généralement la génération d'embeddings pour un grand ensemble de données existant -- budget quelques heures de temps de traitement et 50-100 $ de coûts API pour 100K listes.