1. Avant de commencer
Dans cet atelier de programmation, vous allez apprendre à intégrer Firebase à une application Web Next.js appelée Friendly Eats, qui est un site Web d'avis sur des restaurants.

L'application Web terminée offre des fonctionnalités utiles qui montrent comment Firebase peut vous aider à créer des applications Next.js. Ces fonctionnalités incluent les suivantes :
- Compilation et déploiement automatiques : cet atelier de programmation utilise Firebase App Hosting pour compiler et déployer automatiquement votre code Next.js chaque fois que vous effectuez un push vers une branche configurée.
- Connexion et déconnexion : l'application Web terminée vous permet de vous connecter avec Google et de vous déconnecter. La connexion et la persistance des utilisateurs sont entièrement gérées via Firebase Authentication.
- Images : l'application Web terminée permet aux utilisateurs connectés d'importer des images de restaurants. Les composants Image sont stockés dans Cloud Storage pour Firebase. Le SDK JavaScript Firebase fournit une URL publique pour les images importées. Cette URL publique est ensuite stockée dans le document du restaurant concerné dans Cloud Firestore.
- Avis : l'application Web terminée permet aux utilisateurs connectés de publier des avis sur des restaurants, composés d'une note et d'un message textuel. Les informations sur les avis sont stockées dans Cloud Firestore.
- Filtres : l'application Web terminée permet aux utilisateurs connectés de filtrer la liste des restaurants par catégorie, emplacement et prix. Vous pouvez également personnaliser la méthode de tri utilisée. Les données sont accessibles depuis Cloud Firestore, et les requêtes Firestore sont appliquées en fonction des filtres utilisés.
Prérequis
- Un compte GitHub
- Connaissances de Next.js et JavaScript
Points abordés
- Utiliser Firebase avec le routeur d'application Next.js et le rendu côté serveur
- Comment conserver des images dans Cloud Storage for Firebase.
- Lire et écrire des données dans une base de données Cloud Firestore
- Utiliser la connexion avec Google avec le SDK JavaScript Firebase
Prérequis
- Git
- Une version stable récente de Node.js
- Un navigateur de votre choix, tel que Google Chrome
- Un environnement de développement avec un éditeur de code et un terminal
- Un compte Google pour créer et gérer votre projet Firebase
- La possibilité de passer au forfait Blaze pour votre projet Firebase
2. Configurer votre environnement de développement et votre dépôt GitHub
Cet atelier de programmation fournit la codebase de démarrage de l'application et s'appuie sur la CLI Firebase.
Créer un dépôt GitHub
Le code source de l'atelier de programmation est disponible à l'adresse https://github.com/firebase/friendlyeats-web. Le dépôt contient des exemples de projets pour plusieurs plates-formes. Toutefois, cet atelier de programmation n'utilise que le répertoire nextjs-start. Notez les répertoires suivants :
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Copiez le dossier nextjs-start dans votre propre dépôt :
- À l'aide d'un terminal, créez un dossier sur votre ordinateur et accédez au nouveau répertoire :
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web - Utilisez le package npm giget pour récupérer uniquement le dossier
nextjs-start:npx giget@latest "gh:firebase/friendlyeats-web/nextjs-start#master" . --install - Suivez les modifications localement avec Git :
git init git add . git commit -m "Codelab starting point" git branch -M main - Créez un dépôt GitHub : https://github.com/new. Donnez-lui le nom de votre choix.
- Selon la façon dont vous vous authentifiez auprès de GitHub (HTTPS ou SSH), copiez la nouvelle URL créée par GitHub :
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.gitougit@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
- Transférez les modifications locales vers votre nouveau dépôt GitHub en exécutant la commande suivante. Remplacez l'espace réservé
<REPOSITORY_URL>par l'URL de votre dépôt.git remote add origin <REPOSITORY_URL> git push -u origin main - Le code de démarrage devrait maintenant s'afficher dans votre dépôt GitHub.
Installer ou mettre à jour la CLI Firebase
Exécutez la commande suivante pour vérifier que la CLI Firebase est installée et qu'il s'agit de la version 14.1.0 ou d'une version ultérieure :
firebase --version
Si vous voyez une version antérieure ou si la CLI Firebase n'est pas installée, exécutez la commande d'installation :
npm install -g firebase-tools@latest
Si vous ne parvenez pas à installer la CLI Firebase en raison d'erreurs d'autorisation, consultez la documentation npm ou utilisez une autre option d'installation.
Se connecter à Firebase
- Exécutez la commande suivante pour vous connecter à la CLI Firebase :
firebase login
- Selon que vous souhaitez ou non que Firebase collecte des données, saisissez
YouN. - Dans votre navigateur, sélectionnez votre compte Google, puis cliquez sur Autoriser.
3. Configurer votre projet Firebase
Dans cette section, vous allez configurer un projet Firebase et lui associer une application Web Firebase. Vous allez également configurer les services Firebase utilisés par l'exemple d'application Web.
Créer un projet Firebase
- Connectez-vous à la console Firebase avec le même compte Google que celui utilisé à l'étape précédente.
- Cliquez sur le bouton pour créer un projet, puis saisissez un nom de projet (par exemple,
FriendlyEats Codelab).
- Cliquez sur Continuer.
- Si vous y êtes invité, lisez et acceptez les Conditions d'utilisation de Firebase, puis cliquez sur Continuer.
- (Facultatif) Activez l'assistance IA dans la console Firebase (appelée "Gemini dans Firebase").
- Pour cet atelier de programmation, vous n'avez pas besoin de Google Analytics. Désactivez donc l'option Google Analytics.
- Cliquez sur Créer un projet, attendez que votre projet soit provisionné, puis cliquez sur Continuer.
Passer à un forfait Firebase supérieur
Pour utiliser Firebase App Hosting et Cloud Storage pour Firebase, votre projet Firebase doit être associé au forfait Blaze (paiement à l'usage), ce qui signifie qu'il est associé à un compte de facturation Cloud.
- Un compte de facturation Cloud nécessite un mode de paiement, comme une carte de crédit.
- Si vous débutez avec Firebase et Google Cloud, vérifiez si vous êtes éligible à un crédit de 300 $ et à un compte de facturation Cloud d'essai sans frais.
- Si vous suivez cet atelier de programmation dans le cadre d'un événement, demandez à l'organisateur si des crédits Cloud sont disponibles.
Pour passer votre projet au forfait Blaze, procédez comme suit :
- Dans la console Firebase, sélectionnez Mettre à niveau votre forfait.
- Sélectionnez le forfait Blaze. Suivez les instructions à l'écran pour associer un compte de facturation Cloud à votre projet.
Si vous avez dû créer un compte de facturation Cloud dans le cadre de cette mise à niveau, vous devrez peut-être revenir au processus de mise à niveau dans la console Firebase pour la finaliser.
Ajouter une application Web à votre projet Firebase
- Accédez à la vue d'ensemble de votre projet Firebase, cliquez sur Ajouter une application, puis sur Web.
- Dans la zone de texte App nickname (Pseudo de l'application), saisissez un pseudo facile à mémoriser, par exemple
My Next.js app. - Laissez la case Configurer aussi Firebase Hosting pour cette application décochée.
- Cliquez sur Enregistrer l'application > Accéder à la console.
Configurer les services Firebase dans la console Firebase
Configurer l'authentification
- Dans le panneau de gauche de la console Firebase, développez Build, puis sélectionnez Authentication.
- Cliquez sur Commencer.
- Dans la colonne Fournisseurs de connexion, cliquez sur Google > Activer.
- Dans la zone de texte Nom public du projet, saisissez un nom facile à mémoriser, par exemple
My Next.js app. - Dans le menu déroulant Adresse e-mail d'assistance pour le projet, sélectionnez votre adresse e-mail.
- Cliquez sur Enregistrer.
Configurer Cloud Firestore
- Dans le panneau de gauche de la console Firebase, développez Build (Compilation), puis sélectionnez Firestore Database (Base de données Firestore).
- Cliquez sur Créer une base de données.
- Choisissez Édition standard, puis cliquez sur Suivant.
- Ne modifiez pas l'ID de la base de données. Laissez-le défini sur
(default). - Sélectionnez un emplacement pour votre base de données, puis cliquez sur Suivant.
Pour une application réelle, vous devez choisir un emplacement proche de vos utilisateurs. - Cliquez sur Démarrer en mode test. Lisez la clause de non-responsabilité concernant les règles de sécurité.
Plus tard dans cet atelier de programmation, vous ajouterez des règles de sécurité pour sécuriser vos données. Ne distribuez pas et n'exposez pas publiquement une application sans ajouter de règles de sécurité pour votre base de données. - Cliquez sur Créer.
Configurer Cloud Storage for Firebase
- Dans le panneau de gauche de la console Firebase, développez Build, puis sélectionnez Storage.
- Cliquez sur Commencer.
- Sélectionnez un emplacement pour votre bucket Storage par défaut.
Les buckets situés dansUS-WEST1,US-CENTRAL1etUS-EAST1peuvent bénéficier du niveau d'accès sans frais de Google Cloud Storage. Les buckets situés dans tous les autres emplacements sont soumis aux tarifs et conditions d'utilisation de Google Cloud Storage. - Cliquez sur Démarrer en mode test. Lisez la clause de non-responsabilité concernant les règles de sécurité.
Plus tard dans cet atelier de programmation, vous ajouterez des règles de sécurité pour protéger vos données. Ne distribuez pas et n'exposez pas publiquement une application sans ajouter de règles de sécurité pour votre bucket Storage. - Cliquez sur Créer.
Déployer des règles de sécurité
Le code comporte déjà des ensembles de règles de sécurité pour Firestore et Cloud Storage for Firebase. Une fois les règles de sécurité déployées, les données de votre base de données et de votre bucket sont mieux protégées contre une utilisation abusive.
- Dans votre terminal, configurez la CLI pour qu'elle utilise le projet Firebase que vous avez créé précédemment :
Lorsque vous êtes invité à saisir un alias, saisissezfirebase use --add
friendlyeats-codelab. - Pour déployer ces règles de sécurité (ainsi que les index qui seront nécessaires plus tard), exécutez cette commande dans votre terminal :
firebase deploy --only firestore,storage
- Si vous êtes invité à confirmer l'opération (
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?"), appuyez surEnterpour sélectionner Yes (Oui).
4. Examiner le codebase de démarrage
Dans cette section, vous allez examiner quelques zones de la codebase de démarrage de l'application auxquelles vous ajouterez des fonctionnalités dans cet atelier de programmation.
Structure des dossiers et des fichiers
Le tableau suivant présente la structure des dossiers et des fichiers de l'application :
Dossiers et fichiers | Description |
| Composants React pour les filtres, les en-têtes, les détails des restaurants et les avis |
| Fonctions utilitaires qui ne sont pas nécessairement liées à React ou Next.js |
| Code spécifique à Firebase et configuration de Firebase |
| Éléments statiques de l'application Web, comme les icônes |
| Routage avec le routeur d'application Next.js |
| Dépendances du projet avec npm |
| Configuration spécifique à Next.js (les actions du serveur sont activées) |
| Configuration du service de langage JavaScript |
Composants serveur et client
Il s'agit d'une application Web Next.js qui utilise App Router. Le rendu côté serveur est utilisé dans toute l'application. Par exemple, le fichier src/app/page.js est un composant serveur responsable de la page principale. Le fichier src/components/RestaurantListings.jsx est un composant client indiqué par la directive "use client" au début du fichier.
Instructions d'importation
Vous remarquerez peut-être des instructions d'importation comme celles-ci :
import RatingPicker from "@/src/components/RatingPicker.jsx";
L'application utilise le symbole @ pour éviter les chemins d'importation relatifs peu pratiques, ce qui est possible grâce aux alias de chemin.
API spécifiques à Firebase
Tout le code de l'API Firebase est encapsulé dans le répertoire src/lib/firebase. Les composants React individuels importent ensuite les fonctions encapsulées à partir du répertoire src/lib/firebase, plutôt que d'importer directement les fonctions Firebase.
Données fictives
Les données fictives sur les restaurants et les avis sont contenues dans le fichier src/lib/randomData.js. Les données de ce fichier sont assemblées dans le code du fichier src/lib/fakeRestaurants.js.
5. Créer un backend App Hosting
Dans cette section, vous allez configurer un backend App Hosting pour surveiller une branche de votre dépôt Git.
À la fin de cette section, vous disposerez d'un backend App Hosting connecté à votre dépôt GitHub, qui recompilera et déploiera automatiquement une nouvelle version de votre application chaque fois que vous enverrez un nouveau commit à votre branche main.
Créer un backend
- Accédez à la page App Hosting dans la console Firebase.
- Cliquez sur Commencer pour lancer le processus de création du backend.
- Sélectionnez une région. Pour une application réelle, vous choisiriez la région la plus proche de vos utilisateurs.
- Suivez les instructions de l'étape Importer un dépôt GitHub pour configurer l'authentification GitHub.
- Dans Dépôt, sélectionnez Accorder l'accès à un nouveau dépôt dans GitHub, puis suivez les instructions pour activer l'accès au dépôt GitHub que vous avez créé précédemment.
- Cliquez sur Actualiser la liste pour actualiser la liste, puis sélectionnez votre dépôt et cliquez sur Suivant.
- Définissez les paramètres de déploiement :
- Définissez la branche active sur
main. - Conservez le répertoire racine
/. - Activez les déploiements automatiques.
- Définissez la branche active sur
- Nommez votre backend
friendlyeats-codelab, puis cliquez sur Suivant. - Dans Associer une application Web Firebase, choisissez Sélectionner une application Web Firebase existante, puis sélectionnez l'application que vous avez ajoutée dans la liste.
- Cliquez sur Terminer et déployer. Vous êtes redirigé vers une nouvelle page où vous pouvez voir l'état de votre nouveau backend App Hosting.
- Cliquez sur Afficher pour afficher plus d'informations sur votre déploiement App Hosting, y compris l'état du déploiement, les journaux et les détails d'utilisation.
- Une fois le déploiement terminé, cliquez sur l'URL de votre site sous Domaines pour l'ouvrir. La propagation DNS peut prendre quelques minutes.
- Petit problème… Lorsque vous chargez la page, un message d'erreur s'affiche : "Application error: a server-side exception has occurred (see the server logs for more information)."
- Dans la console Firebase, consultez l'onglet Journaux de votre backend App Hosting. Un journal "Error: not implemented " s'affiche. Nous allons corriger cela à l'étape suivante, lorsque nous ajouterons l'authentification.
Vous avez déployé l'application Web initiale. Chaque fois que vous envoyez un nouveau commit vers la branche main de votre dépôt GitHub, vous verrez une nouvelle compilation et un nouveau déploiement commencer dans la console Firebase, et votre site sera automatiquement mis à jour une fois le déploiement terminé.
6. Ajouter l'authentification à l'application Web
Dans cette section, vous allez ajouter l'authentification à l'application Web pour pouvoir vous y connecter.
Ajouter un domaine autorisé
Firebase Authentication n'acceptera que les demandes de connexion provenant des domaines que vous autorisez. Ici, nous allons ajouter le domaine de votre backend App Hosting à la liste des domaines approuvés de votre projet.
- Ouvrez la page App Hosting, puis cliquez sur Afficher sous votre site déployé pour accéder à la page Présentation. Copiez le nom de domaine de votre backend App Hosting.
- Accédez à l'onglet Paramètres d'authentification, puis sélectionnez le projet auquel vous souhaitez ajouter un domaine autorisé. Ensuite, recherchez la section Domaines autorisés et cliquez dessus.
- Cliquez sur le bouton Ajouter un domaine.
- Saisissez le domaine de votre backend App Hosting.
- Cliquez sur Ajouter.
Implémenter les fonctions de connexion et de déconnexion
Dans le fichier src/lib/firebase/auth.js, remplacez les fonctions onAuthStateChanged, onIdTokenChanged, signInWithGoogle et signOut par le code suivant :
export function onAuthStateChanged(cb) {
return _onAuthStateChanged(auth, cb);
}
export function onIdTokenChanged(cb) {
return _onIdTokenChanged(auth, cb);
}
export async function signInWithGoogle() {
const provider = new GoogleAuthProvider();
try {
await signInWithPopup(auth, provider);
} catch (error) {
console.error("Error signing in with Google", error);
}
}
export async function signOut() {
try {
return auth.signOut();
} catch (error) {
console.error("Error signing out with Google", error);
}
}
Ce code utilise les API Firebase suivantes :
API Firebase | Description |
Ajoute un observateur pour les modifications de l'état de connexion de l'utilisateur. | |
Ajoute un observateur pour les modifications apportées au jeton d'ID de l'utilisateur. | |
Crée une instance de fournisseur d'authentification Google. | |
Démarre un flux d'authentification basé sur une boîte de dialogue. | |
Déconnecte l'utilisateur. |
Dans le fichier src/components/Header.jsx, le code appelle déjà les fonctions signInWithGoogle et signOut.
Envoyer l'état d'authentification au serveur
Pour transmettre l'état d'authentification au serveur, nous allons utiliser des cookies. Chaque fois que l'état d'authentification change dans le client, nous mettons à jour le cookie __session.
Dans src/components/Header.jsx, remplacez la fonction useUserSession par le code suivant :
function useUserSession(initialUser) {
useEffect(() => {
return onIdTokenChanged(async (user) => {
if (user) {
const idToken = await user.getIdToken();
await setCookie("__session", idToken);
} else {
await deleteCookie("__session");
}
if (initialUser?.uid === user?.uid) {
return;
}
window.location.reload();
});
}, [initialUser]);
return initialUser;
}
Lire l'état d'authentification sur le serveur
Nous allons utiliser FirebaseServerApp pour dupliquer l'état d'authentification du client sur le serveur.
Ouvrez src/lib/firebase/serverApp.js et remplacez la fonction getAuthenticatedAppForUser :
export async function getAuthenticatedAppForUser() {
const authIdToken = (await cookies()).get("__session")?.value;
// Firebase Server App is a new feature in the JS SDK that allows you to
// instantiate the SDK with credentials retrieved from the client & has
// other affordances for use in server environments.
const firebaseServerApp = initializeServerApp(
// https://github.com/firebase/firebase-js-sdk/issues/8863#issuecomment-2751401913
initializeApp(),
{
authIdToken,
}
);
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return { firebaseServerApp, currentUser: auth.currentUser };
}
Vérifier les modifications
La mise en page racine du fichier src/app/layout.js affiche l'en-tête et transmet l'utilisateur, s'il est disponible, en tant que propriété.
<Header initialUser={currentUser?.toJSON()} />
Cela signifie que le composant <Header> affiche les données utilisateur, si elles sont disponibles, pendant l'exécution du serveur. Si des mises à jour d'authentification sont effectuées pendant le cycle de vie de la page après le chargement de page initial, le gestionnaire onAuthStateChanged les gère.
Il est maintenant temps de déployer un nouveau build et de vérifier ce que vous avez créé.
- Créez un commit avec le message "Add authentication" et déployez-le dans votre dépôt GitHub.
git add . git commit -m "Add authentication" git push - Ouvrez la page App Hosting et, une fois le nouveau déploiement terminé, cliquez sur l'URL du site pour l'ouvrir.
- Tester l'authentification :
- Connectez-vous avec votre compte Google et vérifiez que votre nom à afficher apparaît dans l'en-tête après votre connexion.
- Déconnectez-vous, puis reconnectez-vous. Vous pouvez répéter cette étape avec différents utilisateurs.
- Facultatif : Effectuez un clic droit sur l'application Web, sélectionnez Afficher le code source de la page, puis recherchez le nom à afficher. Il apparaît dans la source HTML brute renvoyée par le serveur.
7. Afficher les informations sur le restaurant
L'application Web inclut des données fictives pour les restaurants et les avis.
Ajouter un ou plusieurs restaurants
Pour insérer des données de restaurant fictives dans votre base de données Cloud Firestore locale, procédez comme suit :
- Connectez-vous à l'application Web si ce n'est pas déjà fait. Sélectionnez ensuite
> Ajouter des exemples de restaurants. Notez qu'aucun restaurant ne s'affiche dans l'application Web Friendly Eats, car nous n'avons pas encore configuré le code de récupération des données. Nous allons corriger cela à l'étape suivante. - Dans la console Firebase, sur la page Firestore Database, sélectionnez restaurants. Vous voyez les documents de premier niveau de la collection "restaurants", chacun représentant un restaurant.
- Cliquez sur quelques documents pour explorer les propriétés d'un document de restaurant.
Afficher la liste des restaurants
Votre base de données Cloud Firestore contient désormais des restaurants que l'application Web Next.js peut afficher.
Pour définir le code de récupération des données, procédez comme suit :
- Dans le fichier
src/app/page.js, recherchez le composant serveur<Home />et examinez l'appel de la fonctiongetRestaurants, qui récupère une liste de restaurants au moment de l'exécution du serveur. Vous allez implémenter la fonctiongetRestaurantslors des prochaines étapes. - Dans le fichier
src/lib/firebase/firestore.js, remplacez les fonctionsapplyQueryFiltersetgetRestaurantspar le code suivant :
function applyQueryFilters(q, { category, city, price, sort }) {
if (category) {
q = query(q, where("category", "==", category));
}
if (city) {
q = query(q, where("city", "==", city));
}
if (price) {
q = query(q, where("price", "==", price.length));
}
if (sort === "Rating" || !sort) {
q = query(q, orderBy("avgRating", "desc"));
} else if (sort === "Review") {
q = query(q, orderBy("numRatings", "desc"));
}
return q;
}
export async function getRestaurants(db = db, filters = {}) {
let q = query(collection(db, "restaurants"));
q = applyQueryFilters(q, filters);
const results = await getDocs(q);
return results.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
// Only plain objects can be passed to Client Components from Server Components
timestamp: doc.data().timestamp.toDate(),
};
});
}
- Créez un commit avec le message "Read the list of restaurants from Firestore" (Lire la liste des restaurants depuis Firestore) et déployez-le dans votre dépôt GitHub.
git add . git commit -m "Read the list of restaurants from Firestore" git push - Ouvrez la page App Hosting dans la console Firebase et attendez que le nouveau déploiement soit terminé.
- Dans l'application Web, actualisez la page. Les images du restaurant s'affichent sous forme de tuiles sur la page.
Vérifier que les fiches de restaurant se chargent au moment de l'exécution du serveur
Lorsque vous utilisez le framework Next.js, il n'est pas toujours évident de savoir quand les données sont chargées au moment de l'exécution côté serveur ou côté client.
Pour vérifier que les fiches de restaurants se chargent au moment de l'exécution du serveur, procédez comme suit :
- Dans l'application Web, ouvrez les outils de développement et désactivez JavaScript.

- Actualisez l'application Web. Les fiches de restaurants se chargent toujours. Les informations sur le restaurant sont renvoyées dans la réponse du serveur. Lorsque JavaScript est activé, les informations sur le restaurant sont hydratées via le code JavaScript côté client.
- Dans les Outils de développement, réactivez JavaScript.
Écouter les mises à jour des restaurants avec les écouteurs d'instantanés Cloud Firestore
Dans la section précédente, vous avez vu comment l'ensemble initial de restaurants était chargé à partir du fichier src/app/page.js. Le fichier src/app/page.js est un composant serveur et est affiché sur le serveur, y compris le code de récupération des données Firebase.
Le fichier src/components/RestaurantListings.jsx est un composant client et peut être configuré pour hydrater le balisage affiché par le serveur.
Pour configurer le fichier src/components/RestaurantListings.jsx afin d'hydrater le balisage affiché par le serveur, procédez comme suit :
- Dans le fichier
src/components/RestaurantListings.jsx, observez le code suivant, qui est déjà écrit pour vous :
useEffect(() => {
return getRestaurantsSnapshot((data) => {
setRestaurants(data);
}, filters);
}, [filters]);
Ce code appelle la fonction getRestaurantsSnapshot(), qui est semblable à la fonction getRestaurants() que vous avez implémentée lors d'une étape précédente. Cependant, cette fonction d'instantané fournit un mécanisme de rappel qui est appelé chaque fois qu'une modification est apportée à la collection de restaurants.
- Dans le fichier
src/lib/firebase/firestore.js, remplacez la fonctiongetRestaurantsSnapshot()par le code suivant :
export function getRestaurantsSnapshot(cb, filters = {}) {
if (typeof cb !== "function") {
console.log("Error: The callback parameter is not a function");
return;
}
let q = query(collection(db, "restaurants"));
q = applyQueryFilters(q, filters);
return onSnapshot(q, (querySnapshot) => {
const results = querySnapshot.docs.map((doc) => {
return {
id: doc.id,
...doc.data(),
// Only plain objects can be passed to Client Components from Server Components
timestamp: doc.data().timestamp.toDate(),
};
});
cb(results);
});
}
- Dans le fichier
src/lib/firebase/firestore.js, remplacez la fonctiongetRestaurantSnapshotById()par le code suivant :
export function getRestaurantSnapshotById(restaurantId, cb) {
if (!restaurantId) {
console.log("Error: Invalid ID received: ", restaurantId);
return;
}
if (typeof cb !== "function") {
console.log("Error: The callback parameter is not a function");
return;
}
const docRef = doc(db, "restaurants", restaurantId);
return onSnapshot(docRef, (docSnap) => {
cb({
...docSnap.data(),
timestamp: docSnap.data().timestamp.toDate(),
});
});
}
Les modifications apportées sur la page Base de données Firestore sont désormais répercutées dans l'application Web en temps réel.
- Créez un commit avec le message "Listen for realtime restaurant updates" et déployez-le dans votre dépôt GitHub.
git add . git commit -m "Listen for realtime restaurant updates" git push - Ouvrez la page App Hosting dans la console Firebase et attendez que le nouveau déploiement soit terminé.
- Dans l'application Web, sélectionnez
> Add sample restaurants (Ajouter des exemples de restaurants). Si votre fonction d'instantané est correctement implémentée, les restaurants s'affichent en temps réel sans qu'il soit nécessaire d'actualiser la page.
8. Enregistrer les avis envoyés par les utilisateurs depuis l'application Web
- Dans le fichier
src/lib/firebase/firestore.js, remplacez la fonctionupdateWithRating()par le code suivant :
const updateWithRating = async (
transaction,
docRef,
newRatingDocument,
review
) => {
const restaurant = await transaction.get(docRef);
const data = restaurant.data();
const newNumRatings = data?.numRatings ? data.numRatings + 1 : 1;
const newSumRating = (data?.sumRating || 0) + Number(review.rating);
const newAverage = newSumRating / newNumRatings;
transaction.update(docRef, {
numRatings: newNumRatings,
sumRating: newSumRating,
avgRating: newAverage,
});
transaction.set(newRatingDocument, {
...review,
timestamp: Timestamp.fromDate(new Date()),
});
};
Ce code insère un nouveau document Firestore représentant le nouvel avis. Le code met également à jour le document Firestore existant qui représente le restaurant avec les chiffres actualisés du nombre d'avis et de la note moyenne calculée.
- Remplacez la fonction
addReviewToRestaurant()par le code suivant :
export async function addReviewToRestaurant(db, restaurantId, review) {
if (!restaurantId) {
throw new Error("No restaurant ID has been provided.");
}
if (!review) {
throw new Error("A valid review has not been provided.");
}
try {
const docRef = doc(collection(db, "restaurants"), restaurantId);
const newRatingDocument = doc(
collection(db, `restaurants/${restaurantId}/ratings`),
);
// corrected line
await runTransaction(db, (transaction) =>
updateWithRating(transaction, docRef, newRatingDocument, review),
);
} catch (error) {
console.error(
"There was an error adding the rating to the restaurant",
error,
);
throw error;
}
}
Implémenter une action de serveur Next.js
Une action de serveur Next.js fournit une API pratique pour accéder aux données de formulaire, comme data.get("text") pour obtenir la valeur textuelle de la charge utile d'envoi du formulaire.
Pour utiliser une action de serveur Next.js afin de traiter l'envoi du formulaire d'avis, procédez comme suit :
- Dans le fichier
src/components/ReviewDialog.jsx, recherchez l'attributactiondans l'élément<form>.
<form
action={handleReviewFormSubmission}
onSubmit={() => {
handleClose();
}}
>
La valeur de l'attribut action fait référence à une fonction que vous implémenterez à l'étape suivante.
- Dans le fichier
src/app/actions.js, remplacez la fonctionhandleReviewFormSubmission()par le code suivant :
export async function handleReviewFormSubmission(data) {
const { firebaseServerApp } = await getAuthenticatedAppForUser();
const db = getFirestore(firebaseServerApp);
await addReviewToRestaurant(db, data.get("restaurantId"), {
text: data.get("text"),
rating: data.get("rating"),
// This came from a hidden form field.
userId: data.get("userId"),
});
}
Ajouter des avis sur un restaurant
Vous avez implémenté la prise en charge de l'envoi d'avis. Vous pouvez maintenant vérifier que vos avis sont correctement insérés dans Cloud Firestore.
Pour ajouter un avis et vérifier qu'il est inséré dans Cloud Firestore, procédez comme suit :
- Créez un commit avec le message "Allow users to submit restaurant reviews" (Autoriser les utilisateurs à envoyer des avis sur les restaurants) et déployez-le dans votre dépôt GitHub.
git add . git commit -m "Allow users to submit restaurant reviews" git push - Ouvrez la page App Hosting dans la console Firebase et attendez que le nouveau déploiement soit terminé.
- Actualisez l'application Web, puis sélectionnez un restaurant sur la page d'accueil.
- Sur la page du restaurant, cliquez sur
. - Sélectionnez une note.
- Rédigez un avis.
- Cliquez sur Envoyer. Votre avis s'affiche en haut de la liste des avis.
- Dans Cloud Firestore, recherchez le document du restaurant que vous avez évalué dans le panneau Ajouter un document, puis sélectionnez-le.
- Dans le panneau Démarrer une collection, sélectionnez ratings.
- Dans le panneau Ajouter un document, recherchez le document que vous avez examiné pour vérifier qu'il a été inséré comme prévu.
9. Enregistrer les fichiers importés par l'utilisateur depuis l'application Web
Dans cette section, vous allez ajouter une fonctionnalité permettant de remplacer l'image associée à un restaurant lorsque vous êtes connecté. Vous importez l'image dans Firebase Storage et mettez à jour l'URL de l'image dans le document Cloud Firestore qui représente le restaurant.
Pour enregistrer les fichiers importés par l'utilisateur depuis l'application Web, procédez comme suit :
- Dans le fichier
src/components/Restaurant.jsx, observez le code qui s'exécute lorsqu'un utilisateur importe un fichier :
async function handleRestaurantImage(target) {
const image = target.files ? target.files[0] : null;
if (!image) {
return;
}
const imageURL = await updateRestaurantImage(id, image);
setRestaurantDetails({ ...restaurantDetails, photo: imageURL });
}
Aucune modification n'est nécessaire pour cette fonction, mais vous implémenterez le comportement de la fonction updateRestaurantImage() lors des prochaines étapes.
- Dans le fichier
src/lib/firebase/storage.js, remplacez les fonctionsupdateRestaurantImage()etuploadImage()par le code suivant :
export async function updateRestaurantImage(restaurantId, image) {
try {
if (!restaurantId) {
throw new Error("No restaurant ID has been provided.");
}
if (!image || !image.name) {
throw new Error("A valid image has not been provided.");
}
const publicImageUrl = await uploadImage(restaurantId, image);
await updateRestaurantImageReference(restaurantId, publicImageUrl);
return publicImageUrl;
} catch (error) {
console.error("Error processing request:", error);
}
}
async function uploadImage(restaurantId, image) {
const filePath = `images/${restaurantId}/${image.name}`;
const newImageRef = ref(storage, filePath);
await uploadBytesResumable(newImageRef, image);
return await getDownloadURL(newImageRef);
}
La fonction updateRestaurantImageReference() est déjà implémentée pour vous. Cette fonction met à jour un document de restaurant existant dans Cloud Firestore avec une URL d'image mise à jour.
Vérifier la fonctionnalité d'importation d'images
Pour vérifier que l'image est importée comme prévu, procédez comme suit :
- Créez un commit avec le message "Allow users to change each restaurants' photo" (Autoriser les utilisateurs à modifier la photo de chaque restaurant) et transférez-le vers votre dépôt GitHub.
git add . git commit -m "Allow users to change each restaurants' photo" git push - Ouvrez la page App Hosting dans la console Firebase et attendez que le nouveau déploiement soit terminé.
- Dans l'application Web, vérifiez que vous êtes connecté, puis sélectionnez un restaurant.
- Cliquez sur
et importez une image depuis votre système de fichiers. Votre image quitte votre environnement local et est importée dans Cloud Storage. L'image s'affiche immédiatement après l'importation. - Accédez à Cloud Storage for Firebase.
- Accédez au dossier qui représente le restaurant. L'image que vous avez importée existe dans le dossier.

10. Résumer des avis sur des restaurants avec l'IA générative
Dans cette section, vous allez ajouter une fonctionnalité de résumé des avis pour qu'un utilisateur puisse rapidement comprendre ce que tout le monde pense d'un restaurant sans avoir à lire tous les avis.
Stocker une clé API Gemini dans Cloud Secret Manager
- Pour utiliser l'API Gemini, vous avez besoin d'une clé API. Accédez à Google AI Studio et cliquez sur Créer une clé API.
- Nommez la clé comme vous le souhaitez. Si votre projet ne figure pas sous Sélectionner un projet importé, cliquez sur Importer un projet, cochez votre projet dans la liste, puis cliquez sur Importer. Enfin, sélectionnez-le sous Choisir un projet importé, puis cliquez sur Créer une clé.
- App Hosting s'intègre à Cloud Secret Manager pour vous permettre de stocker des valeurs sensibles telles que des clés API de manière sécurisée :
- Dans un terminal, exécutez la commande suivante pour créer un secret :
firebase apphosting:secrets:set GEMINI_API_KEY- Lorsque vous êtes invité à saisir la valeur du secret, copiez et collez votre clé API Gemini depuis Google AI Studio.
- Lorsqu'il vous est demandé si le nouveau secret est destiné à la production ou aux tests locaux, sélectionnez "Production".
- Lorsque vous êtes invité à accorder l'accès au secret au compte de service de votre backend, sélectionnez "Oui".
- Lorsque vous êtes invité à ajouter le nouveau secret à
apphosting.yaml, saisissezYpour accepter.
Votre clé API Gemini est désormais stockée de manière sécurisée dans Cloud Secret Manager et est accessible par votre backend App Hosting.
Implémenter le composant de résumé des avis
- Dans
src/components/Reviews/ReviewSummary.jsx, remplacez la fonctionGeminiSummarypar le code suivant :export async function GeminiSummary({ restaurantId }) { const { firebaseServerApp } = await getAuthenticatedAppForUser(); const reviews = await getReviewsByRestaurantId( getFirestore(firebaseServerApp), restaurantId ); const reviewSeparator = "@"; const prompt = ` Based on the following restaurant reviews, where each review is separated by a '${reviewSeparator}' character, create a one-sentence summary of what people think of the restaurant. Here are the reviews: ${reviews.map((review) => review.text).join(reviewSeparator)} `; try { if (!process.env.GEMINI_API_KEY) { // Make sure GEMINI_API_KEY environment variable is set: // https://genkit.dev/docs/get-started/ throw new Error( 'GEMINI_API_KEY not set. Set it with "firebase apphosting:secrets:set GEMINI_API_KEY"' ); } // Configure a Genkit instance. const ai = genkit({ plugins: [googleAI()], model: gemini20Flash, // set default model }); const { text } = await ai.generate(prompt); return ( <div className="restaurant__review_summary"> <p>{text}</p> <p>✨ Summarized with Gemini</p> </div> ); } catch (e) { console.error(e); return <p>Error summarizing reviews.</p>; } } - Créez un commit avec le message "Use AI to summarize reviews" et déployez-le dans votre dépôt GitHub.
git add . git commit -m "Use AI to summarize reviews" git push - Ouvrez la page App Hosting dans la console Firebase et attendez que le nouveau déploiement soit terminé.
- Ouvrez la page d'un restaurant. En haut de la page, vous devriez voir un résumé en une phrase de tous les avis de la page.
- Ajoutez un avis et actualisez la page. Le résumé devrait changer.
11. Annuler la publication de votre site App Hosting
Une fois cet atelier de programmation terminé, si vous ne comptez pas continuer à utiliser l'application, vous pouvez annuler sa publication pour vous assurer que personne n'accède à vos ressources Firestore, Storage et Gemini. Vous pouvez republier à tout moment.
Pour annuler la publication d'un site App Hosting :
- Ouvrez App Hosting dans la console Firebase.
- Recherchez le backend de votre application, puis cliquez sur Afficher.
- Dans la section Informations sur le backend, à côté de Domaines, cliquez sur Gérer. La page Domaines se charge.
- À côté de votre domaine, cliquez sur l'icône Plus (trois points verticaux), sélectionnez Désactiver le domaine, puis cliquez sur Désactiver pour confirmer.
12. Conclusion
Félicitations ! Vous avez appris à utiliser Firebase pour ajouter des fonctionnalités à une application Next.js. Plus précisément, vous avez utilisé les éléments suivants :
- Firebase App Hosting pour compiler et déployer automatiquement votre code Next.js chaque fois que vous effectuez un push vers une branche configurée.
- Firebase Authentication pour activer les fonctionnalités de connexion et de déconnexion.
- Cloud Firestore pour les données sur les restaurants et les avis sur les restaurants.
- Cloud Storage for Firebase pour les images des restaurants.