1. Qu’est‑ce que le mode inline et pourquoi c’est le « défaut »
Les consignes officielles d’OpenAI soulignent : l’affichage inline est le mode principal pour les ChatGPT Apps. Le widget inline est rendu directement dans le fil du chat au‑dessus de la réponse du modèle et inclut un petit bloc d’UI (carte, liste, carrousel) plus un message de suivi (follow‑up) de GPT en dessous.
L’idée est simple : au lieu de basculer l’utilisateur vers une grande interface séparée, on lui offre une « impulsion » visuelle compacte directement dans le contexte de la conversation : le modèle explique ce qui s’est passé et les options suivantes, et le widget présente proprement la structure et les actions disponibles.
Un widget inline :
- est léger en contenu et ne requiert pas beaucoup d’étapes ;
- n’emmène pas l’utilisateur dans une navigation complexe avec onglets et barres de défilement internes ;
- résout une ou deux petites tâches : montrer une liste d’options, permettre un choix, confirmer une action, afficher un statut.
Le mode fullscreen (nous le verrons dans la prochaine leçon) sert aux parcours volumineux et au contenu complexe. Pour l’instant, l’important est ailleurs : par défaut, pensez inline, et activez fullscreen en connaissance de cause, lorsque inline ne suffit manifestement plus.
Notre objectif dans cette leçon est d’apprendre à manier avec assurance les trois principaux patrons inline et de travailler par‑dessus avec des CTA :
- cartes
- listes
- carrousels
et de leur associer correctement des CTA (Call to Action).
2. Quand inline est meilleur que fullscreen
Pour simplifier, le mode inline est un « assistant rapide », tandis que le fullscreen est une « application distincte à l’intérieur de ChatGPT ».
Inline est particulièrement pertinent lorsque :
- il faut présenter plusieurs options et en laisser choisir une ou deux ;
- le résultat peut s’exprimer dans une structure compacte : carte cadeau, résumé de commande, mini‑tableau ;
- l’utilisateur exécute une action courte : « choisir », « afficher plus de détails », « modifier le filtre » ;
- le dialogue reste central : GPT explique, plaisante, commente, et le widget fournit simplement un formulaire ou un visuel pratique.
Dans le contexte de GiftGenius, inline, c’est :
- afficher les 3 à 5 meilleurs cadeaux pour la personne choisie ;
- proposer un filtre rapide : « montre uniquement les cadeaux numériques » ;
- confirmer le choix : « voici le résumé de la commande, tout est OK ? ».
Vous aurez besoin du fullscreen plus tard pour un assistant de paiement en trois étapes. Pour l’instant, restons dans la zone légère : un résultat d’appel d’outil → un widget inline.
Pour illustrer, un petit tableau :
| Patron | Quand il est idéal | Exemple dans GiftGenius |
|---|---|---|
| Carte | 1–3 entités avec paramètres clés et CTA | 3 cadeaux phares |
| Liste | 5–10 points textuels, lisibilité prioritaire | liste d’idées sans images |
| Carrousel | 3–8 variantes similaires avec visuel, défilement requis | longue liste de cadeaux |
Avec cela en tête, passons au concret : comment ces patrons se traduisent en UI et en code. Nous aborderons chaque patron selon le même format : d’abord — ce que c’est côté UX, puis — un composant React simple pour GiftGenius et, enfin, comment tout cela s’intègre dans un widget inline.
3. Cartes : le bloc de base de l’UI inline
Qu’est‑ce qu’une carte dans le contexte de l’Apps SDK
Selon les consignes OpenAI, une carte inline est un widget léger, mono‑utilisateur, qui présente une petite quantité de données structurées et 1 à 2 actions en bas. Elle peut comporter un titre, une image, quelques lignes de métadonnées et un CTA primaire (en plus d’un éventuel secondaire).
Dans GiftGenius, chaque carte représente un cadeau. On peut y placer :
- le nom du cadeau ;
- le prix ;
- à qui il convient (par exemple « collègue », « ami proche ») ;
- une courte explication du pourquoi c’est une bonne option ;
- un bouton « Choisir ce cadeau » ou « En savoir plus ».
La carte doit être autosuffisante : en la regardant, l’utilisateur comprend déjà quelle entité elle représente et quelle est l’action principale.
Type de données et composant simple GiftCard
Commençons par définir le type de données pour un cadeau. Supposons que nous disposons déjà d’un ToolOutput avec un tableau de tels objets ; ici, seule la partie UI nous intéresse.
// Structure générale du cadeau pour l’UI
export type GiftSuggestion = {
id: string;
title: string;
priceLabel: string; // par ex. « ≈ 40 $ »
recipientLabel: string; // « pour un collègue »
reason?: string; // explication par le modèle
imageUrl?: string;
};
Créons maintenant un composant React simple pour la carte :
type GiftCardProps = {
gift: GiftSuggestion;
onSelect: (gift: GiftSuggestion) => void;
};
export function GiftCard({ gift, onSelect }: GiftCardProps) {
return (
<div className="flex flex-col gap-2 rounded-lg border p-3">
<div className="text-sm font-medium">{gift.title}</div>
<div className="text-xs text-muted-foreground">
Pour: {gift.recipientLabel} · {gift.priceLabel}
</div>
{gift.reason && (
<div className="text-xs text-muted-foreground">{gift.reason}</div>
)}
<button
className="mt-2 self-start rounded bg-primary px-3 py-1 text-xs text-primary-foreground"
onClick={() => onSelect(gift)}
>
Choisir ce cadeau
</button>
</div>
);
}
Quelques nuances d’emblée :
- nous n’encombrons pas la carte de texte, au maximum 2–3 lignes de métadonnées et une courte explication ;
- un CTA principal — « Choisir ce cadeau » ; évitons d’y entasser 5 variantes ;
- le composant est facilement réutilisable dans une liste inline comme dans un carrousel.
Comment les cartes s’insèrent dans le widget global
Supposons que nous ayons un tableau gifts obtenu après l’appel de l’outil giftgenius.suggestGifts via notre MCP. En mode inline, le widget peut simplement les afficher sous forme de grille de 1 à 3 colonnes.
type GiftGridProps = {
gifts: GiftSuggestion[];
onSelect: (gift: GiftSuggestion) => void;
};
export function GiftGrid({ gifts, onSelect }: GiftGridProps) {
return (
<div className="grid gap-3 sm:grid-cols-2">
{gifts.map((gift) => (
<GiftCard key={gift.id} gift={gift} onSelect={onSelect} />
))}
</div>
);
}
Ici, nous :
- utilisons une grille de 1–2 colonnes pour éviter l’effet « mur de briques » ;
- pouvons facilement limiter le nombre de cartes, par exemple aux 3–6 premières.
Le gestionnaire onSelect peut appeler l’outil de checkout ou simplement enregistrer le choix dans l’état du widget et laisser le modèle poursuivre le dialogue. Exemple d’intégration minimaliste avec un outil :
async function handleSelect(gift: GiftSuggestion) {
await window.openai.actions.call("giftgenius.startCheckout", {
giftId: gift.id,
});
}
Ici, window.openai.actions.call est le pont pour invoquer un outil MCP enregistré directement depuis le widget.
Généralement après cet appel, le modèle affiche soit un statut, soit ouvre le widget suivant (par exemple, un résumé de commande). L’essentiel — ne tentez pas de réaliser tout le checkout dans la logique de la carte ; la carte doit déclencher l’étape suivante, claire.
4. Listes : quand le visuel n’est pas primordial
Si la carte est une petite « affiche », la liste est un récapitulatif textuel soigné. La documentation et les recommandations UX montrent que les listes sont pertinentes quand le contenu textuel prime sur l’accent visuel.
La liste convient quand :
- il faut présenter 5–10 options, mais sans image ;
- l’utilisateur veut « parcourir rapidement » les noms et brèves descriptions ;
- les actions sont identiques pour tous les éléments, et l’UI ne doit pas distraire.
Exemples dans GiftGenius :
- liste d’idées « rapides » sans détails ;
- liste de catégories favorites : « pour les collègues », « pour les parents », « pour les enfants » ;
- liste de sélections enregistrées (« Cadeaux pour le service RH », « Petites idées de Noël à moins de 20 $ »).
Un composant de liste simple
Créons une liste compacte avec un seul bouton CTA « En savoir plus » à droite.
type GiftListProps = {
gifts: GiftSuggestion[];
onSelect: (gift: GiftSuggestion) => void;
};
export function GiftList({ gifts, onSelect }: GiftListProps) {
return (
<ul className="flex flex-col gap-2">
{gifts.map((gift) => (
<li
key={gift.id}
className="flex items-center justify-between rounded-md border px-3 py-2 text-sm"
>
<span className="truncate">{gift.title}</span>
<button
className="text-xs text-primary"
onClick={() => onSelect(gift)}
>
En savoir plus
</button>
</li>
))}
<ul>
);
}
Ici, nous :
- attribuons truncate au titre, afin que les noms longs ne cassent pas la mise en page ;
- utilisons de nouveau un seul CTA par élément ;
- gardons toutes les informations « riches » (description, image, avis) pour l’étape suivante — par exemple, à l’ouverture d’une carte dédiée ou d’une vue fullscreen.
La liste se combine particulièrement bien avec des propositions de follow‑up de GPT. Le widget présente une liste de « candidats », et en dessous GPT écrit quelque chose comme :
« Je peux restreindre aux cadeaux jusqu’à 30 $ ou n’afficher que les options numériques. Que choisit‑on ? » et propose deux ou trois boutons de follow‑up.
Dans une section séparée, nous verrons plus en détail comment combiner au mieux les widgets inline et les messages de follow‑up selon les scénarios.
5. Carrousels : quand les variantes sont nombreuses mais similaires
Un carrousel est un ensemble de cartes alignées horizontalement et feuilletées par balayage ou via des boutons de navigation. Les consignes recommandent les carrousels lorsque vous affichez un petit ensemble d’éléments similaires (généralement 3–8), chacun contenant une image, un titre et quelques métadonnées.
L’idée principale : l’utilisateur peut rapidement parcourir les options sans s’endormir devant une liste verticale interminable.
Dans GiftGenius, un carrousel est utile si :
- nous avons 10–15 cadeaux pertinents, mais le widget inline ne doit afficher que « l’élite des huit » ;
- chaque cadeau est visuellement agréable (image, présentation) ;
- il est important que l’utilisateur feuillette les options sans descendre trop bas dans le chat.
Règles UX pour les carrousels
Sur la base des consignes et de la recherche :
- le nombre de cartes dans un carrousel — de 3 à 8 ; s’il y en a davantage, mieux vaut proposer une commande « Afficher plus » ;
- chaque carte :
- doit comporter une image ou un autre élément visuel ;
- ne doit pas contenir plus de deux lignes de texte‑métadonnées ;
- comporte un CTA clair, par exemple « Choisir » ou « En savoir plus » ;
- aucune navigation imbriquée complexe (onglets, sous‑transitions) dans la carte ;
- éviter les barres de défilement internes (verticales) : laissez la hauteur de la carte s’adapter dans une limite raisonnable, mais sans sa propre barre de défilement.
Un carrousel simple « une carte à la fois »
Pour éviter un défilement horizontal complexe, on peut implémenter la variante la plus simple : afficher une carte à la fois et fournir des boutons « précédent/suivant ».
import { useState } from "react";
type GiftCarouselProps = {
gifts: GiftSuggestion[];
onSelect: (gift: GiftSuggestion) => void;
};
export function GiftCarousel({ gifts, onSelect }: GiftCarouselProps) {
const [index, setIndex] = useState(0);
const gift = gifts[index];
return (
<div className="flex flex-col gap-2">
<GiftCard gift={gift} onSelect={onSelect} />
<div className="flex items-center justify-between text-xs">
<button
disabled={index === 0}
onClick={() => setIndex((i) => i - 1)}
>
← Précédent
</button>
<span>
{index + 1} / {gifts.length}
</span>
<button
disabled={index === gifts.length - 1}
onClick={() => setIndex((i) => i + 1)}
>
Suivant →
</button>
</div>
</div>
);
}
Ceci donne déjà une sensation de « carrousel », tout en :
- gardant le code compact ;
- évitant de lutter avec la largeur du conteneur et les défilements horizontaux dans le widget ;
- permettant de limiter facilement gifts à 8 éléments avant de passer le tableau au composant.
Si vous voulez un carrousel plus « authentique », vous pouvez utiliser overflow-x-auto et une largeur fixe pour les cartes, mais c’est un cas où il est plus simple d’utiliser un composant prêt à l’emploi d’une bibliothèque UI (shadcn/ui, solutions compatibles Radix, etc.) plutôt que de réinventer le vôtre.
6. Boutons CTA : peu, clair, utile
Les CTA (Call to Action) sont le cœur de tout patron inline. Ce sont les boutons qui transforment votre widget d’une simple image en un outil opérationnel.
Principes clés
La documentation OpenAI est assez stricte :
- sur une carte — deux boutons primaires au maximum (un principal, un secondaire) ;
- dans un carrousel — si possible, un CTA par élément ;
- le texte du CTA doit être un verbe concret : « Afficher les détails », « Ajouter à la liste », « Passer au paiement », plutôt que des libellés vagues comme « OK » ou « Action ».
Moins il y a de boutons, plus c’est simple pour le modèle et pour l’utilisateur. N’oubliez pas qu’au‑dessus et au‑dessous du widget il y a encore la partie textuelle de la réponse, plus les propositions de follow‑up de GPT.
Lier les CTA à la logique de l’application
Dans notre GiftGenius, la plupart des CTA vont soit :
- modifier les filtres/critères de recherche (nouvel appel d’outil giftgenius.refineSearch),
- lancer le checkout (giftgenius.startCheckout),
- ouvrir un site externe (via openExternal, que vous connaissez déjà grâce aux leçons précédentes).
Exemple de gestionnaire simple pour le CTA « Modifier les filtres » :
async function handleRefineFilters(gift: GiftSuggestion) {
await window.openai.actions.call("giftgenius.refineSearch", {
baseGiftId: gift.id,
});
}
Côté UX, il est essentiel d’indiquer dans les instructions système quand et quels CTA le modèle doit proposer. Par exemple :
- si l’utilisateur demande « montre plus d’options », mieux vaut afficher un nouveau carrousel avec un bouton « Choisir » ;
- si l’on arrive à l’achat, le CTA « Passer au paiement » doit déclencher l’appel d’outil qui lance le checkout ACP (nous y viendrons dans le module sur le commerce et les paiements).
Autre bonne pratique — ne pas dupliquer les fonctions de ChatGPT dans les CTA. Inutile de créer un bouton « Demander à ChatGPT », l’utilisateur dispose déjà d’un champ de saisie et de la voix. Les consignes recommandent explicitement d’éviter des entrées « dupliquées » dans la carte.
7. Inline + follow‑up : un duo complémentaire
Un widget inline ne vit jamais en vase clos. La structure de la réponse est généralement la suivante :
- le modèle décide d’utiliser votre App et d’appeler un outil ;
- votre MCP renvoie des données ;
- ChatGPT rend le widget inline avec ces données ;
- en dessous, le modèle ajoute un petit texte de follow‑up et des options prêtes à l’emploi pour continuer.
Pour GiftGenius, cela peut ressembler à :
- widget inline : trois cartes cadeaux avec CTA « Choisir » ;
- texte en dessous :
« Voici trois idées pour un collègue : une lampe de bureau, un cours de prise de parole en public et une carte cadeau de café. Je peux : — n’afficher que les options jusqu’à 30 $ ; — proposer quelques idées supplémentaires dans le même style ; — aider à passer directement à l’achat de l’une d’elles. »
Dans le follow‑up, le modèle peut faire référence aux CTA de votre widget (« cliquez sur “Choisir” sous l’option qui vous plaît ») ou proposer des commandes textuelles, qui mèneront de nouveau à un appel d’outil et à un rafraîchissement de l’UI inline.
Rappelez‑vous : le widget n’a pas à tout faire. Il est parfois préférable de laisser une partie du scénario au dialogue textuel, et d’utiliser le widget comme « bloc visuel » au sein de la conversation.
8. Comment cela s’intègre dans le flux global de GiftGenius
Pour clarifier, rassemblons tout dans un diagramme de séquence simple :
sequenceDiagram participant U as Utilisateur participant C as ChatGPT participant A as GiftGenius Widget participant B as MCP/Backend U->>C: "Sélectionne 3 cadeaux à 50 $ maximum pour un collègue" C->>B: call_tool(giftgenius.suggestGifts) B-->>C: 3 meilleures options C->>A: rendu du widget inline (cartes/carrousel) A-->>U: cartes avec CTA "Choisir" U->>A: clic sur le CTA A->>B: call_tool(giftgenius.startCheckout) B-->>A: statut / lien de paiement A-->>U: récapitulatif du choix / statut C-->>U: follow-up: "Je peux proposer d’autres idées ou aider avec une carte de vœux"
D’un point de vue architectural :
- le MCP reste le « cerveau » (sélection, logique métier, ACP),
- le widget est le « visage » (cartes/listes/carrousels),
- ChatGPT est le « maître de cérémonie » qui explique ce qui s’est passé et propose les prochaines étapes.
Pour que ce flux soit agréable :
- n’encombrez pas le widget d’actions ;
- gardez des données compactes dans les cartes ;
- réfléchissez aux options de follow‑up utiles après chaque affichage inline.
9. Quelques aspects visuels des patrons inline
Nous parlerons en détail du design visuel dans une prochaine leçon du module, mais quelques points, cruciaux pour les patrons inline, méritent d’être mentionnés dès maintenant.
Premièrement, assurez‑vous que vos cartes et listes ne ressemblent pas à un site étranger à l’intérieur de ChatGPT. Les couleurs et espacements doivent être soignés, sans dégradés criards ni polices Comic Sans. Le widget inline fait partie de l’UI globale de ChatGPT, pas une bannière de 2007.
Deuxièmement, évitez les barres de défilement internes. Si votre carte est si longue qu’une barre de défilement propre y apparaît, quelque chose cloche : soit vous essayez d’y insérer trop de contenu, soit le patron choisi n’est pas le bon (peut‑être faut‑il passer en fullscreen).
Troisièmement, maîtrisez la densité :
- laissez un espace visible entre les cartes ;
- assurez‑vous que le CTA est facilement cliquable (padding adéquat) ;
- un texte lisible même sur mobile, sans polices microscopiques.
Tout cela peut sembler être des « détails de designer », mais l’expérience montre que si le widget inline paraît « natif », le modèle l’utilise plus volontiers et les utilisateurs s’y perdent moins.
10. Pratique : faire évoluer GiftGenius sur la base de la leçon
Si vous souhaitez consolider vos acquis, voici une checklist pratique :
Commencez par prendre le résultat actuel de l’outil giftgenius.suggestGifts (un tableau de cadeaux) et :
- Implémentez trois variantes d’UI dans un même composant :
- GiftGrid avec des cartes ;
- GiftList avec une liste textuelle ;
- GiftCarousel avec la navigation « précédent/suivant ».
- Ajoutez‑leur une ou deux CTA :
- pour les cartes — « Choisir » ;
- pour la liste — « En savoir plus » ;
- pour le carrousel — également « Choisir », plus un bouton sous le widget « Afficher plus d’options ».
- Selon l’état (par exemple, combien de cadeaux l’outil a renvoyés au total), choisissez quel patron utiliser :
- s’il y a peu d’options (≤ 3) — une grille de cartes ;
- si vous avez beaucoup d’idées textuelles — une liste ;
- si vous avez beaucoup de cadeaux visuels — un carrousel.
Vous vous exercerez ainsi non seulement à l’UI, mais commencerez aussi à penser au choix dynamique du patron selon le contexte, ce qui plaira autant aux utilisateurs qu’aux équipes de review du Store.
En résumé, les patrons inline sont une couche d’UI rapide et légère, qui vit directement dans le fil du chat et n’essaie pas de remplacer une application distincte. Cartes, listes et carrousels couvrent 80 % des cas typiques : présenter des options, permettre un choix et poursuivre le dialogue proprement.
Dans la prochaine leçon du module, nous verrons quoi faire quand inline « ne suit plus » : nous étudierons les assistants fullscreen, le mode PiP et les scénarios où votre App a réellement besoin d’un grand écran dédié à l’intérieur de ChatGPT.
11. Erreurs typiques avec les patrons inline
Erreur n° 1 : transformer le widget inline en mini‑site.
Parfois, les développeurs essaient d’insérer dans une seule carte des onglets, des accordéons, des formulaires, un tableau et quantité d’autres éléments. Au final, on obtient une UI lourde qui casse le rythme du chat et devient pénible sur mobile. Les consignes disent clairement : pas de navigations profondes ni de vues complexes dans les cartes inline ; les scénarios complexes vont en fullscreen.
Erreur n° 2 : trop de boutons CTA.
« Et si on mettait sur la carte “En savoir plus”, “Acheter”, “Favori”, “Partager”, “Signaler” et “Générer une carte” ? » Au final, l’utilisateur est perdu, le modèle aussi, et la probabilité de cliquer sur le bon bouton chute. Rappelez‑vous la règle : un CTA principal et au maximum un secondaire. Les autres scénarios iront mieux dans un message de follow‑up de GPT ou des étapes ultérieures.
Erreur n° 3 : mélanger liste, cartes et carrousel dans une même réponse sans raison.
Si le même contenu apparaît tantôt en liste, tantôt en cartes, tantôt en carrousel « juste parce qu’on peut », l’utilisateur perd la sensation de cohérence. Mieux vaut choisir un patron pour un type de sortie donné (par exemple, des idées sans images — liste, des cadeaux avec images — carrousel) et s’y tenir.
Erreur n° 4 : des cartes surchargées de texte.
Une carte avec trois paragraphes de description, trois prix et deux blocs « pourquoi c’est super » devient un mur de texte. L’utilisateur cesse de la « scanner » et fait défiler. Essayez de ne laisser dans la carte que l’essentiel : un titre, un paramètre clé, une courte raison et un CTA. Tout le reste peut être expliqué dans la réponse textuelle de GPT à côté.
Erreur n° 5 : ne compter que sur l’UI et ignorer le dialogue de follow‑up.
On voit parfois l’approche « tout via des boutons, pas besoin de discuter ». C’est contraire à l’idée même de ChatGPT. Le widget inline doit compléter le dialogue, non le remplacer. N’oubliez pas de réfléchir aux options de follow‑up que le modèle peut proposer sous le widget : modifier les filtres, demander plus d’options, passer à l’étape suivante.
Erreur n° 6 : ignorer les limites sur le nombre d’éléments.
Un carrousel de 25 cartes ou une liste de 50 éléments dans un seul widget inline est le moyen sûr pour que l’utilisateur fasse défiler sans rien voir. La documentation recommande 3–8 éléments dans un carrousel et 5–10 éléments dans une liste. S’il y a plus de données, il est utile d’ajouter un CTA comme « Afficher plus » ou « Tout afficher en texte ».
Erreur n° 7 : utiliser inline là où un fullscreen est déjà nécessaire.
La tentation est parfois de « tout faire en inline », même lorsqu’il y a déjà 4 étapes, des formulaires à dix champs et de grands tableaux. Au final, on obtient soit un monstre, soit des défilements imbriqués et de pseudo‑étapes dans les cartes. Dès que vous sentez que les étapes et champs se multiplient — c’est le signal de penser à passer sur un assistant fullscreen, et de garder inline pour les aperçus rapides et les résumés d’actions.
GO TO FULL VERSION