# 08 — Les formats `report`, `toon` (webtoon), `book`, `roadmap`, `stories` et `calendar`

**Statut : accepté · Phase : P6 à P11 · Mis à jour : 02/11/2026.**

> **Note du 02/11/2026.** Chaque format a désormais son plan détaillé, écrit d'après le code :
> [23 · Report](/23-report), [24 · Webtoon](/24-webtoon), [25 · Book](/25-book),
> [26 · Roadmap](/26-roadmap), [27 · Calendar](/27-calendar) et [28 · Stories](/28-stories). Ce
> document reste la vue d'ensemble et le socle commun (§0) ; **là où un plan détaillé s'en écarte,
> c'est le plan détaillé qui vaut**, une fois accepté. Les écarts relevés en les écrivant, chacun
> repris comme question ouverte du plan concerné :
>
> - commandes : `export ics`, `export rss` (§4, §5) s'écrivent `export --to ics|rss` (audit DO-8) ;
> - toon : la forme sur une ligne `:::bubble{…} texte :::` n'est pas lue par le parseur (seul
>   `:::notes` en a une) ; un fichier de langue « textes seuls » contredit la règle des variantes
>   complètes (`09` §1) ; la découpe « en évitant de couper une bulle » contredit `15` (« sans égard
>   aux cases ») ; `sharp` n'est pas dans le lockfile ;
> - book : une scène est une **section** d'un chapitre (un fichier par chapitre), pas un chapitre ;
>   `subtitle` n'est pas un champ de `StoryMetaSourceSchema` ;
> - roadmap : `type=milestone` heurte la règle B4 (`type=` réservé aux blocs motion) ; la roadmap de
>   Récit ne peut pas être générée depuis `06`, une page de site n'est pas une story ;
> - calendar : une scène est un événement, il n'y a pas de tableau `events[]` ; `video=` devient
>   `film=` (vocabulaire d'`AGENTS.md`) ; le séparateur d'`office-hours` (§5) est coupé sur deux
>   lignes ;
> - stories : `duration` et `aspect` s'écrivent `dur` et `aspectRatio`, comme dans le code ;
> - exemples : `owner=@jane` et `author: Jane Doe` sont des noms de personnes, la règle est Lorem
>   Ipsum.

Ces six formats font partie de la vision **dès maintenant**. Ils ont chacun leur package, leur site,
leurs exemples et leurs phases. Ils consomment le même modèle `Story` (voir `02-architecture.md`) et
la même syntaxe : frontmatter, scènes séparées par `---`, directives `:::`. Le présent document est
leur spécification, au même niveau que `05-video.md` pour `motion`.

**Réglages à plat.** Les réglages d'un format s'écrivent à la racine du frontmatter (`width`,
`view`, `timezone`…), sans clé `toon:`, `roadmap:`, `calendar:` ni `stories:`. En JSON, ils sont les
`settings` de la story, et ces `settings` sont la section du format dans `recit.config`. La forme
imbriquée (`toon.direction`, `calendar.timezone`) n'existe que dans `recit.config`. Aucun réglage ne
s'appelle `kind`, réservé au discriminant des documents JSON (`09-langues-et-json.md` §2.2).

## 0. Vue d'ensemble des neuf formats

| Format     | Package               | Site                   | Une scène =                  | Lecture                                           | Exports                                             | Phase |
| ---------- | --------------------- | ---------------------- | ---------------------------- | ------------------------------------------------- | --------------------------------------------------- | ----- |
| `deck`     | `@recit/deck`         | presentation.recit.dev | une slide                    | slide par slide, console présentateur             | HTML, PDF                                           | P1–P2 |
| `motion`   | `@recit/motion*`      | motion.recit.dev       | un plan                      | timeline                                          | lecture web, MP4, GIF                               | P4    |
| `docs`     | `@recit/site-stories` | docs.recit.dev         | une page                     | navigation de doc                                 | site statique                                       | P1–P2 |
| `report`   | `@recit/report`       | report.recit.dev       | une section                  | défilement continu                                | HTML, PDF paginé                                    | P6    |
| `toon`     | `@recit/toon`         | webtoon.recit.dev      | une case                     | ruban vertical, au scroll                         | lecteur web, tranches PNG/WebP, PDF, motion         | P7    |
| `book`     | `@recit/book`         | book.recit.dev         | un chapitre                  | pages, table des matières                         | web, PDF, EPUB 3                                    | P8    |
| `roadmap`  | `@recit/roadmap`      | roadmap.recit.dev      | une piste (lane) ou un jalon | Now / Next / Later, frise, kanban                 | web, embed, PDF, ICS des jalons, RSS des livraisons | P9    |
| `calendar` | `@recit/calendar`     | calendar.recit.dev     | un événement (ou un jour)    | mois, semaine, agenda, année                      | web, embed, ICS et flux abonnable, PDF              | P10   |
| `stories`  | `@recit/stories`      | story.recit.dev        | une carte plein écran `9:16` | tap ou swipe, lecture auto, barres de progression | web, embed, images, vidéo (via motion)              | P11   |

### Trois packages partagés, ajoutés pour ces formats

| Package        | Groupe                                                                                                            | Rôle                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Utilisé par                                                                                                                                                    |
| -------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `@recit/data`  | fondations (`packages/data`)                                                                                      | chargement de données (CSV, JSON, YAML ; plus tard Parquet via DuckDB-wasm), requêtes simples (`filter`, `groupBy`, `sum`…), formatage localisé (`Intl`), composants `Chart`, `DataTable`, `Value`. Graphiques rendus en **SVG côté build** (SSR), donc sans JS côté client pour l'impression                                                                                                                                                                                                                                                                                                              | `report` d'abord, puis `deck` et `docs` (un `::chart` dans une slide ou une page)                                                                              |
| `@recit/paged` | outils (`packages/tools/paged`, `scope:tool` ; l'ébauche est encore dans `packages/formats/paged` jusqu'à PDF1.0) | **Node uniquement, importé par la CLI seulement** : chaîne d'impression commune (`15-export-pdf.md`). Sous-export `@recit/paged/runner`, seul module « lancer Chromium, servir un build, attendre prêt, mesurer, imprimer ou capturer » (PDF, tranches du toon, images, cartes). Moteur `chromium` (Playwright `page.pdf`) pour tous les formats ; moteur `pagedjs` (polyfill injecté depuis Node) pour `book` en P8 et en option du report : table des matières numérotée, titres courants, notes de bas de page. `pageCss(options)`. Les formats n'en dépendent pas : ils fournissent une vue imprimable | imprime ou capture pour `deck` (export PDF, qui migre dessus), `report`, `toon`, `book`, puis les formats suivants de la liste fermée de `15-export-pdf.md` §1 |
| `@recit/time`  | fondations (`packages/time`)                                                                                      | dates, durées, fuseaux (`Temporal` via polyfill, sinon `Intl`), récurrences RFC 5545 (`rrule`), trimestres et semaines ISO, génération et lecture **ICS**, formatage localisé                                                                                                                                                                                                                                                                                                                                                                                                                              | `roadmap` et `calendar` (créé en P9). Le report de P6 s'en passe : ses axes temporels utilisent `Intl` et l'échelle temporelle de `d3-scale`                   |

Choix techniques :

- graphiques : **d3 sans DOM** (`d3-scale`, `d3-shape`, ISC, déjà dans le lockfile), rendu SVG au
  build, base partagée avec les cartes (`13-cartes.md` D9). Tranché le 24/10 (question 10 de
  `06-roadmap.md`) : Observable Plot est écarté, car il demande un DOM virtuel en SSR ;
- pagination : Chromium (CSS Paged Media natif, boîtes de marge) pour tous les formats ;
  **Paged.js** (MIT) seulement pour `book` en P8, et en option du report, après le spike go/no-go
  PDF3.0 (`15-export-pdf.md` §3.4) ;
- EPUB : génération maison (XHTML + OPF + `nav.xhtml`, zip via `fflate`), vérifiée en CI par
  `epubcheck`.

### Ponts entre formats

Une même source peut changer de format en changeant `format:` ou via `recit convert`. On ne promet
que les ponts dont la correspondance est fermée. Le reste produit une erreur explicite, jamais une
devinette (règle d'emaki).

| De → vers          | Correspondance                                                                                                                   | Phase |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------- | ----- |
| deck → motion      | layouts → blocs (`02-architecture.md` §4)                                                                                        | P4    |
| report → deck      | une section → une slide. `::chart` et `::table` gardés, texte long résumé en erreur si trop dense (règles de densité existantes) | P6    |
| toon → motion      | une case → un plan `9:16` avec panoramique vertical, bulles en apparition                                                        | P7    |
| book → docs        | un chapitre → une page du framework de sites, table des matières → sidebar                                                       | P8    |
| roadmap → calendar | chaque jalon ou item daté → un événement (ICS partagé)                                                                           | P10   |
| calendar → stories | les prochains événements → une story « à venir »                                                                                 | P11   |
| stories ⇄ motion   | une carte → un plan `9:16`, mêmes blocs d'animation                                                                              | P11   |
| report → stories   | chaque `:::kpi` ou `::chart` → une carte                                                                                         | P11   |
| → PDF              | formats de la liste fermée de `15-export-pdf.md` §1 seulement, par une seule chaîne (`@recit/paged`, `recit export --to pdf`)    | P6–P8 |

## 1. `report` — rapports de données

**Promesse.** Un rapport trimestriel, une étude ou un tableau de bord figé s'écrit en Markdown. Les
chiffres viennent **des données, jamais du texte** : un nombre affiché est toujours calculé.

### Syntaxe

```md
---
title: Lorem Ipsum Quarterly
format: report
lang: en
data:
  sales: ./data/sales.csv
  regions: ./data/regions.json
pdf:
  page:
    size: A4
  toc: true
---

--- id=summary

# Summary

Revenue reached :value{data=sales field=revenue agg=sum format=currency}, up :value{data=sales
field=revenue agg=growth period=quarter format=percent} over last quarter.

::chart{data=sales type=line x=month y=revenue}

--- id=regions

## Regions

::table{data=regions columns="name,revenue,growth" sort=-revenue}

:::callout{type=info} Lorem ipsum dolor sit amet. :::
```

| Directive                          | Rôle                                                                                                        |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| frontmatter `data:`                | sources nommées, chemins relatifs au fichier. Lues au build et validées (colonnes, types)                   |
| `:value{data field agg format}`    | un nombre dans le texte, calculé. `agg` : `sum`, `avg`, `min`, `max`, `count`, `last`, `growth`             |
| `::chart{data type x y color}`     | `line`, `bar`, `area`, `dot`, `pie` (v2). Couleurs depuis les tokens du thème (teinte unique Q07, dégradés) |
| `::table{data columns sort limit}` | tableau formaté. Pagination automatique en PDF (en-tête répété)                                             |
| `:::kpi`                           | grille de chiffres clés (`:value` + libellé)                                                                |
| directives existantes              | `:::callout`, `:::card`, `:::col`, Mermaid, KaTeX, code                                                     |

Règles :

- un champ ou une source inconnus produisent une erreur avec numéro de ligne
  (`report.md:12 :value: field "revnue" not in sales (did you mean "revenue"?)`) ;
- aucun chiffre écrit en dur dans un `::chart` ;
- les règles de densité et d'accessibilité de `@recit/core` s'appliquent : texte alternatif généré
  pour chaque graphique (résumé des données).

### Rendu et exports

- **HTML** : une page continue avec sommaire latéral, ancres par section et thème clair ou sombre.
  Embarquable dans le framework de sites (`<StoryEmbed format="report" />`).
- **PDF** : `recit export --to pdf report.md` via `@recit/paged`, moteur Chromium (A4 ou Letter,
  page de titre, table des matières **en liens, sans numéros** en P6, en-tête courant avec le titre,
  pied avec la page, tableaux à en-tête répété). La table des matières numérotée arrive en P8, avec
  le moteur `pagedjs` en option (`15-export-pdf.md` §3.4). Réglages à plat : `pdf.page.size` (ex-
  `paper`) et `pdf.toc`, sans clé `report:` ; ils sont la section `report.pdf` de `recit.config` et
  le `settings.pdf` du JSON.
- **Données mises à jour** : `recit build` relit les sources. Un `recit dev` surveille aussi les
  fichiers de données.

### Phases (P6)

- [ ] R1 — `@recit/data` : loaders CSV/JSON/YAML, validation, `Value`, `DataTable`, `Chart` (d3 sans
      DOM, SSR SVG). Tests unitaires sur les agrégations.
- [ ] R2 — `@recit/paged` : extraire la logique d'export PDF de `@recit/cli` dans
      `@recit/paged/runner`, contrat d'impression `@recit/core/print`, moteur `chromium`,
      `pageCss(options)`, en-têtes et pieds statiques (boîtes de marge), table des matières sans
      numéros. Pas de Paged.js en P6. Le deck migre dessus sans changement visible (goldens). Détail
      : PDF0 et PDF1 de `15-export-pdf.md`.
- [ ] R3 — `@recit/report` : layout continu, sommaire, `:::kpi`, thème `report` dans `@recit/theme`.
- [ ] R4 — CLI : `recit dev | build | export --to pdf` pour `format: report`. Surveillance des
      données.
- [ ] R5 — Pont report → deck (`recit convert report.md --to deck`).
- [ ] R6 — `examples/report-quarterly` (données Lorem générées), `examples/report-study` ;
      `sites/report` (report.recit.dev) ; `sites/docs` › Formats › Report.
- [ ] Tests : goldens PDF (rendu page par page en PNG), e2e sur l'exemple, erreurs de données avec
      numéro de ligne.

## 2. `toon` — webtoons et BD

**Promesse.** Un épisode de webtoon s'écrit en Markdown : les images des cases, et **le texte des
bulles à part**. Le lettrage est généré, donc traduisible. La même planche se lit au scroll sur le
web, s'exporte en tranches pour les plateformes et peut devenir une vidéo verticale.

### Syntaxe

```md
---
title: Lorem Ipsum — Episode 1
format: toon
lang: en
width: 800
gutter: 120
font: comic # police de lettrage du thème
---

--- id=p1 src=./panels/01.webp alt="Lorem street at night"

:::bubble{x=62% y=18% tail=bottom-left} Lorem ipsum? :::

:::caption
Somewhere, dolor sit amet.
:::

--- id=p2 src=./panels/02.webp height=1400 gutter=40

:::bubble{x=30% y=12% shape=shout} Ipsum! :::

:::sfx{x=70% y=60% rotate=-12} BOOM :::
```

| Élément                                                           | Rôle                                                                                                                                         |
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| attributs de scène `src`, `alt`, `height`, `gutter`, `background` | image de la case (ou fond uni), description (traduisible, exigée par le PDF balisé : `15-export-pdf.md` §3.5), hauteur, espace après la case |
| `:::bubble{x y tail shape}`                                       | bulle positionnée en pourcentage. `shape` : `speech`, `thought`, `shout`, `whisper`                                                          |
| `:::caption`                                                      | encart narratif                                                                                                                              |
| `:::sfx`                                                          | onomatopée, en texte vectoriel                                                                                                               |
| `:::notes`                                                        | notes d'auteur (non publiées)                                                                                                                |
| traductions                                                       | `episode-1.fr.md` ne contient que les textes (bulles, encarts et `alt`) par `id` de scène. Les images sont partagées                         |

Règles :

- image manquante, ou bulle hors de la case : erreur avec numéro de ligne ;
- tailles d'image et poids total vérifiés au build (avertissement au-delà d'un budget configurable).

### Rendu et exports

- **Lecteur web** : ruban vertical à largeur fixe (800 px de référence, responsive), chargement
  progressif des images, bulles en HTML et SVG (texte sélectionnable, indexé par Pagefind,
  accessible), apparition au scroll (`motion`), sommaire des épisodes. Embarquable dans le framework
  de sites.
- **Tranches** : `recit export --to images episode.md` produit des PNG ou WebP découpés à la hauteur
  exigée par les plateformes (préréglages à vérifier, par exemple Webtoon Canvas : 800 px de large),
  en évitant de couper une bulle. Capture par la CLI à travers `@recit/paged/runner` (Playwright),
  puis découpe par `@recit/toon` via `sharp`. Attention : `sharp` est à `false` dans `allowBuilds`
  du fork, à activer pour `@recit/toon` seulement.
- **PDF** : `recit export --to pdf episode.md`, pages de hauteur fixe coupées entre les cases, une
  case trop haute sur sa propre page (avertissement), un PDF par langue. Ce découpage est
  **distinct** de celui des tranches (`15-export-pdf.md` §3.5, PDF2).
- **Pont vers motion** : `recit render episode.md --as motion --aspect 9:16`, avec panoramique
  vertical case par case et bulles en apparition.
- **Séries** : un dossier = une série. `series.yaml` (ou le frontmatter du premier épisode) donne le
  titre, la couverture et l'ordre.

### Phases (P7)

- [ ] W1 — `@recit/toon` : modèle de case (image, bulles, encarts, sfx), lecteur web, thème de
      lettrage dans `@recit/theme`.
- [ ] W2 — Traductions par `id` de scène (`*.fr.md`), lecteur avec sélecteur de langue.
- [ ] W3 — Export en tranches (préréglages de plateformes, budget de poids) : capture par la CLI à
      travers `@recit/paged/runner`, découpe dans `@recit/toon`.
- [ ] PDF du webtoon : tâches PDF2.1 à PDF2.4 de `15-export-pdf.md`.
- [ ] W4 — Pont toon → motion.
- [ ] W5 — `examples/toon-episode` (cases SVG abstraites générées, aucune image sous droits),
      `sites/webtoon` (webtoon.recit.dev), `sites/docs` › Formats › Webtoon.
- [ ] Tests : goldens des tranches, e2e du lecteur (scroll, lazy loading), erreurs de
      positionnement.

## 3. `book` — livres et e-books

**Promesse.** Un livre, un manuel ou une thèse s'écrit en plusieurs fichiers Markdown. On en tire un
PDF prêt à imprimer, un EPUB et une édition web, depuis la même source.

### Syntaxe

```
my-book/
  book.md            # frontmatter du livre + ordre des chapitres
  01-introduction.md
  02-lorem.md
  03-ipsum.md
  images/
```

```md
---
title: Lorem Ipsum
subtitle: A Dolor Sit Amet Story
author: Jane Doe
format: book
lang: en
chapters:
  - 01-introduction.md
  - 02-lorem.md
  - 03-ipsum.md
front: [title, copyright, toc]
back: [notes, index]
pdf:
  page:
    size: { width: 6in, height: 9in } # A5, A4, or literal sizes
---
```

Dans un chapitre :

- le **H1** est le titre du chapitre ;
- `---` sépare les sections. Un saut de page est possible avec `--- break=page` ;
- notes de bas de page en GFM (`[^1]`) ;
- figures numérotées (`::figure{src caption id}`) et renvois (`:ref[fig-map]`) ;
- `:index[term]` pour l'index ;
- citations et épigraphes avec `:::epigraph`.

Règles :

- chapitre listé mais absent, renvoi vers un `id` inconnu, image manquante : erreur avec numéro de
  ligne ;
- typographie selon `lang` : césure (`hyphens: auto`), veuves et orphelines, espaces insécables
  françaises.

### Rendu et exports

Réglages à plat, sans clé `book:` : `chapters`, `front` et `back` décrivent la structure du livre
(lue aussi par l'EPUB et l'édition web) ; seule la mise en page imprimée va sous `pdf`. L'ancien
`trim` devient `pdf.page.size`, en valeurs littérales (`15-export-pdf.md` §3.2 et §3.3).

- **HTML intermédiaire** : `@recit/book` produit une fois le HTML du livre (hast), consommé par la
  chaîne PDF et par l'EPUB.
- **PDF** : via `@recit/paged`, moteur `pagedjs` (après le spike PDF3.0). Taille de page
  (`pdf.page.size`), marges intérieure et extérieure (pages paires et impaires), titres courants
  (livre à gauche, chapitre à droite), numérotation romaine puis arabe, chapitres sur page impaire,
  table des matières et index avec numéros de page.
- **EPUB 3** : un XHTML par chapitre, `nav.xhtml`, couverture, métadonnées, polices du thème
  embarquées, notes en `aside` (`epub:type="footnote"`). Validé par `epubcheck` en CI.
- **Édition web** : pont book → docs. Chaque chapitre devient une page du framework de sites et la
  table des matières devient la sidebar. La recherche Pagefind fonctionne.
- `recit export --to pdf book.md`, `recit export --to epub book.md`, `recit build book.md` (édition
  web).

### Phases (P8)

- [ ] B1 — `@recit/book` : modèle multi-fichiers (`book.md` + chapitres), numérotation, renvois,
      index, notes.
- [ ] B2 — PDF imprimable via `@recit/paged` (pages paires et impaires, titres courants,
      numérotation), réglages à plat ; tâches PDF3.0 à PDF3.7 de `15-export-pdf.md`.
- [ ] B3 — EPUB 3 depuis le HTML intermédiaire de `@recit/book`, et `epubcheck` en CI.
- [ ] B4 — Édition web (pont book → docs dans `@recit/site-stories`).
- [ ] B5 — `examples/book-novella` (Lorem Ipsum, 3 chapitres), `sites/book` (book.recit.dev),
      `sites/docs` › Formats › Book.
- [ ] Tests : goldens PDF (pages clés), `epubcheck`, renvois cassés, e2e de l'édition web.

## 4. `roadmap` — feuilles de route publiques

**Promesse.** Une roadmap produit, open source ou d'équipe s'écrit en Markdown, ou se synchronise en
JSON. Elle se publie en page publique ou s'intègre à une doc. Le plan de Récit lui-même
(`06-roadmap.md`) est le premier exemple publié sur roadmap.recit.dev.

### Syntaxe

```md
---
title: Lorem Product Roadmap
format: roadmap
lang: en
view: now-next-later # now-next-later | timeline | kanban
period: quarter # month | quarter | half
statuses: [planned, in-progress, shipped, paused]
---

--- lane=editor id=editor

## Editor

- [x] Lorem ipsum export {id=export status=shipped quarter=2026-Q3 link=https://example.com}
- [ ] Dolor sit amet sync {id=sync status=in-progress start=2026-10-01 end=2026-12-15 owner=@jane}
- [ ] Consectetur offline mode {id=offline status=planned quarter=2027-Q1 tags=mobile,beta}

--- lane=api id=api

## API

- [ ] Adipiscing webhooks {id=webhooks status=planned quarter=2027-Q1 depends=sync}

--- type=milestone id=v1 date=2027-03-31

## 1.0 release
```

| Élément                     | Rôle                                                                                                                                   |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `--- lane=…`                | une piste. Le titre H2 est le libellé                                                                                                  |
| item de liste avec `{…}`    | un élément : `status`, `start`, `end` ou `quarter`, `owner`, `tags`, `link`, `depends`. La case `[x]` vaut `status=shipped` par défaut |
| `--- type=milestone date=…` | un jalon, affiché sur la frise et exporté en ICS                                                                                       |
| `:::item{id}`               | bloc de description longue d'un élément (Markdown complet, captures)                                                                   |
| compagnon `product.json`    | statuts et dates gérés par un outil (CI, script de synchronisation), le texte restant dans le `.md` (voir `09-langues-et-json.md`)     |

Règles :

- `depends` vers un `id` inconnu, `end` avant `start`, ou statut hors de `statuses` : erreur avec
  numéro de ligne ;
- un élément `shipped` sans date produit un avertissement.

### Composants

`Roadmap` (racine, choix de la vue), `NowNextLater`, `Timeline` (frise avec pistes et jalons),
`Kanban` (colonnes par statut), `RoadmapItem` (carte : titre, statut, dates, propriétaire, tags,
lien), `StatusBadge`, `Milestone`, `ProgressBar` (part `shipped` par piste), `RoadmapFilters`
(statut, tag, propriétaire, période), `DependencyLine`, `Changelog` (liste des `shipped` par date,
avec flux RSS). Tous sont utilisables en MDX dans une page du framework de sites
(`<StoryEmbed slug="product" format="roadmap" view="timeline" />`).

### Rendu et exports

- Web : les trois vues, des filtres dans l'URL (`?status=in-progress&tag=mobile`), et une ancre par
  élément.
- `recit export ics` pour les jalons, `recit export rss` pour les livraisons,
  `recit export --to pdf` pour la frise, imprimée par la CLI et `@recit/paged`.
- Synchronisation (plus tard, hors du cœur) : scripts d'import GitHub Projects ou Linear vers le
  compagnon JSON. Le Markdown reste la source du texte.

### Phases (P9)

- [ ] RM1 — `@recit/time` (dates, trimestres, ICS).
- [ ] RM2 — `@recit/roadmap` : modèle, vues `now-next-later`, `timeline` et `kanban`, filtres,
      composants.
- [ ] RM3 — Exports ICS, RSS et PDF.
- [ ] RM4 — `examples/roadmap-product` (Lorem, en/fr) et publication de la roadmap de Récit
      elle-même, générée depuis `sites/plans/pages/06-roadmap.md` converti au format roadmap.
- [ ] RM5 — `sites/roadmap` (roadmap.recit.dev), `sites/docs` › Formats › Roadmap.
- [ ] Tests : goldens des trois vues, validation des dépendances, ICS validé (parseur ICS en test).

## 5. `calendar` — calendriers et agendas

**Promesse.** Un calendrier d'événements (meetups, cours, sorties, planning éditorial) s'écrit en
Markdown ou en JSON. On l'affiche en mois, en semaine ou en agenda, on l'intègre à une doc, et on
s'y abonne en ICS.

### Syntaxe

```md
---
title: Lorem Meetups
format: calendar
lang: en
timezone: Europe/Paris
view: month # month | week | agenda | year
firstDay: monday
---

--- id=kickoff start=2026-11-05T18:30 end=2026-11-05T20:30 location="Lorem Hall, Paris" tags=meetup

## Kickoff meetup

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

--- id=office-hours start=2026-11-03T10:00 duration=1h rrule="FREQ=WEEKLY;BYDAY=TU;COUNT=8"
url=https://example.com/live

## Office hours

--- id=launch date=2027-03-31 allDay=true tags=release

## 1.0 launch
```

| Élément                            | Rôle                                                                                                                                                                                                 |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| scène = événement                  | `start` / `end`, ou `duration`, ou `date` + `allDay`. `timezone` par événement, sinon celle du calendrier                                                                                            |
| `rrule`, `exdate`                  | récurrences (RFC 5545)                                                                                                                                                                               |
| `location`, `url`, `tags`, `color` | `color` reste dans la teinte unique : seulement des variations de clarté, ou des tags avec icônes                                                                                                    |
| corps de la scène                  | description en Markdown complet                                                                                                                                                                      |
| `include: [../roadmap/product.md]` | importe les jalons d'une roadmap (pont roadmap → calendar)                                                                                                                                           |
| JSON                               | un `meetups.json` complet (`kind: "story"`, `format: "calendar"`) avec `events[]` et des titres `Localized` est souvent plus pratique que le Markdown. C'est le cas d'usage type du JSON multilingue |

Règles :

- `end` avant `start`, `rrule` invalide, fuseau inconnu : erreur avec numéro de ligne ;
- chevauchements signalés si `noOverlap` est vrai.

### Composants

`Calendar` (racine, choix de la vue), `MonthView`, `WeekView`, `AgendaList`, `YearView`,
`EventCard`, `EventDetail` (modale ou page, avec « ajouter à mon agenda »), `MiniCalendar`,
`UpcomingEvents` (les N prochains, à intégrer dans une page de doc ou sur recit.dev), `Countdown`,
`TimezoneSwitcher`, `CalendarFilters` (tags), `SubscribeButton` (ICS, Google, Outlook).

### Rendu et exports

- Web : les quatre vues, une page par événement (SEO, `schema.org/Event` en JSON-LD), dates
  localisées (`Intl`).
- `recit export ics` produit un fichier et un flux abonnable publié avec le site
  (`/calendar/<slug>.ics`). `recit export --to pdf` imprime le mois ou l'agenda.
- Un événement passé peut renvoyer vers son deck ou sa vidéo (`deck=…`, `video=…`), ce qui relie les
  formats.

### Phases (P10)

- [ ] CA1 — `@recit/time` : récurrences, fuseaux, ICS en lecture (import d'un `.ics` existant).
- [ ] CA2 — `@recit/calendar` : modèle, vues, composants, JSON-LD.
- [ ] CA3 — ICS abonnable, PDF, pont roadmap → calendar.
- [ ] CA4 — `examples/calendar-meetups` (JSON multilingue en/fr) et `examples/calendar-course`
      (Markdown).
- [ ] CA5 — `sites/calendar` (calendar.recit.dev), `sites/docs` › Formats › Calendar.
- [ ] Tests : récurrences (changements d'heure), fuseaux, ICS aller-retour, goldens des vues.

## 6. `stories` — stories web (cartes plein écran)

**Promesse.** Des stories à la Instagram ou Google Web Stories : des cartes verticales plein écran
qu'on fait défiler d'un tap. On les écrit en Markdown, on les intègre partout (doc, landing,
réseaux), et on peut les exporter en images ou en vidéo.

Le format s'appelle `stories` (au pluriel) pour ne pas le confondre avec le modèle `Story` du cœur.
Le site s'appelle **story.recit.dev** (et `stories.recit.dev` y redirige).

### Syntaxe

```md
---
title: Lorem Launch
format: stories
lang: en
duration: 5s
autoplay: true
aspect: 9:16
---

--- id=hook background=./bg/01.webp

# Lorem ipsum.

--- id=proof duration=7s

## :value{data=sales field=revenue agg=sum format=currency}

dolor sit amet this quarter

--- id=cta background=#0b0b0f

# Try it now

::cta[Get started]{href=https://recit.dev}
```

| Élément              | Rôle                                                                                                                               |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| scène = carte        | `background` (image, vidéo courte ou couleur), `duration`, `overlay` (dégradé pour la lisibilité)                                  |
| contenu              | les blocs Markdown habituels, plus les blocs animés de motion (`type=stat`, `type=list`…) quand `@recit/motion-blocks` est présent |
| `::cta[label]{href}` | bouton d'action en bas de la carte (swipe up)                                                                                      |
| `:::poll`            | sondage (v2, nécessite un stockage, hors périmètre au départ)                                                                      |

Règles :

- texte trop long pour une carte : erreur (règles de densité de `@recit/core`, seuils propres au
  format) ;
- image de fond sans `alt` en mode strict : erreur.

### Composants

`StoryPlayer` (racine), `StoryCard`, `ProgressBars` (une barre par carte), `TapZones` (précédent,
pause, suivant ; clavier et swipe), `StoryCTA`, `StoryCover` (vignette ronde, à la Instagram),
`StoryRail` (rangée de vignettes de plusieurs stories), `MuteToggle`, `ShareButton`.

### Rendu et exports

- Web : lecteur plein écran sur mobile, cadre `9:16` centré sur desktop, embed dans le framework de
  sites. Préchargement de la carte suivante.
- `recit export --to images` produit un PNG par carte (`1080×1920`) pour les réseaux, capturé par la
  CLI à travers `@recit/paged/runner`. Pas de PDF pour `stories` (`15-export-pdf.md` §1).
  `recit render --as motion` produit un MP4 vertical (pont stories ⇄ motion).
- SEO : métadonnées compatibles avec le format Web Stories (à vérifier au moment de
  l'implémentation).

### Phases (P11)

- [ ] ST1 — `@recit/stories` : lecteur, composants, densité.
- [ ] ST2 — Intégration des blocs motion, ponts stories ⇄ motion, report → stories et calendar →
      stories.
- [ ] ST3 — Export d'images.
- [ ] ST4 — `examples/stories-launch` (en/fr), `sites/story` (story.recit.dev), `sites/docs` ›
      Formats › Stories.
- [ ] Tests : navigation (tap, clavier, swipe), lecture automatique, goldens des cartes.

## 7. Composants transverses à tous les formats

En plus des composants propres à chaque format, tous les formats partagent :

- les directives et composants de `@recit/core` / `@recit/deck` : `:::callout`, `:::card`, `:::col`,
  `:badge`, `:kbd`, `::image`, Mermaid, KaTeX, blocs de code Shiki, `:::component{name}` et les
  composants MDX de l'utilisateur ;
- les composants de données de `@recit/data` : `:value`, `::chart`, `::table`, `:::kpi` ;
- les composants d'intégration de `@recit/site-stories` : `StoryEmbed` (prop `format`, `view`,
  `locale`) et `StoryGallery` (filtrable par format).

Les composants communs aux **sites** (en-tête, sélecteur de sites et de langue, hero, galerie,
gabarits, pied de page) sont décrits dans `07-domaines.md` §4.

## 8. Impact sur le reste du plan

| Fichier              | Ce qui change                                                                                                                                                                                                                                                                                             |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `02-architecture.md` | `StoryFormat` couvre les neuf formats. Les ponts sont listés ici, en §0                                                                                                                                                                                                                                   |
| `03-packaging.md`    | `@recit/report`, `@recit/toon`, `@recit/book` deviennent des packages planifiés (P6, P7, P8). Ajout de `@recit/data` (fondations) et `@recit/paged` (outils, Node, importé par la CLI seulement). Puis `@recit/roadmap`, `@recit/calendar`, `@recit/stories` (P9, P10, P11) et `@recit/time` (fondations) |
| `07-domaines.md`     | report.recit.dev, webtoon.recit.dev et book.recit.dev deviennent des sites planifiés, ouverts à la sortie de leur format. Même chose pour roadmap.recit.dev, calendar.recit.dev et story.recit.dev                                                                                                        |
| `06-roadmap.md`      | P6 Report, P7 Webtoon, P8 Book, P9 Roadmap, P10 Calendar, P11 Stories, puis P12 1.0                                                                                                                                                                                                                       |
| `brand/`             | icônes `fmt-report`, `fmt-toon` et `fmt-book` à harmoniser avec Q07. Icônes `fmt-roadmap`, `fmt-calendar` et `fmt-stories` à créer, dans la même famille, dans la teinte unique                                                                                                                           |

## 9. Risques propres à ces formats

| Risque                                                                  | Parade                                                                                                                                                     |
| ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| La pagination navigateur (Paged.js) est fragile sur les longs documents | goldens PDF page par page. `@recit/paged` isole le moteur, qu'on peut remplacer (par exemple par un moteur CSS Paged Media natif) sans toucher aux formats |
| Le poids des images de webtoon (lecture mobile)                         | conversion WebP/AVIF au build, `srcset`, budget de poids avec avertissement                                                                                |
| Les specs des plateformes de webtoon changent                           | préréglages versionnés et documentés, avec une date de vérification                                                                                        |
| Des chiffres faux dans un rapport                                       | `:value` obligatoire pour les nombres issus des données. Le lint signale les nombres écrits en dur à côté d'un `::chart` (avertissement)                   |
| Fuseaux horaires et changements d'heure (calendar)                      | `@recit/time` testé sur les changements d'heure. Les heures sont toujours stockées avec leur fuseau, et l'affichage est converti                           |
| Une roadmap publique qui promet des dates                               | dates optionnelles, vue `now-next-later` par défaut sans dates                                                                                             |
| Confusion entre `Story` (modèle) et `stories` (format)                  | le format garde le pluriel. La doc a un glossaire                                                                                                          |
| EPUB invalide sur certaines liseuses                                    | `epubcheck` en CI, tests manuels sur Apple Books, Kobo et Calibre avant la 1.0                                                                             |
| Trop de formats en parallèle                                            | un format à la fois (P6 → P11). Chacun a son critère de sortie avant d'attaquer le suivant                                                                 |

## 10. Formats et blocs proposés par le backlog (plans 10 à 14)

Ces idées viennent de `sites/plans/pages/archive/BACKLOG_IDEA.md`. Leur ordre et leurs options ont
été acceptés le 24/10/2026 (décisions réversibles, `06-roadmap.md`), et leur spec complète est dans
leur propre plan. Elles arriveraient après la 1.0, avec un petit lot avancé dans une phase existante
(`06-roadmap.md`, « Backlog : plans 10 à 14 »). Les neuf formats ci-dessus restent ceux de la 1.0 ;
un format ajouté ensuite est un ajout compatible en `v1`.

| Proposition              | Nature                                        | Package                                     | Site                    | Phase (lot avancé) | Spec                       |
| ------------------------ | --------------------------------------------- | ------------------------------------------- | ----------------------- | ------------------ | -------------------------- |
| `:::form` et contrat API | bloc transverse ; format `form` en option     | `@recit/form` (fondation)                   | form.recit.dev          | P13 (P10)          | `10-formulaires.md`        |
| `pixel`, `textcard`      | blocs transverses, pas de format              | `@recit/components`, `@recit/motion-blocks` | motion.recit.dev/images | — (P11)            | `11-images.md`             |
| `glossary`, `directory`  | deux formats, un package ; `:term` transverse | `@recit/directory`                          | directory.recit.dev     | P14 (P9)           | `12-glossaire-annuaire.md` |
| `::map`, `atlas`         | bloc transverse ; format `atlas` retenu (P15) | `@recit/geo` (fondation), `@recit/atlas`    | maps.recit.dev          | P15 (P6)           | `13-cartes.md`             |
| bible et scénariste      | outillage, doc et site, pas de format         | `@recit/scenario` (fondation)               | ai.recit.dev            | P16 (P7)           | `14-ia-scenario.md`        |

Ponts proposés par ces plans (form → deck, atlas → motion, bible → book, stories → toon…) : listés
dans chaque plan, ajoutés au tableau du §0 seulement quand leur phase est décidée.
