The seam that puts Festipod's persistence behind interchangeable Refine backends was built on `festipod-refine`, over a base this one has since overtaken everywhere else. Carrying the seam rather than the branch keeps the evolved data layer intact and costs nothing: the backend contract, the registry and the provider that mounts Refine depend only on the domain types, so they compile here untouched once `@refinedev/core` is present — the one dependency this adds, installed through pnpm as this project requires. Nothing imports them and the registry is empty, which is the intended state. Wiring the seam means rewriting `FestipodDataContext` against this base's version of it — its own decision, with its own failure modes, and not one to smuggle into a transfer. Landing the files first makes that decision reviewable against real code instead of a diff between two branches. The doctrine travels with the code, because the seam is unreadable without it: the reconstructed observation of `@activitypods/refine-providers` — a package that publishes no engagement at all, hence `type: reconstruct` and a pin on the commit it was read at — our usage declaration beside it, and the brief that arbitrates one data shape for two rights models. So the manifest grows a `publish:` section: this repo still offers no interface, but it does now publish what it consumes, which is the only channel a provider has for learning that. The brief was written where three of the leaves it cites did not exist, and named them in prose to say so. Here they exist, so it links them; and its open deduplication point now reads against this repo's own `materializeAttendance` instead of against a sibling branch. It stays open, and the finding is unchanged: the active set is keyed per deposit, which buys replay idempotence and not person identity, so the count counts deposits rather than people. Two comment zones came over knowingly superseded — runtime hot-switching as what shapes the provider, and a sign-in barrier waiting on something `AuthGate` no longer does. They are recorded as data-layer doc-debt instead of being quietly rewritten, so the rewrite lands with the wiring that settles what they should say.
Festipod
Festipod permet aux utilisateurs de créer des points de rencontre qui viennent se « greffer » sur des événements publics existants. L'objectif est de favoriser les rencontres autour de ces événements.
L'événement public (festival, conférence, salon…) n'est qu'un prétexte et un point d'ancrage temporel et géographique : la valeur produite par l'app, c'est le point de rencontre que les utilisateurs viennent y greffer pour se retrouver.
Application web mobile-first. Stack : Bun + React + NextGraph (P2P, local-first, chiffré de bout en bout).
Modèle fonctionnel
Tous les utilisateurs sont authentifiés — il n'y a pas d'accès anonyme à l'app.
Acteurs
- Utilisateur — toute personne ayant un compte (un wallet NextGraph). Tous les acteurs ci-dessous sont des spécialisations d'un utilisateur dans un contexte donné.
- Connexion (« ami ») — un autre utilisateur avec qui je suis connecté. Sert à scoper les listes (« mes amis qui participent à… ») et la confiance.
- Déclarant d'un événement — l'utilisateur qui a inséré l'événement dans Festipod. N'est pas (forcément) un organisateur de l'événement réel : c'est juste quelqu'un qui le référence pour que d'autres puissent y attacher des points de rencontre.
- Hôte d'un point de rencontre — l'utilisateur qui a créé un point de rencontre rattaché à un événement.
- Inscrit à un point de rencontre — un utilisateur qui s'est inscrit à un point de rencontre. De fait, il devient participant à l'événement parent.
- Membre d'une communauté d'intérêt — un utilisateur abonné à une communauté pour découvrir les événements qu'elle référence.
Concepts métier
- Point de rencontre — l'unité de valeur de l'app. Un moment de rencontre proposé par un hôte à un endroit et à un horaire donnés, greffé sur un événement public. C'est ce à quoi on s'inscrit (on ne s'inscrit pas à un événement). Sans points de rencontre, un événement Festipod n'a pas d'intérêt.
- Événement — l'ancrage. Un événement public réel (festival, conférence, salon, exposition…) référencé dans Festipod pour servir de support à des points de rencontre. C'est simplement un prétexte (titre, dates, lieu, thèmes) ; le déclarant n'est pas l'organisateur officiel de l'événement, juste celui qui l'a inscrit dans Festipod.
- Communauté d'intérêt — un groupement thématique d'utilisateurs. Sert principalement à découvrir des événements (via abonnement) et à délimiter les périmètres de référencement.
- Liste curated — une liste d'événements éditorialisée (par un utilisateur ou une communauté), distincte de « les événements que j'ai déclarés » ou « les événements de la communauté ». Permet d'organiser/recommander.
- Connexion — lien de confiance entre deux utilisateurs (équivalent « ami »).
Fonctionnalités actuelles
Implémentées dans le code (écrans visibles via le router) :
- Authentification via wallet NextGraph
- Cycle de vie d'événement (déclaration, consultation, mise à jour)
- Cycle de vie de point de rencontre (rattaché à un événement)
- Inscription / désinscription à un point de rencontre
- Liste des participants à un événement
- Profil utilisateur, mise à jour, partage de profil
- Liste d'amis (connexions)
- Profil d'un autre utilisateur
Voir l'inventaire des routes et des écrans dans le concept app-architecture.
Défis ouverts
- Déduplication des événements en infra décentralisée. NextGraph étant P2P, rien n'empêche deux utilisateurs de déclarer indépendamment le même événement public (par ex. « Eurockéennes 2027 ») et de produire deux entrées distinctes. La dispersion qui en résulte fragmente les points de rencontre greffés et réduit leur visibilité — ce qui va à l'encontre de la fonction première de l'app. Pistes envisagées, non tranchées :
- proposer à l'utilisateur, lors de la déclaration, les événements déjà déclarés dans son réseau / ses communautés qui correspondent à sa saisie (recherche avant création) ;
- utiliser un identifiant externe canonique (URL officielle de l'événement, Wikidata, schema.org/Event) pour reconnaître les doublons et les présenter comme un seul événement à l'affichage ;
- laisser des curators (humains ou communautaires) fusionner / vetter les entrées canoniques.
Évolutions à venir
Identifiées comme nécessaires (notamment pour la scalabilité et la découverte) mais pas encore implémentées :
- Abonnement à une communauté d'intérêt pour découvrir ses événements (mécanisme de discovery distribué).
- Abonnement à un utilisateur pour suivre les événements qu'il déclare (sans nécessairement être ami).
- Listes curated — créer et partager des sélections d'événements éditorialisées.
- Multi-utilisateurs collaboratif : aujourd'hui chaque utilisateur a ses données isolées dans son wallet. Le passage en mode collaboratif (un point de rencontre vu par plusieurs personnes) suppose un refactor de la couche données. Voir le concept nextgraph-platform (briefs multi-store, matrice d'autorisations, wallet partagé, fork inbox).
Quick Start
bun install
bun run dev # Dev server avec HMR (port 3000)
Commandes utiles
bun run build # Build production vers dist/
bun run storybook # Parcourir écrans et composants
bun run test:cucumber # Tests BDD
bun run features:parse # Régénérer features.ts depuis les .feature
bun run steps:extract # Extraire les step definitions pour les tooltips
bun run build:orm # Régénérer l'ORM depuis les SHEX shapes
Documentation
- AGENTS.md — cœur : but produit, invariants, carte des concepts
- .project/concepts/ — toute la doctrine projet (savoir, règles, décisions, briefs), typée et livrée par hook au moment pertinent. 6 concepts :
functional-domain,app-architecture,tech-stack,data-layer,bdd-testing,nextgraph-platform.