Un widget de témoignages simple pour Next.js (sans package npm, une iframe)
Tu construis ton portfolio ou le site d’un client en Next.js et tu veux de vrais avis dessus. Tu pourrais coder une table de témoignages, un écran d’admin et un flux de modération, ou poser une seule iframe. Ce guide montre la deuxième option avec SimplerFeedback : le snippet HTML brut, un petit composant App Router, le bandeau pour une page d’accueil, et ce qu’une iframe ne sait honnêtement pas faire.
L’idée : tes avis vivent sur un mur à toi, ton site l’encadre
Avec SimplerFeedback, les avis arrivent par tes formulaires et sont publiés sur ton mur, une page publique à l’adresse simplerfeedback.com/wall/ton-slug. Cette page est la source de vérité : tu valides un avis, il apparaît sur le mur, et tous les sites qui intègrent le mur l’affichent aussi.
Ton site Next.js ne stocke rien. Il affiche le mur dans une iframe. Le mur est du HTML statique servi depuis un CDN : pas de clé d’API à protéger, pas de package npm à installer, pas de build à relancer quand un nouvel avis arrive. Tu publies un avis dans l’app et l’intégration est à jour.
Le snippet HTML brut
Dans l’app, ouvre Mon mur, puis Partager, et copie le code d’intégration. Il tient en deux lignes : l’iframe, et un script optionnel qui la dimensionne.
<iframe
src="https://simplerfeedback.com/wall/your-slug?embed=wall"
title="Your name"
style="width:100%;height:900px;border:0"
loading="lazy"
></iframe>
<script src="https://simplerfeedback.com/embed.js" async></script>La hauteur de 900px n’est qu’un repli. embed.js écoute le message que le mur envoie avec la vraie hauteur de son contenu (sf-embed-height) et ajuste l’iframe en conséquence : pas de barre de défilement interne, pas de blanc en bas. Sans le script, l’iframe garde simplement la hauteur écrite dans son attribut style. Une seule balise script suffit pour toutes les iframes de mur de la page.
Un composant Next.js App Router
Coller du HTML brut dans du JSX marche, mais un petit composant garde le slug dans une prop et ne charge le script qu’une fois. next/script avec strategy="lazyOnload" charge embed.js quand le navigateur est au repos et le dédoublonne : afficher le composant deux fois sur une page n’ajoute pas le script deux fois (et le script se protège lui-même).
// components/TestimonialWall.tsx
'use client';
import Script from 'next/script';
type Props = {
slug: string;
title: string;
variant?: 'wall' | 'strip';
featured?: boolean; // strip only, Premium
};
export function TestimonialWall({ slug, title, variant = 'wall', featured = false }: Props) {
const params = new URLSearchParams({ embed: variant });
if (variant === 'strip' && featured) params.set('featured', '1');
const src = `https://simplerfeedback.com/wall/${encodeURIComponent(slug)}?${params}`;
return (
<>
<iframe
src={src}
title={title}
loading="lazy"
style={{ width: '100%', height: variant === 'strip' ? 320 : 900, border: 0 }}
/>
<Script src="https://simplerfeedback.com/embed.js" strategy="lazyOnload" />
</>
);
}Deux attributs comptent. title donne un nom accessible à l’iframe, annoncé par les lecteurs d’écran ; mets quelque chose de parlant comme « Avis clients », pas « iframe ». loading="lazy" fait qu’un mur situé sous la ligne de flottaison n’est chargé que quand le visiteur s’en approche : il ne coûte rien au premier affichage.
Le bandeau pour une page d’accueil, et les avis épinglés seulement
Le mur complet va bien sur une page /temoignages. Sur une page d’accueil, tu veux plutôt une courte bande de preuves sous le hero. Utilise ?embed=strip : un bandeau horizontal d’avis, haut de 320px par défaut. En Premium, ajoute featured=1 au bandeau pour n’afficher que les avis que tu as épinglés (trois au maximum) : ta page d’accueil s’ouvre toujours sur les meilleurs.
// app/page.tsx — un bandeau d’avis épinglés sous le hero
import { TestimonialWall } from '@/components/TestimonialWall';
export default function Home() {
return (
<main>
{/* ...hero... */}
<TestimonialWall slug="ton-slug" title="Ce que disent mes clients" variant="strip" featured />
</main>
);
}
// app/temoignages/page.tsx — le mur complet
// <TestimonialWall slug="ton-slug" title="Avis clients" />Style et mise en page
Traite l’iframe comme une image : elle prend toute la largeur de son conteneur et embed.js s’occupe de la hauteur. Mets-la dans le wrapper que ta mise en page utilise déjà (un conteneur à largeur max, une cellule de grille) et elle s’adapte.
- Largeur : 100 % du parent. Contrains le parent, pas l’iframe.
- Hauteur : fixée par embed.js d’après le contenu ; la hauteur inline n’est qu’un repli.
- Couleurs et mode sombre ou clair viennent du style du mur, pas de ton site. Ton CSS ne peut pas entrer dans une iframe d’une autre origine, et ce n’est pas la peine d’essayer.
- Choisis un style de mur qui va avec la page (Terminal colle bien à un portfolio de dev), ou prends Build your own en Premium pour régler le fond, l’accent et la couleur du texte sur ta marque.
Les limites, honnêtement
C’est une iframe, avec ce que ça implique. Les avis ne sont pas rendus côté serveur dans ton DOM : les moteurs de recherche n’attribuent pas le texte des avis à ta page ; ce texte est indexé sur l’URL du mur, vers laquelle tu peux aussi faire un lien direct. Il n’y a pas de package de composant React ni d’API publique pour récupérer les avis en JSON : le composant ci-dessus est à copier, et l’iframe est l’intégration.
Pour la plupart des portfolios et des sites clients, c’est le bon compromis : deux minutes pour l’ajouter, rien à maintenir, et des avis qui restent à jour tout seuls.