SPB Git forge

spb/fabri-ka

Public

Agrégateur de produits québécois — www.fabri-ka.com

217commits 1branches 0releases
66.1 MBsize
maindefault branch
6 h agolast push
Python 38.4% HTML 30.3% TypeScript 17.2% CSS 11% JavaScript 3.2%

Reapply "feat(doc): page documentation /doc (guide + captures) + lien footer + PDF téléchargeable"

This reverts commit 5e1cac24bce561a01122a01c79de83a11e9bce79.
Simon-Pierre Boucher committed 1 mo ago (Aug 24, 2026) parent fc592f0

8 changed files +206 −2

modified fabrika/web.py +10 −1
@@ -14,7 +14,7 @@ from pathlib import Path
14 14
15 15 from fastapi import BackgroundTasks, Body, FastAPI, HTTPException, Query, Request
16 16 from fastapi.middleware.gzip import GZipMiddleware
17 −from fastapi.responses import FileResponse
17 +from fastapi.responses import FileResponse, RedirectResponse
18 18 from fastapi.staticfiles import StaticFiles
19 19
20 20 from . import auth, db, hubfav, inscriptions, seo
@@ -538,6 +538,15 @@ class HashedStaticFiles(StaticFiles):
538 538 if FRONT_DIST.exists():
539 539 app.mount("/assets", HashedStaticFiles(directory=FRONT_DIST / "assets"), name="assets")
540 540
541 + @app.get("/doc", include_in_schema=False)
542 + def doc_redirect():
543 + return RedirectResponse("/doc/", status_code=301)
544 +
545 + # /doc : documentation statique (index.html + captures + PDF) — montée
546 + # explicitement pour que le catch-all SPA ne l'intercepte pas.
547 + if (FRONT_DIST / "doc").is_dir():
548 + app.mount("/doc", StaticFiles(directory=FRONT_DIST / "doc", html=True), name="doc")
549 +
541 550 @app.get("/{path:path}")
542 551 def spa(path: str, request: Request):
543 552 target = FRONT_DIST / path
added frontend/public/doc/fabri-ka-documentation.pdf +0 −0

Binary file not shown.

added frontend/public/doc/img/etape1.png +0 −0

Binary file not shown.

added frontend/public/doc/img/etape2.png +0 −0

Binary file not shown.

added frontend/public/doc/img/etape3.png +0 −0

Binary file not shown.

added frontend/public/doc/img/etape4.png +0 −0

Binary file not shown.

added frontend/public/doc/index.html +195 −0
@@ -0,0 +1,195 @@
1 +<!DOCTYPE html>
2 +<html lang="fr">
3 +<head>
4 +<meta charset="utf-8">
5 +<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6 +<title>Documentation — Fabri·Ka</title>
7 +<meta name="description" content="Comment fonctionne Fabri·Ka : guide pas à pas, données, architecture.">
8 +<style>
9 + :root{ --ink:#101014; --paper:#faf9f6; --accent:#c4532e; --muted:#6b6b70; --line:#e6e4de; }
10 + *{box-sizing:border-box} html,body{margin:0;padding:0;background:var(--paper);color:var(--ink);
11 + font:16px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;-webkit-text-size-adjust:100%}
12 + .container{max-width:960px;margin:0 auto;padding:0 20px}
13 + header.doc{background:var(--ink);color:var(--paper);padding:20px 0}
14 + header.doc .container{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
15 + header.doc a{color:var(--paper);text-decoration:none}
16 + .wordmark{font-weight:800;font-size:20px;letter-spacing:.02em}
17 + .wordmark .ka{color:var(--accent)}
18 + .btn-pdf{display:inline-block;background:var(--accent);color:#fff;font-weight:700;
19 + padding:10px 18px;border-radius:999px;text-decoration:none;font-size:15px}
20 + header.doc .btn-pdf{color:#fff}
21 + .hero{padding:48px 0 8px}
22 + .hero h1{font-size:clamp(28px,5vw,44px);line-height:1.1;margin:0 0 12px}
23 + .hero h1 mark{background:var(--accent);color:#fff;padding:2px 8px}
24 + .hero p.lead{font-size:18px;color:var(--muted);max-width:640px}
25 + .kicker{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
26 + border-left:3px solid var(--accent);padding-left:10px;margin:40px 0 8px;font-weight:700}
27 + section{padding:8px 0 16px}
28 + h2{font-size:26px;margin:6px 0 12px}
29 + .step{display:grid;grid-template-columns:56px 1fr;gap:16px;margin:26px 0;align-items:start}
30 + .step .num{width:44px;height:44px;border-radius:50%;background:var(--ink);color:var(--accent);
31 + display:flex;align-items:center;justify-content:center;font-weight:800;font-size:18px}
32 + .step h3{margin:6px 0 6px;font-size:19px}
33 + .step p{margin:0 0 12px;color:#3a3a40}
34 + .shot{border:1px solid var(--line);border-radius:12px;overflow:hidden;box-shadow:0 8px 30px rgba(16,16,20,.08)}
35 + .shot img{display:block;width:100%;height:auto}
36 + .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px;margin:16px 0}
37 + .card{border:1px solid var(--line);border-radius:12px;padding:16px;background:#fff}
38 + .card b{display:block;margin-bottom:6px}
39 + table{border-collapse:collapse;width:100%;font-size:15px}
40 + th,td{border:1px solid var(--line);padding:8px 10px;text-align:left;vertical-align:top}
41 + th{background:var(--ink);color:var(--paper)}
42 + .faq dt{font-weight:700;margin:18px 0 4px}
43 + .faq dd{margin:0;color:#3a3a40}
44 + footer.doc{margin-top:56px;background:var(--ink);color:var(--paper);padding:28px 0;font-size:14px}
45 + footer.doc a{color:var(--accent);text-decoration:none}
46 + @media print{
47 + header.doc .btn-pdf{display:none}
48 + .shot{box-shadow:none;break-inside:avoid}
49 + .step{break-inside:avoid}
50 + a{color:inherit;text-decoration:none}
51 + }
52 + @media(max-width:640px){ .step{grid-template-columns:40px 1fr} .step .num{width:34px;height:34px;font-size:15px} }
53 +</style>
54 +</head>
55 +<body>
56 +<header class="doc">
57 + <div class="container">
58 + <a class="wordmark" href="/">Fabri<span class="ka">·Ka</span></a>
59 + <nav style="display:flex;gap:14px;align-items:center">
60 + <a href="/">← Retour au site</a>
61 + <a class="btn-pdf" href="./fabri-ka-documentation.pdf" download>Télécharger le PDF</a>
62 + </nav>
63 + </div>
64 +</header>
65 +
66 +<div class="container">
67 + <div class="hero">
68 + <p class="kicker">Documentation · mise à jour 2026-08-24</p>
69 + <h1>Comment fonctionne <mark>Fabri·Ka</mark></h1>
70 + <p class="lead">Le répertoire des produits québécois : plus de 300 000 produits de 1 377 boutiques d'ici, trouvables au même endroit.</p>
71 + </div>
72 +
73 + <section>
74 + <p class="kicker">Vue d'ensemble</p>
75 + <h2>À quoi sert le site</h2>
76 + <p><strong>Fabri-Ka est un agrégateur de découverte de produits québécois.</strong> Acheter
77 + local demande normalement de connaître des centaines de boutiques dispersées — érablières,
78 + microbrasseries, savonneries, ébénistes, torréfacteurs, fermes… Fabri-Ka les recense, aspire
79 + leurs catalogues publics et les rend trouvables par catégorie, région, origine et prix.
80 + <strong>Aucune vente ne se fait sur Fabri-Ka</strong> : chaque produit renvoie vers la boutique
81 + d'origine, à qui appartiennent prix, photos et stocks.</p>
82 + <div class="cards">
83 + <div class="card"><b>301 534 produits</b>Provenant de 1 377 boutiques en ligne du Québec, indexés en recherche plein-texte.</div>
84 + <div class="card"><b>3 507 boutiques vérifiées</b>Au registre, classées par origine de fabrication (A–E) avec évidence conservée.</div>
85 + <div class="card"><b>17 régions administratives</b>Couverture complète de la province, avec pages par région et par catégorie.</div>
86 + <div class="card"><b>Resynchronisation aux 6 h</b>Les catalogues sont ré-aspirés en continu : nouveautés, prix et retraits suivis automatiquement.</div>
87 + </div>
88 + </section>
89 +
90 + <section>
91 + <p class="kicker">Guide pas à pas</p>
92 + <h2>Utiliser le site en 4 étapes</h2>
93 +
94 + <div class="step">
95 + <div class="num">1</div>
96 + <div>
97 + <h3>Arriver sur l'accueil</h3>
98 + <p>La page d'accueil présente le répertoire : recherche au premier plan, catégories vedettes
99 + (mode, bijoux, épicerie fine, érable…) et sélection de produits d'ici. La navigation donne
100 + accès aux produits, aux boutiques, aux statistiques et au formulaire « Inscrire mon
101 + atelier » pour les marchands.</p>
102 + <div class="shot"><img src="./img/etape1.png" alt="Étape 1 — page d'accueil de Fabri-Ka"></div>
103 + </div>
104 + </div>
105 +
106 + <div class="step">
107 + <div class="num">2</div>
108 + <div>
109 + <h3>Chercher un produit et filtrer</h3>
110 + <p>La recherche plein-texte est insensible aux accents (« erable » trouve « érable »).
111 + À gauche, les filtres croisent catégorie (20 catégories avec compteurs), région, origine
112 + de fabrication (A–E) et prix ; on peut se limiter aux fabricants seulement. Chaque carte
113 + affiche la pastille d'origine, le prix et la boutique source.</p>
114 + <div class="shot"><img src="./img/etape2.png" alt="Étape 2 — recherche « érable » : 6 716 produits, filtres catégorie/région/origine"></div>
115 + </div>
116 + </div>
117 +
118 + <div class="step">
119 + <div class="num">3</div>
120 + <div>
121 + <h3>Ouvrir la fiche produit et aller chez le marchand</h3>
122 + <p>La fiche montre la galerie, le prix, la description, la marque, la catégorie et le badge
123 + d'origine (ex. « A — Fabriqué au Québec »), plus la boutique avec sa région. Le bouton
124 + <strong>« Voir chez [la boutique] »</strong> mène directement à la page du produit chez le
125 + marchand — c'est là que l'achat se conclut. En bas, des produits similaires prolongent la
126 + découverte.</p>
127 + <div class="shot"><img src="./img/etape3.png" alt="Étape 3 — fiche produit : tarte au sirop d'érable, bouton vers la boutique d'origine"></div>
128 + </div>
129 + </div>
130 +
131 + <div class="step">
132 + <div class="num">4</div>
133 + <div>
134 + <h3>Explorer le répertoire de boutiques</h3>
135 + <p>L'onglet Boutiques liste les 1 377 boutiques avec produits (et permet d'élargir à tout
136 + le registre) : logo, région, plateforme ecommerce, classe d'origine et nombre de produits.
137 + Chaque fiche boutique détaille stats de prix, politique de livraison, catégories et
138 + boutiques similaires. On filtre par région ou par nom.</p>
139 + <div class="shot"><img src="./img/etape4.png" alt="Étape 4 — répertoire des boutiques québécoises"></div>
140 + </div>
141 + </div>
142 + </section>
143 +
144 + <section>
145 + <p class="kicker">Sous le capot</p>
146 + <h2>D'où viennent les données</h2>
147 + <p>Tout commence par un <strong>pipeline de découverte</strong> (35+ sources : certifications
148 + <em>Aliments du Québec</em> et <em>Les Produits du Québec</em>, associations, annuaires,
149 + marques régionales) qui recense les boutiques et les classe par <strong>origine de fabrication
150 + (A–E)</strong>, chaque classement étant justifié par une évidence conservée. Le registre compte
151 + 3 507 boutiques québécoises vérifiées.</p>
152 + <p>Les catalogues sont ensuite aspirés par des <strong>connecteurs par plateforme ecommerce</strong>
153 + — et non par site : le même code Shopify sert des centaines de boutiques, et 9 connecteurs
154 + couvrent Shopify, WooCommerce, Wix, Squarespace, Square Online, Votresite.ca et les sites
155 + génériques (sitemap → JSON-LD), avec Scrapfly/Firecrawl en secours anti-bot. Un processus
156 + autonome (<code>fabri-ka-sync</code>) resynchronise le tout <strong>aux 6 heures</strong> :
157 + chaque produit est mis à jour par hash de contenu, et un produit disparu du catalogue source
158 + est retiré après un délai de grâce de deux synchronisations.</p>
159 + <p>Le résultat alimente un <strong>moteur de recherche plein-texte FTS5</strong> (insensible aux
160 + accents) et plus de 301 000 pages indexables, rendues côté serveur pour le référencement.</p>
161 + </section>
162 +
163 + <section>
164 + <p class="kicker">Questions fréquentes</p>
165 + <h2>FAQ</h2>
166 + <dl class="faq">
167 + <dt>Peut-on acheter directement sur Fabri-Ka ?</dt>
168 + <dd>Non. Fabri-Ka est un répertoire de découverte : chaque fiche renvoie vers la boutique
169 + d'origine, où se fait l'achat. Prix, photos et stocks appartiennent aux marchands.</dd>
170 + <dt>Les prix sont-ils à jour ?</dt>
171 + <dd>Les catalogues sont resynchronisés aux 6 heures. Le prix affiché est celui relevé à la
172 + dernière synchronisation ; le prix officiel reste celui de la boutique.</dd>
173 + <dt>Que signifient les pastilles A, B, C… ?</dt>
174 + <dd>La classe d'origine de la boutique : A — fabriqué au Québec, B — conçu au Québec,
175 + C — détaillant québécois, jusqu'à E. Chaque classement s'appuie sur une évidence conservée
176 + (certification, association, mention du site).</dd>
177 + <dt>Je suis un artisan ou une boutique : comment être ajouté ?</dt>
178 + <dd>Via le formulaire <a href="/inscrire">« Inscrire mon atelier »</a> ; la boutique est
179 + ensuite vérifiée puis connectée au pipeline.</dd>
180 + <dt>Faut-il un compte ?</dt>
181 + <dd>Non pour chercher. Un compte KA ID (gratuit, commun aux 13 plateformes du Groupe KA)
182 + permet de garder des favoris partagés dans « Mon univers Ka ».</dd>
183 + </dl>
184 + </section>
185 +</div>
186 +
187 +<footer class="doc">
188 + <div class="container">
189 + <p><b>Fabri·Ka</b> — un service <a href="https://www.groupe-ka.com">Groupe KA</a>.
190 + Écosystème : les 13 plateformes sont liées au pied de chaque site.</p>
191 + <p>© 2026 Groupe KA — Simon-Pierre Boucher · <a href="mailto:contact@spboucher.ai">contact@spboucher.ai</a></p>
192 + </div>
193 +</footer>
194 +</body>
195 +</html>
modified frontend/src/App.tsx +1 −1
@@ -218,7 +218,7 @@ export default function App() {
218 218 </Routes>
219 219 </main>
220 220 {/* Pied de page commun Groupe KA (ka-ui) */}
221 − <KaFooter siteId="fabri-ka" />
221 + <KaFooter siteId="fabri-ka" localLegal={[{ label: 'Documentation', href: '/doc/' }]} />
222 222 <BottomNav />
223 223 </div>
224 224 </FavoritesProvider>
225 225