Objectif : rafraîchir une interface automatiquement quand un module écrit une donnée (nouvel item Work, soumission de formulaire, inférence IA terminée…), via Convex.
Prérequis : l'URL Convex (NEXT_PUBLIC_CONVEX_URL) et un JWT valide.
Le modèle¶
Le JWT est transmis aux fonctions Convex comme argument (jamais via cookie). On souscrit à une requête qui renvoie les événements récents, et on déclenche un rechargement ciblé lorsqu'un nouvel événement apparaît.
import { useQuery } from "convex/react";
import { api } from "@puwapi/convex"; // fonctions générées
function useWorkRealtime(token: string, reload: () => void) {
const events = useQuery(api.work.getRecentEvents, { token, limit: 20 });
const lastSeen = useRef<number>(0);
useEffect(() => {
if (!events?.length) return;
const newest = events[0]._creationTime;
if (lastSeen.current && newest > lastSeen.current) {
reload(); // relire les données par l'API REST
}
lastSeen.current = newest;
}, [events, reload]);
}
Canaux par module¶
Chaque module a sa table d'événements et sa requête :
| Module | Requête | Événements |
|---|---|---|
| Work | api.work.getRecentEvents | item_created, status_changed, assigned, item_deleted, github_linked, comment_added |
| Forms | api.forms.getRecentEvents | submission_received |
| Careers | api.careers.getRecentEvents | application_received, stage_changed, job_published |
| IA | api.ai.getRecentEvents | inférence terminée |
Règles d'or¶
- L'événement est un signal, pas la donnée. Il porte des identifiants + un statut, pas le contenu métier. Relisez toujours le détail par l'API REST.
- Montez le client seulement si l'URL Convex et le token sont présents (sinon, fonctionnement en REST pur, sans temps réel).
- Le temps réel est optionnel : une intégration serveur peut ignorer Convex et interroger l'API (ou un webhook applicatif) à son rythme.
Sans front React¶
Pour un backend, n'utilisez pas Convex : interrogez l'API REST (polling) ou, quand il existe, un webhook applicatif du module. Convex est pensé pour les interfaces.