Spaces:
Running
Running
File size: 26,633 Bytes
179bb0f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 | # Spécification produit et technique
## Portail universel de recherche IIIF + lecture Mirador + connecteurs MCP
## 1. Résumé exécutif
Objectif : créer une application web déployable sur un Hugging Face Space permettant de rechercher des objets patrimoniaux dans plusieurs bibliothèques et musées numériques du monde, d’afficher une galerie de résultats unifiée, puis d’ouvrir directement les objets sélectionnés dans Mirador pour lecture, comparaison et navigation.
Le produit doit être pensé comme trois couches distinctes :
1. **Couche découverte** : moteur fédéré de recherche multi-sources.
2. **Couche lecture** : viewer IIIF basé sur Mirador.
3. **Couche interopérabilité** : API interne normalisée et outils MCP permettant à un agent IA ou à un autre client de lancer une recherche, récupérer un manifest et ouvrir une ressource dans Mirador.
Le projet ne doit pas supposer que Mirador sait faire la recherche. Mirador est uniquement la couche d’affichage.
---
## 2. Vision produit
### 2.1 Problème
Aujourd’hui, les ressources IIIF sont dispersées entre de nombreuses institutions. Même quand les objets sont accessibles, l’utilisateur doit souvent :
* connaître l’institution à l’avance ;
* chercher sur plusieurs interfaces différentes ;
* comprendre des modèles de données hétérogènes ;
* récupérer manuellement les manifests ;
* changer de viewer selon l’établissement.
### 2.2 Proposition de valeur
Le produit doit offrir une expérience simple :
**Chercher partout, lire tout de suite, comparer dans le même viewer.**
### 2.3 Utilisateurs cibles
* chercheurs en histoire, histoire de l’art, philologie, humanités numériques ;
* conservateurs, documentalistes, bibliothécaires ;
* étudiants ;
* amateurs avancés ;
* développeurs IA ou agents utilisant MCP.
### 2.4 Promesse utilisateur
Un utilisateur tape une requête unique, obtient une galerie d’objets provenant de plusieurs institutions, filtre les résultats, puis ouvre un ou plusieurs objets dans Mirador sans avoir à manipuler les manifests manuellement.
---
## 3. Périmètre du MVP
Le MVP doit rester réaliste, robuste et simple à déployer.
### 3.1 Ce que le MVP doit faire
* proposer une recherche fédérée sur un petit nombre de sources initiales ;
* normaliser les résultats dans un format unique ;
* afficher une galerie de résultats ;
* ouvrir un résultat dans Mirador via son manifest IIIF ;
* permettre l’ouverture de plusieurs objets en parallèle dans Mirador ;
* exposer les fonctions principales via une API interne ;
* exposer éventuellement ces fonctions via MCP.
### 3.2 Sources initiales recommandées pour le MVP
Commencer avec 3 à 5 connecteurs maximum.
Je recommande :
* Gallica / BnF
* Bodleian Digital
* Europeana
* un connecteur générique IIIF manifest-by-URL
* éventuellement une source de démonstration simple et stable
### 3.3 Ce que le MVP ne doit pas faire
* pas de moissonnage global du web patrimonial ;
* pas d’index mondial complet ;
* pas de promesse de couverture exhaustive ;
* pas de création de compte utilisateur ;
* pas d’annotation collaborative persistante dans la première version ;
* pas de recherche plein texte universelle sur tous les OCR du monde.
---
## 4. Principes de conception
### 4.1 Architecture modulaire
Chaque source doit être branchée via un connecteur indépendant. L’ajout d’une nouvelle institution ne doit pas nécessiter de modifier le cœur applicatif.
### 4.2 Dégradation élégante
Si une source ne fournit pas toutes les métadonnées attendues, le système doit renvoyer un résultat partiel plutôt qu’un échec global.
### 4.3 Transparence
Chaque résultat doit afficher clairement :
* l’institution source ;
* le type de source ;
* l’URL de notice ;
* la disponibilité ou non d’un manifest IIIF ;
* les droits si connus.
### 4.4 IIIF-first mais pas IIIF-only
Le système privilégie les ressources IIIF, mais il doit accepter que certains catalogues aient une recherche propre et un accès au manifest indirect.
### 4.5 Viewer séparé du moteur
Mirador ne contient aucune logique de recherche métier. Il reçoit des manifests déjà identifiés par la couche découverte.
---
## 5. Cas d’usage
### 5.1 Recherche simple
L’utilisateur tape « book of hours » et voit des résultats venant de plusieurs institutions.
### 5.2 Filtrage
L’utilisateur filtre par institution, type d’objet, langue, période ou disponibilité IIIF.
### 5.3 Lecture
L’utilisateur clique sur un résultat et l’objet s’ouvre dans Mirador.
### 5.4 Comparaison
L’utilisateur sélectionne plusieurs résultats et les ouvre côte à côte dans Mirador.
### 5.5 Import manuel
L’utilisateur colle l’URL d’un manifest IIIF ou d’une notice ; le système tente de détecter le manifest et l’ouvre.
### 5.6 Usage agentique
Un agent appelle le serveur MCP pour rechercher « Dante manuscript », filtre les résultats par institution, récupère les manifests et renvoie au client une URL d’ouverture dans Mirador.
---
## 6. Fonctionnalités détaillées
## 6.1 Onglet Recherche
Doit contenir :
* champ de recherche plein texte ;
* bouton rechercher ;
* filtres latéraux ;
* sélecteur de sources ;
* mode recherche simple / avancée ;
* affichage galerie ;
* pagination ou scroll infini.
### 6.1.1 Recherche simple
Un seul champ libre interroge plusieurs sources.
### 6.1.2 Recherche avancée
Champs optionnels :
* mots-clés ;
* institution ;
* type de document ;
* langue ;
* date min ;
* date max ;
* disponibilité IIIF ;
* présence d’image ;
* présence d’OCR.
### 6.1.3 Galerie de résultats
Chaque carte doit afficher :
* miniature ;
* titre ;
* institution ;
* type d’objet ;
* date ;
* auteur / créateur si disponible ;
* indicateur IIIF ;
* indicateur OCR ;
* lien notice ;
* bouton « Ouvrir dans Mirador » ;
* case à cocher « comparer ».
## 6.2 Onglet Lecture
Cet onglet embarque Mirador.
Fonctions attendues :
* ouverture d’un manifest ;
* ouverture de plusieurs manifests ;
* disposition multi-fenêtres ;
* zoom, rotation, navigation canvas/page ;
* panneau métadonnées ;
* bouton partage d’URL ;
* bouton retour résultats.
## 6.3 Barre d’actions rapides
Visible depuis les cartes de résultats :
* ouvrir ;
* ajouter à la comparaison ;
* copier manifest ;
* copier notice ;
* ouvrir dans un nouvel onglet.
## 6.4 Import manuel
Une interface doit permettre :
* de coller une URL de manifest ;
* de coller une URL de notice ;
* de saisir un identifiant connu selon certaines sources.
Le backend tente alors :
1. de reconnaître la source ;
2. de récupérer le manifest ;
3. de charger Mirador.
## 6.5 Journal de transparence
Pour chaque résultat, un panneau optionnel « Voir la provenance » doit pouvoir afficher :
* connecteur utilisé ;
* requête envoyée ;
* temps de réponse ;
* niveau de confiance de normalisation ;
* champs absents.
---
## 7. Architecture globale
## 7.1 Vue d’ensemble
Le système comporte :
### Frontend
* application React ou Next.js ;
* interface utilisateur ;
* intégration Mirador ;
* gestion de l’état ;
* appel à l’API backend.
### Backend
* FastAPI ;
* orchestrateur de recherche ;
* normalisation des métadonnées ;
* cache ;
* résolution de manifests ;
* endpoints REST ;
* couche MCP optionnelle.
### Déploiement
* Hugging Face Space Docker ;
* variables d’environnement ;
* stockage léger pour cache local ;
* logs standardisés.
---
## 8. Choix techniques recommandés
## 8.1 Frontend
* React + TypeScript
* Vite ou Next.js
* TanStack Query pour les appels réseau
* Zustand ou Redux Toolkit pour l’état global
* composant Mirador intégré dans une vue dédiée
* Tailwind CSS pour l’UI
## 8.2 Backend
* Python 3.11+
* FastAPI
* httpx pour appels asynchrones
* pydantic pour modèles
* cachetools ou redis optionnel si disponible
* structlog ou logging JSON
## 8.3 MCP
* couche séparée, facultative au démarrage
* outils exposés par-dessus les mêmes services métiers que le REST
* surtout aucune logique dupliquée entre REST et MCP
## 8.4 Déploiement
* conteneur unique au MVP
* frontend servi soit statiquement, soit via le backend
* config simple via variables d’environnement
---
## 9. Architecture logique détaillée
## 9.1 Modules backend
### a. Search Orchestrator
Responsabilités :
* recevoir une requête utilisateur ;
* sélectionner les connecteurs à appeler ;
* lancer les appels en parallèle ;
* agréger les réponses ;
* normaliser les résultats ;
* classer ;
* renvoyer la réponse unifiée.
### b. Connector Registry
Registre de tous les connecteurs disponibles.
Fonctions :
* lister les connecteurs ;
* indiquer leurs capacités ;
* savoir lesquels sont activés ;
* fournir l’instance du connecteur demandé.
### c. Source Connectors
Un connecteur par source.
Interface commune obligatoire :
* `search(query, filters, page, page_size)`
* `get_item(source_id)`
* `resolve_manifest(item_or_url)`
* `healthcheck()`
* `capabilities()`
### d. Normalization Layer
Transforme des réponses hétérogènes en schéma commun.
### e. Manifest Resolver
Essaye de trouver un manifest à partir de :
* métadonnées de résultat ;
* URL de notice ;
* endpoint spécifique de la source ;
* heuristiques configurées.
### f. Cache Layer
Cache des requêtes de recherche et des résolutions de manifest.
### g. MCP Adapter
Expose certains services backend sous forme d’outils MCP.
---
## 10. Contrat des connecteurs
Chaque connecteur doit implémenter une classe abstraite commune.
### 10.1 Interface conceptuelle
```python
class BaseConnector(ABC):
name: str
source_type: str
@abstractmethod
async def search(self, query: str, filters: dict, page: int, page_size: int) -> SearchResultPage:
...
@abstractmethod
async def get_item(self, source_id: str) -> NormalizedItem | None:
...
@abstractmethod
async def resolve_manifest(self, item: NormalizedItem | None = None, url: str | None = None) -> str | None:
...
@abstractmethod
async def capabilities(self) -> dict:
...
@abstractmethod
async def healthcheck(self) -> dict:
...
```
### 10.2 Capacités déclaratives
Un connecteur doit déclarer explicitement :
* recherche libre oui/non ;
* recherche structurée oui/non ;
* pagination oui/non ;
* facettes oui/non ;
* résolution manifest directe oui/non ;
* OCR signalé oui/non ;
* miniature disponible oui/non.
---
## 11. Schéma de données normalisé
## 11.1 Objet principal : NormalizedItem
```json
{
"id": "global-unique-id",
"source": "gallica",
"source_label": "Gallica / BnF",
"source_item_id": "ark-or-internal-id",
"title": "string",
"subtitle": "string|null",
"creators": ["string"],
"date_display": "string|null",
"date_sort": "string|null",
"languages": ["string"],
"object_type": "manuscript|book|image|map|newspaper|other",
"description": "string|null",
"thumbnail_url": "string|null",
"preview_image_url": "string|null",
"institution": "string|null",
"collection": "string|null",
"rights": "string|null",
"license": "string|null",
"record_url": "string|null",
"manifest_url": "string|null",
"iiif_image_service_url": "string|null",
"has_iiif_manifest": true,
"has_images": true,
"has_ocr": false,
"availability": "public|restricted|unknown",
"relevance_score": 0.0,
"raw_source_payload": {},
"normalization_warnings": ["string"]
}
```
## 11.2 Réponse de recherche
```json
{
"query": "book of hours",
"page": 1,
"page_size": 24,
"total_estimated": 214,
"results": [],
"sources_used": ["gallica", "bodleian", "europeana"],
"partial_failures": [
{
"source": "bodleian",
"error": null,
"status": "ok"
}
],
"duration_ms": 942,
"facets": {
"source": [],
"object_type": [],
"language": []
}
}
```
---
## 12. API REST interne
## 12.1 Endpoints principaux
### `GET /api/health`
Retourne l’état global de l’application.
### `GET /api/sources`
Retourne la liste des connecteurs actifs et leurs capacités.
### `POST /api/search`
Entrée :
```json
{
"query": "book of hours",
"sources": ["gallica", "bodleian"],
"filters": {
"object_type": ["manuscript"],
"language": ["lat"],
"has_iiif_manifest": true
},
"page": 1,
"page_size": 24,
"sort": "relevance"
}
```
Sortie : SearchResponse normalisée.
### `GET /api/item/{global_id}`
Retourne le détail d’un item normalisé.
### `POST /api/resolve-manifest`
Entrée :
```json
{
"source": "gallica",
"source_item_id": "identifier",
"record_url": "optional"
}
```
Sortie :
```json
{
"manifest_url": "https://.../manifest",
"status": "resolved",
"method": "metadata|heuristic|source-api"
}
```
### `POST /api/open`
Entrée :
```json
{
"manifest_urls": ["https://example.org/manifest/1"],
"workspace": "default"
}
```
Sortie :
```json
{
"mirador_state": {}
}
```
### `POST /api/import`
Permet d’importer une URL libre.
Entrée :
```json
{
"url": "https://example.org/item/or/manifest"
}
```
Sortie :
```json
{
"detected_source": "bodleian",
"record_url": "...",
"manifest_url": "...",
"item": {}
}
```
---
## 13. Outils MCP à exposer
Le serveur MCP doit réutiliser les mêmes services métiers que l’API REST.
### Outils minimum
#### `search_items`
Paramètres :
* query
* sources
* filters
* page
* page_size
Retour : liste normalisée de résultats.
#### `get_item`
Paramètres :
* global_id
Retour : détail d’un item.
#### `resolve_manifest`
Paramètres :
* global_id ou URL
Retour : manifest URL.
#### `open_in_mirador`
Paramètres :
* une ou plusieurs manifest URLs
Retour : URL d’ouverture ou état Mirador sérialisé.
#### `list_sources`
Retour : sources actives et capacités.
### Ressources MCP éventuelles
* catalogue des sources
* documentation des schémas
* exemples de requêtes
---
## 14. Intégration Mirador
## 14.1 Attentes fonctionnelles
Mirador doit être embarqué comme composant de lecture.
L’application doit pouvoir :
* initialiser Mirador avec zéro, une ou plusieurs fenêtres ;
* injecter dynamiquement les manifests sélectionnés ;
* mémoriser l’état courant de la session ;
* permettre un partage d’URL si possible.
## 14.2 Mode d’intégration
Créer un composant `MiradorWorkspace` qui reçoit une liste de manifests et une configuration.
Exemple de props :
```ts
interface MiradorWorkspaceProps {
manifestUrls: string[]
initialView?: "single" | "compare"
showMetadata?: boolean
onStateChange?: (state: unknown) => void
}
```
## 14.3 État applicatif
Le frontend doit stocker séparément :
* résultats de recherche ;
* sélection pour comparaison ;
* manifests ouverts ;
* configuration du workspace.
---
## 15. UI et UX détaillées
## 15.1 Navigation principale
* onglet Recherche
* onglet Lecture
* onglet Import
* onglet Sources
* onglet À propos
## 15.2 Page Recherche
### Colonne gauche
* sources
* type d’objet
* période
* langue
* disponibilité IIIF
* présence OCR
### Zone centrale
* barre de recherche
* tri
* nombre de résultats
* cartes résultats
### Colonne droite optionnelle
* panier de comparaison
* aperçu rapide du résultat sélectionné
## 15.3 Cartes résultats
Doivent être lisibles, homogènes et sobres.
Actions visibles :
* ouvrir
* comparer
* détails
## 15.4 Page Lecture
* bandeau avec titres des objets ouverts
* zone Mirador principale
* panneau latéral avec métadonnées et provenance
## 15.5 Page Sources
Affiche pour chaque source :
* nom
* description
* statut
* capacités
* notes spécifiques
* exemple de requête test
---
## 16. Classement et fusion des résultats
Le système doit agréger des résultats hétérogènes. Il faut donc définir une stratégie de ranking simple au MVP.
### 16.1 Score de base
Combiner :
* score natif de la source si disponible ;
* qualité de correspondance textuelle locale ;
* disponibilité d’un manifest ;
* présence d’une miniature ;
* complétude des métadonnées.
### 16.2 Déduplication légère
Tenter de détecter des doublons faibles via :
* titre normalisé ;
* identifiants communs ;
* URLs canoniques ;
* manifest identique.
En cas de doute, ne pas fusionner automatiquement au MVP.
---
## 17. Performance et robustesse
## 17.1 Appels concurrents
Le backend doit appeler les connecteurs en parallèle avec timeout par source.
## 17.2 Timeouts
Chaque source doit avoir :
* timeout connexion ;
* timeout lecture ;
* timeout global par requête.
## 17.3 Partial success
Si une source échoue, les autres résultats doivent quand même apparaître.
## 17.4 Cache
Mettre en cache :
* résultats de recherche récents ;
* résolutions de manifest ;
* capacités des sources.
## 17.5 Limitation
Ajouter un plafond raisonnable de sources interrogées simultanément au MVP.
---
## 18. Sécurité et conformité
## 18.1 Sécurité minimale
* validation stricte des URLs importées ;
* blocage des schémas non autorisés ;
* prévention SSRF basique ;
* limitation des domaines si nécessaire ;
* logs sans données sensibles.
## 18.2 Respect des sources
* afficher la source d’origine ;
* ne pas masquer les droits ;
* ne pas revendiquer la propriété des données ;
* lien systématique vers la notice d’origine.
## 18.3 CORS et proxy
Prévoir un backend pouvant agir comme intermédiaire pour certains appels si le frontend rencontre des restrictions cross-origin.
---
## 19. Observabilité
Prévoir :
* logs structurés ;
* mesure des temps par source ;
* taux de résolution des manifests ;
* taux d’échec par connecteur ;
* nombre moyen de résultats par source.
---
## 20. Arborescence de projet recommandée
```text
app/
frontend/
src/
components/
pages/
hooks/
store/
lib/
types/
backend/
app/
api/
services/
connectors/
models/
mcp/
utils/
config/
tests/
unit/
integration/
docs/
Dockerfile
docker-compose.yml
README.md
```
---
## 21. Plan de développement par étapes
## Phase 1 — socle
* boot frontend ;
* boot backend ;
* endpoint health ;
* intégration Mirador minimale ;
* schéma `NormalizedItem`.
## Phase 2 — connecteurs MVP
* connecteur Gallica ;
* connecteur Bodleian ;
* connecteur Europeana ;
* registre de connecteurs ;
* orchestration de recherche.
## Phase 3 — UX recherche
* galerie ;
* filtres ;
* pagination ;
* détail item ;
* ouverture Mirador.
## Phase 4 — import et résolution
* import URL ;
* résolution manifest ;
* comparaison multi-fenêtres.
## Phase 5 — MCP
* outils minimum ;
* documentation ;
* exemples clients.
## Phase 6 — polissage
* cache ;
* logs ;
* robustesse ;
* amélioration ranking.
---
## 22. Critères d’acceptation du MVP
Le MVP est considéré comme acceptable si :
1. une requête simple renvoie des résultats depuis au moins trois sources ;
2. les résultats sont affichés dans une galerie homogène ;
3. au moins 80 % des résultats disposant réellement d’un manifest peuvent être ouverts dans Mirador ;
4. l’ouverture de plusieurs objets dans Mirador fonctionne ;
5. l’échec d’une source n’empêche pas la réponse globale ;
6. l’API `/api/sources` décrit clairement les capacités ;
7. l’import d’une URL de manifest fonctionne ;
8. les fonctions principales sont exposées aussi via MCP si la couche MCP est activée.
---
## 23. Non-objectifs explicites
Le document doit clairement indiquer ce que le produit n’est pas :
* ce n’est pas un moteur de recherche web généraliste ;
* ce n’est pas un catalogue mondial exhaustif ;
* ce n’est pas une base propriétaire remplaçant les institutions ;
* ce n’est pas un viewer maison destiné à remplacer Mirador ;
* ce n’est pas une solution d’annotation scientifique complète au MVP.
---
## 24. Spécification pour génération de code par LLM
Le LLM chargé de coder le projet doit respecter les consignes suivantes.
### 24.1 Contraintes générales
* tout le code doit être typé ;
* tout le code doit être modulaire ;
* aucune logique métier dupliquée entre REST et MCP ;
* chaque connecteur doit être isolé ;
* chaque fonction publique doit avoir docstring ou commentaire clair ;
* les erreurs doivent être gérées proprement ;
* les appels réseau doivent être asynchrones côté backend.
### 24.2 Contraintes frontend
* TypeScript strict ;
* composants réutilisables ;
* éviter les dépendances inutiles ;
* UI simple et claire ;
* aucun style inline massif ;
* préférer Tailwind.
### 24.3 Contraintes backend
* FastAPI ;
* modèles Pydantic ;
* services séparés des routes ;
* tests unitaires des connecteurs ;
* tests d’intégration des endpoints.
### 24.4 Livrables attendus du LLM
* code complet frontend ;
* code complet backend ;
* Dockerfile ;
* README d’installation ;
* exemples `.env.example` ;
* tests minimum ;
* documentation d’API.
---
## 25. Prompt maître pour un LLM codeur
```text
Tu dois générer un projet complet déployable sur Hugging Face Spaces sous forme d’application web Docker.
Objectif du produit : une interface de recherche fédérée sur plusieurs sources patrimoniales, avec affichage d’une galerie de résultats normalisés, puis ouverture directe des objets dans Mirador à partir de leurs manifests IIIF.
Contraintes :
- frontend React + TypeScript ;
- backend FastAPI Python ;
- architecture modulaire ;
- connecteurs par source ;
- schéma de données normalisé ;
- Mirador intégré comme couche de lecture ;
- API REST interne ;
- couche MCP optionnelle mais prévue ;
- code propre, typé, documenté, testable.
Fonctionnalités MVP :
- champ de recherche ;
- sélection de sources ;
- filtres simples ;
- galerie de résultats ;
- bouton ouvrir dans Mirador ;
- comparaison multi-objets ;
- import manuel d’URL de manifest ;
- endpoint listant les sources et capacités.
Architecture attendue :
- dossier frontend ;
- dossier backend ;
- dossier tests ;
- Dockerfile ;
- README.
Backend :
- créer une interface abstraite BaseConnector ;
- implémenter un registry de connecteurs ;
- implémenter un orchestrateur de recherche ;
- définir les modèles Pydantic NormalizedItem, SearchResponse, SourceCapability ;
- créer les endpoints /api/health, /api/sources, /api/search, /api/item/{id}, /api/resolve-manifest, /api/import.
Frontend :
- créer une page Recherche ;
- créer une page Lecture avec Mirador ;
- créer un store pour la sélection des résultats ;
- créer des cartes de résultats ;
- permettre d’ouvrir un ou plusieurs manifests dans Mirador.
Important :
- ne pas coder de logique de recherche dans Mirador ;
- séparer nettement découverte et lecture ;
- gérer les erreurs partielles des sources ;
- prévoir des mocks si certaines API réelles sont instables.
Commence par générer l’arborescence complète du projet, puis le backend, puis le frontend, puis les tests, puis le Dockerfile et le README.
```
---
## 26. Prompts spécialisés par lot
## Prompt lot 1 — backend socle
```text
Génère uniquement le backend FastAPI du projet.
Exigences :
- Python 3.11+
- FastAPI
- Pydantic
- httpx async
- architecture modulaire
- BaseConnector abstraite
- ConnectorRegistry
- SearchOrchestrator
- modèles NormalizedItem, SearchResponse, SourceInfo
- endpoints : /api/health, /api/sources, /api/search, /api/item/{id}, /api/resolve-manifest, /api/import
- gestion d’erreurs propre
- docstrings
- tests unitaires de base
Ne génère pas encore le frontend.
```
## Prompt lot 2 — frontend socle
```text
Génère uniquement le frontend React + TypeScript du projet.
Exigences :
- page Recherche
- filtres latéraux
- galerie de résultats
- composant ResultCard
- store global pour manifests sélectionnés
- page Lecture intégrant Mirador
- navigation simple entre Recherche et Lecture
- Tailwind CSS
- code propre et typé
Le frontend doit appeler les endpoints du backend déjà définis.
```
## Prompt lot 3 — connecteurs
```text
Ajoute au backend un système de connecteurs source.
Exigences :
- implémenter BaseConnector
- créer au moins 3 connecteurs d’exemple
- chaque connecteur doit renvoyer des résultats normalisés
- prévoir un mode mock si la source distante n’est pas disponible
- ne pas dupliquer la logique de normalisation
```
## Prompt lot 4 — MCP
```text
Ajoute une couche MCP au backend existant.
Exigences :
- exposer les outils search_items, get_item, resolve_manifest, open_in_mirador, list_sources
- réutiliser les mêmes services métiers que les routes REST
- ne créer aucune duplication de logique
- fournir un exemple minimal d’utilisation par un client MCP
```
---
## 27. Backlog post-MVP
Après le MVP, prévoir :
* sauvegarde de sessions ;
* favoris ;
* export CSV / JSON des résultats ;
* partage de workspace Mirador ;
* annotation persistante ;
* index local optionnel ;
* détection de doublons plus avancée ;
* recherche intra-document via Content Search IIIF quand disponible ;
* enrichissement sémantique ;
* facettes avancées ;
* recommandation d’objets similaires.
---
## 28. Décisions produit à ne pas perdre
1. Mirador est la couche de lecture, jamais la couche de recherche.
2. Les connecteurs sont les unités fondamentales d’extension.
3. Le schéma normalisé est le cœur du projet.
4. Le MVP privilégie la simplicité et la robustesse sur l’exhaustivité.
5. Le MCP est utile comme surcouche d’interopérabilité, pas comme justification unique du produit.
---
## 29. Version courte à remettre à un développeur ou à un LLM
Créer une application web déployable sur Hugging Face Spaces qui permet de rechercher des objets patrimoniaux dans plusieurs institutions, d’afficher les résultats sous forme de galerie homogène, puis d’ouvrir directement les objets dans Mirador à partir de leurs manifests IIIF.
Le produit comprend :
* un frontend React/TypeScript ;
* un backend FastAPI ;
* des connecteurs source modulaires ;
* un schéma de données normalisé ;
* Mirador intégré ;
* une API REST ;
* une couche MCP optionnelle.
Le MVP doit inclure recherche fédérée, filtres simples, galerie, ouverture Mirador, comparaison multi-objets et import manuel d’URL de manifest.
Le système doit être robuste aux échecs partiels, simple à étendre et proprement documenté.
|