ObsiGate
Porte d'entrée web ultra-léger pour vos vaults Obsidian — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
┌─────────────────────────────────────────────────────────┐
│ [🔍 Recherche...] [☀/🌙 Thème] ObsiGate │
├──────────────┬──────────────────────────────────────────┤
│ SIDEBAR │ CONTENT AREA │
│ ▼ Recettes │ 📄 Titre du fichier │
│ 📁 Soupes │ Tags: #recette #rapide │
│ 📄 Pizza │ [Contenu Markdown rendu] │
│ ▼ IT │ │
│ 📁 Docker │ │
│ Tags Cloud │ │
└──────────────┴──────────────────────────────────────────┘
📋 Table des matières
- Fonctionnalités
- Architecture
- Prérequis
- Installation rapide
- Configuration détaillée
- Variables d'environnement
- Ajouter une nouvelle vault
- Build multi-platform
- Utilisation
- API
- Performance
- Dépannage
- Stack technique
- Changelog
✨ Fonctionnalités
- 🗂️ Multi-vault : Visualisez plusieurs vaults Obsidian simultanément
- 🌳 Navigation arborescente : Parcourez vos dossiers et fichiers dans la sidebar
- 🔍 Recherche avancée : Moteur TF-IDF avec normalisation des accents, snippets surlignés, facettes, pagination et tri
- 💡 Autocomplétion intelligente : Suggestions de fichiers, tags et historique avec navigation clavier
- 🧩 Syntaxe de requête : Opérateurs
tag:,#,vault:,title:,path:avec chips visuels - 📜 Historique de recherche : Persisté en localStorage (max 50 entrées, LIFO, dédupliqué)
- 🏷️ Tag cloud : Filtrage par tags extraits des frontmatters YAML
- 🔗 Wikilinks : Les
[[liens internes]]Obsidian sont cliquables - 🖼️ Images Obsidian : Support complet des syntaxes d'images Obsidian avec résolution intelligente
- 🎨 Syntax highlight : Coloration syntaxique des blocs de code
- 🌓 Thème clair/sombre : Toggle persisté en localStorage
- <EFBFBD> Synchronisation temps réel : Surveillance automatique des fichiers via watchdog avec mise à jour incrémentale de l'index
- 📡 Server-Sent Events : Notifications SSE pour les changements d'index avec reconnexion automatique
- ➕ Gestion dynamique des vaults : Ajout/suppression de vaults via API sans redémarrage
- <EFBFBD>🐳 Docker multi-platform : linux/amd64, linux/arm64, linux/arm/v7, linux/386
- 🔒 Sécurité : Protection contre le path traversal, utilisateur non-root dans Docker
- ❤️ Healthcheck : Endpoint
/api/healthintégré pour Docker et monitoring
🚀 Prérequis
Système requis
- Docker >= 20.10
- docker-compose >= 2.0
- Espace disque : ~200MB pour l'image Docker
Systèmes supportés
- Linux (Ubuntu, Debian, CentOS, etc.)
- macOS (Intel et Apple Silicon)
- Windows (avec Docker Desktop)
- NAS compatibles Docker (Synology, QNAP, etc.)
⚡ Installation rapide
1. Cloner le dépôt
git clone https://git.dracodev.net/Projets/ObsiGate.git
cd ObsiGate
2. Configurer vos vaults
Éditez le fichier docker-compose.yml pour ajouter vos vaults Obsidian :
volumes:
- /chemin/absolu/vers/votre/vault:/vaults/NomDeVotreVault:ro
Important
: Le chemin doit être absolu et le volume en lecture seule (
:ro)
3. Lancer l'application
# Build local de l'image + démarrage
docker-compose up -d --build
# Vérifier les logs
docker-compose logs -f obsigate
Note
: ObsiGate est construit localement depuis le
Dockerfiledu projet. Sans build local, Docker essaiera de télécharger une image distanteobsigate:latestqui n'existe pas forcément.
4. Accéder à l'interface
Ouvrez votre navigateur sur : http://localhost:2020
⚙️ Configuration détaillée
Étape 1 : Préparation des vaults
- Localisez vos vaults Obsidian sur votre système
- Notez les chemins absolus vers chaque dossier
.obsidian - Vérifiez les permissions : Docker doit pouvoir lire ces dossiers
Étape 2 : Configuration docker-compose.yml
Voici un exemple complet :
services:
obsigate:
build:
context: .
image: obsigate:latest
container_name: obsigate
restart: unless-stopped
ports:
- "2020:8080" # Port local 2020 → Port conteneur 8080
volumes:
# Exemples de vaults (adaptez à vos chemins)
- /home/user/Documents/Obsidian-Recettes:/vaults/Recettes:ro
- /home/user/Documents/Obsidian-IT:/vaults/IT:ro
- /home/user/Documents/Obsidian-Perso:/vaults/Perso:ro
environment:
# Configuration des vaults
- VAULT_1_NAME=Recettes
- VAULT_1_PATH=/vaults/Recettes
- VAULT_2_NAME=IT
- VAULT_2_PATH=/vaults/IT
- VAULT_3_NAME=Perso
- VAULT_3_PATH=/vaults/Perso
Étape 3 : Construction de l'image
# Build l'image Docker
docker build -t obsigate:latest .
# Puis démarrer le service
docker-compose up -d --build
# Ou utilisez le script de build multi-platform
chmod +x build.sh
./build.sh
Compatibilité Docker : l'image utilise la variante minimale de
uvicornet une version defastapicompatible (0.110.3) afin d'éviter certaines dépendances optionnelles natives (watchfiles,uvloop,httptools,fastapi-cli, etc.) qui peuvent échouer au build sur certaines plateformes comme Alpine, ARM ou i386.
🌍 Variables d'environnement
Les vaults sont configurées par paires de variables VAULT_N_NAME / VAULT_N_PATH (N = 1, 2, 3…) :
| Variable | Description | Exemple |
|---|---|---|
VAULT_1_NAME |
Nom affiché de la vault | Recettes |
VAULT_1_PATH |
Chemin dans le conteneur | /vaults/Obsidian-RECETTES |
VAULT_1_ATTACHMENTS_PATH |
Chemin relatif vers le dossier d'attachements (optionnel) | 06_Boite_a_Outils/6.2_Attachments |
VAULT_1_SCAN_ATTACHMENTS |
Activer le scan d'images au démarrage (optionnel, défaut: true) | true |
VAULT_2_NAME |
Nom affiché de la vault | IT |
VAULT_2_PATH |
Chemin dans le conteneur | /vaults/Obsidian_IT |
Règles de nommage :
- Utilisez uniquement des lettres, chiffres et tirets
- Pas d'espaces ou caractères spéciaux
- Le nom doit correspondre au chemin dans le conteneur
➕ Ajouter une nouvelle vault
Méthode 1 : Édition directe
-
Arrêtez le conteneur :
docker-compose down -
Ajoutez un volume dans
docker-compose.yml:volumes: - /nouveau/chemin/vault:/vaults/NouvelleVault:ro -
Ajoutez les variables d'environnement :
environment: - VAULT_4_NAME=NouvelleVault - VAULT_4_PATH=/vaults/NouvelleVault -
Redémarrez :
docker-compose up -d --build
Méthode 2 : Hot-reload (recommandé)
- Ajoutez le volume et les variables comme ci-dessus
- Appliquez les changements :
docker-compose up -d --build - Rechargez l'index via l'interface ou l'API :
curl http://localhost:2020/api/index/reload
Méthode 3 : API dynamique (sans redémarrage)
Ajoutez une vault à chaud via l'API (le volume doit déjà être monté) :
curl -X POST http://localhost:2020/api/vaults/add \
-H "Content-Type: application/json" \
-d '{"name": "NouvelleVault", "path": "/vaults/NouvelleVault"}'
Supprimez une vault :
curl -X DELETE http://localhost:2020/api/vaults/NouvelleVault
🔨 Build multi-platform
Pour les architectures multiples (Raspberry Pi, NAS, etc.) :
# Rendre le script exécutable
chmod +x build.sh
# Lancer le build multi-platform
./build.sh
Architectures supportées :
linux/amd64(PC, serveurs standards)linux/arm64(Raspberry Pi 4, Apple Silicon, NAS modernes)linux/arm/v7(Raspberry Pi 3, anciens NAS)linux/386(Systèmes 32-bit legacy)
Pour un build local uniquement :
docker buildx build --platform linux/amd64 --load -t obsigate:latest .
<EFBFBD>️ Rendu d'images Obsidian
ObsiGate supporte toutes les syntaxes d'images Obsidian avec un système de résolution intelligent multi-stratégies.
Syntaxes supportées
-
Standard Markdown avec attributs HTML (compatible Obsidian) :
[<img width="180" height="60" src="path/to/image.svg"/>](https://example.com) -
Wiki-link embed avec chemin complet :
![[06_Boite_a_Outils/6.2_Attachments/image.svg]] -
Wiki-link embed avec nom de fichier uniquement :
![[image.svg]] -
Markdown standard :

Résolution intelligente des chemins
ObsiGate utilise 7 stratégies de résolution par ordre de priorité :
- Chemin absolu : Si le chemin est absolu et existe
- Dossier d'attachements configuré : Via
VAULT_N_ATTACHMENTS_PATH - Index de démarrage (match unique) : Recherche par nom de fichier dans l'index
- Même répertoire : Relatif au fichier markdown courant
- Racine du vault : Relatif à la racine du vault
- Index de démarrage (match le plus proche) : Si plusieurs fichiers portent le même nom
- Fallback : Affiche un placeholder stylisé
[image not found: filename.ext]
Configuration
Pour optimiser la résolution, configurez le dossier d'attachements de chaque vault :
environment:
- VAULT_1_NAME=MonVault
- VAULT_1_PATH=/vaults/MonVault
- VAULT_1_ATTACHMENTS_PATH=Assets/Images # Chemin relatif
- VAULT_1_SCAN_ATTACHMENTS=true # Activer le scan (défaut)
Rescan manuel
Pour rescanner les images d'un vault après ajout/suppression :
curl -X POST http://localhost:2020/api/attachments/rescan/MonVault
<EFBFBD>📖 Utilisation
Interface web
- Navigation : Cliquez sur les vaults dans la sidebar pour les développer
- Recherche : Utilisez la barre de recherche pour chercher dans toutes les vaults
- Tags : Cliquez sur les tags pour filtrer les contenus
- Wikilinks : Les liens
[[page]]sont cliquables et navigables - Images : Toutes les syntaxes d'images Obsidian sont rendues automatiquement
- Thème : Basculez entre thème clair/sombre avec l'icône 🌙/☀️
Raccourcis clavier
| Action | Raccourci |
|---|---|
| Recherche | Ctrl + K ou / |
| Toggle thème | Ctrl + T |
| Focus recherche | Esc |
🔌 API
ObsiGate expose une API REST complète :
| Endpoint | Description | Méthode |
|---|---|---|
/api/health |
Health check (status, version, stats) | GET |
/api/vaults |
Liste des vaults configurées | GET |
/api/browse/{vault}?path= |
Navigation dans les dossiers | GET |
/api/file/{vault}?path= |
Contenu rendu d'un fichier | GET |
/api/file/{vault}/raw?path= |
Contenu brut d'un fichier | GET |
/api/file/{vault}/download?path= |
Téléchargement d'un fichier | GET |
/api/file/{vault}/save?path= |
Sauvegarder un fichier | PUT |
/api/file/{vault}?path= |
Supprimer un fichier | DELETE |
/api/search?q=&vault=&tag= |
Recherche fulltext (legacy) | GET |
/api/search/advanced?q=&vault=&tag=&limit=&offset=&sort= |
Recherche avancée TF-IDF avec facettes et pagination | GET |
/api/suggest?q=&vault=&limit= |
Suggestions de titres de fichiers (autocomplétion) | GET |
/api/tags/suggest?q=&vault=&limit= |
Suggestions de tags (autocomplétion) | GET |
/api/tags?vault= |
Tags uniques avec compteurs | GET |
/api/index/reload |
Force un re-scan des vaults | GET |
/api/events |
Flux SSE temps réel (index updates, vault changes) | GET |
/api/vaults/add |
Ajouter une vault dynamiquement | POST |
/api/vaults/{name} |
Supprimer une vault | DELETE |
/api/vaults/status |
Statut détaillé des vaults (fichiers, watching) | GET |
/api/image/{vault}?path= |
Servir une image avec MIME type approprié | GET |
/api/attachments/rescan/{vault} |
Rescanner les images d'un vault | POST |
/api/attachments/stats?vault= |
Statistiques d'images indexées | GET |
/api/config |
Lire la configuration | GET |
/api/config |
Mettre à jour la configuration | POST |
/api/diagnostics |
Statistiques index, mémoire, moteur de recherche | GET |
Tous les endpoints exposent des schémas Pydantic documentés. La doc interactive est disponible sur
/docs(Swagger UI).
Exemple d'utilisation :
# Health check
curl http://localhost:2020/api/health
# Lister les vaults
curl http://localhost:2020/api/vaults
# Recherche simple (legacy)
curl "http://localhost:2020/api/search?q=recette&vault=all"
# Recherche avancée avec TF-IDF, facettes et pagination
curl "http://localhost:2020/api/search/advanced?q=recette%20tag:cuisine&vault=all&limit=20&offset=0&sort=relevance"
# Autocomplétion de titres
curl "http://localhost:2020/api/suggest?q=piz&vault=all"
# Autocomplétion de tags
curl "http://localhost:2020/api/tags/suggest?q=rec&vault=all"
# Obtenir un fichier
curl "http://localhost:2020/api/file/Recettes?path=pizza.md"
🔍 Recherche avancée
Syntaxe de requête
| Opérateur | Description | Exemple |
|---|---|---|
tag:<nom> |
Filtrer par tag | tag:recette docker |
#<nom> |
Raccourci tag | #linux serveur |
vault:<nom> |
Filtrer par vault | vault:IT kubernetes |
title:<texte> |
Filtrer par titre | title:pizza |
path:<texte> |
Filtrer par chemin | path:recettes/soupes |
"phrase exacte" |
Recherche de phrase | tag:"multi mots" |
Les opérateurs sont combinables : tag:linux vault:IT serveur web recherche "serveur web" dans le vault IT avec le tag linux.
Raccourcis clavier
| Raccourci | Action |
|---|---|
Ctrl+K / Cmd+K |
Focaliser la barre de recherche |
/ |
Focaliser la recherche (hors champ texte) |
↑ / ↓ |
Naviguer dans les suggestions |
Enter |
Sélectionner la suggestion active ou lancer la recherche |
Escape |
Fermer les suggestions / quitter la recherche |
Fonctionnalités
- TF-IDF : Scoring basé sur la fréquence des termes pondérée par l'inverse de la fréquence documentaire
- Boost titre : Les correspondances dans le titre reçoivent un score 3× supérieur
- Normalisation des accents :
resumetrouverésumé,elephanttrouveéléphant - Snippets surlignés : Les termes trouvés sont encadrés par
<mark>dans les extraits - Facettes : Compteurs par vault et par tag dans les résultats
- Pagination : Navigation par pages de 50 résultats
- Tri : Par pertinence (TF-IDF) ou par date de modification
- Chips visuels : Les filtres actifs sont affichés comme des chips colorés supprimables
- Historique : Les 50 dernières recherches sont mémorisées en localStorage
🔧 Dépannage
Problèmes courants
Port déjà utilisé :
# Vérifier qui utilise le port
sudo netstat -tulpn | grep 2020
# Changer le port dans docker-compose.yml
ports:
- "2021:8080"
Vault non trouvée :
- Vérifiez que les chemins sont absolus
- Assurez-vous que les permissions permettent la lecture
- Redémarrez le conteneur après modification
Build échoue :
# Nettoyer et rebuild
docker system prune -f
docker-compose down
docker build --no-cache -t obsigate:latest .
docker-compose up -d
Logs pour debugging :
# Logs en temps réel
docker-compose logs -f obsigate
# Logs détaillés
docker-compose logs --tail=100 obsigate
⚡ Performance
| Métrique | Estimation |
|---|---|
| Indexation | ~1–2s pour 1 000 fichiers markdown |
| Recherche avancée | < 10ms pour la plupart des requêtes (index inversé + TF-IDF) |
| Résolution wikilinks | O(1) via table de lookup |
| Mémoire | ~80–150MB par 1 000 fichiers (contenu capé à 100 KB/fichier) |
| Image Docker | ~180MB (multi-stage, sans outils de build) |
| CPU | Non-bloquant ; recherche offloadée sur thread pool dédié |
Paramètres recommandés par taille de vault
| Taille | Fichiers | search_workers |
prefix_max_expansions |
max_content_size |
|---|---|---|---|---|
| Petit | < 500 | 1 | 50 | 100 000 |
| Moyen | 500–5 000 | 2 | 50 | 100 000 |
| Grand | 5 000+ | 4 | 30 | 50 000 |
Ces paramètres sont configurables via l'interface (Settings) ou l'API /api/config.
Optimisations clés (v1.2.0)
- Index inversé avec set-intersection : la recherche utilise les posting lists pour un retrieval O(k × postings) au lieu de O(N) scan complet
- Prefix matching par recherche binaire : O(log V + k) au lieu de O(V) scan linéaire du vocabulaire
- ThreadPoolExecutor : les fonctions de recherche CPU-bound sont offloadées du event loop asyncio
- Race condition guard :
currentSearchId+AbortControllerempêchent le rendu de résultats obsolètes - Progress bar : barre de progression animée pendant la recherche
- Search timeout : abandon automatique après 30s (configurable)
- Query time display : temps serveur affiché dans les résultats (
query_time_ms) - Staleness detection fix : utilisation d'un compteur de génération au lieu de
id(index)pour détecter les changements d'index
Optimisations v1.1.0
- Recherche sans I/O : le contenu des fichiers est mis en cache dans l'index mémoire
- Scoring multi-facteurs : titre exact (+20), titre partiel (+10), chemin (+5), tag (+3), fréquence contenu (x1 par occurrence, capé à 10)
- Rendu Markdown singleton : le renderer mistune est instancié une seule fois
- AbortController : les requêtes de recherche obsolètes sont annulées côté client
- Debounced icon rendering :
lucide.createIcons()est batché viarequestAnimationFrame
🛡️ Sécurité
- Path traversal : tous les endpoints fichier valident que le chemin résolu reste dans la vault
- Utilisateur non-root : le conteneur Docker tourne sous l'utilisateur
obsigate - Volumes read-only : les vaults sont montées en
:ropar défaut dans docker-compose
🏗️ Stack technique
- Backend : Python 3.11 + FastAPI 0.110 + Uvicorn
- File Watcher : watchdog 4.x (inotify natif + fallback polling)
- Frontend : Vanilla JS + HTML + CSS (zéro framework, zéro build)
- Rendu Markdown : mistune 3.x
- Image Docker : python:3.11-slim (multi-stage)
- Base de données : Aucune (index en mémoire uniquement)
- Architecture : SPA + API REST + SSE
🏠 Architecture
┌─────────────────┐ ┌─────────────────────────────────────────┐
│ Navigateur │◄───►│ FastAPI (backend/main.py) │
│ (SPA) │ REST │ │
│ │ │ ┌──────────────┐ ┌──────────────┐ │
│ app.js │ │ │ indexer.py │ │ search.py │ │
│ style.css │ │ │ (scan+cache)│ │ (in-memory) │ │
│ index.html │ │ └───────┬──────┘ └──────┬───────┘ │
└─────────────────┘ │ │ │ │
│ └──────┬───────┘ │
│ │ │
│ ┌────────┴─────────┐ │
│ │ Index en mémoire │ │
│ │ (fichiers, tags, │ │
│ │ contenu, lookup)│ │
│ └──────────────────┘ │
└─────────────────────────────────────────┘
┌───────────────────────────────┐
│ Filesystem (vaults montées) │
│ /vaults/Recettes (ro) │
│ /vaults/IT (ro) │
└───────────────────────────────┘
Flux de données :
- Au démarrage,
indexer.pyscanne tous les vaults en parallèle (thread pool) - Le contenu, les tags (YAML + inline) et les métadonnées sont mis en cache en mémoire
- Une table de lookup O(1) est construite pour la résolution des wikilinks
watcher.pydémarre la surveillance des fichiers (watchdog natif ou polling)- Les modifications détectées déclenchent une mise à jour incrémentale de l'index
- Les changements sont notifiés au frontend via Server-Sent Events (SSE)
- Les requêtes de recherche utilisent l'index en mémoire (zéro I/O disque)
- Le frontend SPA communique via REST + SSE et gère l'état côté client
📝 Développement
Structure du projet
ObsiGate/
├── backend/ # API FastAPI
│ ├── main.py # Endpoints, Pydantic models, rendu markdown
│ ├── indexer.py # Scan des vaults, index en mémoire, lookup table
│ ├── search.py # Moteur de recherche fulltext avec scoring
│ ├── watcher.py # Surveillance fichiers (watchdog + debounce)
│ └── requirements.txt
├── frontend/ # Interface web (Vanilla JS, zéro framework)
│ ├── index.html # Page SPA + modales (aide, config, éditeur)
│ ├── app.js # Logique SPA, gestion d'état, API client
│ └── style.css # Styles (CSS variables, thèmes, responsive)
├── Dockerfile # Multi-stage, healthcheck, non-root
├── docker-compose.yml # Déploiement avec healthcheck
├── build.sh # Build multi-platform (amd64/arm64/arm/v7/i386)
└── CONTRIBUTING.md # Guide de contribution
Contribuer
Voir CONTRIBUTING.md pour les détails.
📄 Licence
Ce projet est sous licence MIT - voir le fichier LICENSE pour les détails.
🤝 Support
- Issues : git.dracodev.net/Projets/ObsiGate/issues
- Documentation : git.dracodev.net/Projets/ObsiGate/wiki
- Auteur : Bruno Beloeil
📝 Changelog
v1.3.0 (2025)
Synchronisation temps réel
- Surveillance automatique des fichiers via
watchdogavec fallback polling automatique - Mise à jour incrémentale de l'index : ajout, modification, suppression et déplacement de fichiers sans rebuild complet
- Server-Sent Events (SSE) : endpoint
/api/eventspour notifications temps réel vers le frontend - Badge de synchronisation dans le header avec indicateur visuel (connecté/déconnecté/syncing)
- Panel d'événements récents accessible en cliquant sur le badge
- Reconnexion SSE automatique avec backoff exponentiel
- Toast informatif à chaque mise à jour détectée
- Rafraîchissement automatique de la sidebar et du fichier courant si affecté
Gestion dynamique des vaults
POST /api/vaults/add: ajouter une vault à chaud sans redémarrageDELETE /api/vaults/{name}: supprimer une vault de l'indexGET /api/vaults/status: statut détaillé (fichiers, tags, état de surveillance)- Les vaults ajoutées sont automatiquement surveillées par le watcher
Configuration watcher
- Nouveaux paramètres dans
config.json:watcher_enabled,watcher_use_polling,watcher_polling_interval,watcher_debounce - Section « Synchronisation automatique » dans la modal de configuration frontend
- Toggles pour activer/désactiver la surveillance et le mode polling
v1.2.0 (2025)
Performance (critique)
- Réécriture du moteur
advanced_search(): retrieval par set-intersection sur l'index inversé (O(k × postings) au lieu de O(N)) - Prefix matching par recherche binaire sur liste triée de tokens (O(log V + k) au lieu de O(V))
- Offload des fonctions de recherche CPU-bound via
ThreadPoolExecutor(2 workers par défaut) - Pré-calcul des expansions de préfixe pour éviter les recherches binaires répétées
- Fix du bug de staleness :
is_stale()utilise un compteur de génération au lieu deid(index)
Frontend
- Guard contre les race conditions :
currentSearchIdvérifié après chaquefetchavant rendu - Barre de progression animée pendant la recherche
- Timeout de recherche configurable (30s par défaut)
- Longueur minimale de requête configurable (2 caractères par défaut)
- Affichage du temps de requête serveur (
query_time_ms) dans les résultats - Pagination ajoutée sur l'endpoint legacy
/api/search(paramslimit/offset)
Configuration & Diagnostics
- Nouveaux endpoints
GET/POST /api/configpour la configuration persistante (config.json) - Nouveau endpoint
GET /api/diagnostics(stats index, mémoire, moteur de recherche) - Page de configuration étendue : paramètres frontend (debounce, résultats/page, timeout) et backend (workers, boosts, expansions)
- Panel de diagnostics intégré dans la modal de configuration
- Boutons « Forcer réindexation » et « Réinitialiser » dans les paramètres
v1.1.0 (2025)
Sécurité
- Protection path traversal sur tous les endpoints fichier
- Utilisateur non-root dans le conteneur Docker
- Dockerfile multi-stage (élimination des outils de build)
Performance
- Recherche fulltext en mémoire (zéro I/O disque par requête)
- Table de lookup O(1) pour la résolution des wikilinks
- Renderer mistune mis en cache (singleton)
- Scoring multi-facteurs (titre, chemin, tags, fréquence)
lucide.createIcons()batché viarequestAnimationFrameAbortControllersur les requêtes de recherche
Robustesse
- Swap atomique de l'index (thread-safe) pendant le reload
- Extraction des tags inline (#tag) depuis le contenu markdown
- Modèles Pydantic sur tous les endpoints API
- Gestion d'erreurs avec toasts utilisateur (frontend)
- États de chargement pour la sidebar et le contenu
- Remplacement de
on_eventdéprécié parlifespan
Infrastructure
- Endpoint
/api/healthpour monitoring - Healthcheck Docker (Dockerfile + docker-compose)
build.shamélioré (variable version, checks, couleurs)
Documentation
- Docstrings complètes sur toutes les fonctions Python
- Schémas Pydantic documentés (Swagger UI auto-générée)
- README : sections Architecture, Performance, Sécurité, Changelog
- CONTRIBUTING.md ajouté
v1.0.0 (2025)
- Version initiale
Projet : ObsiGate | Version : 1.2.0 | Dernière mise à jour : 2025