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
5 h agolast push
Python 38.4% HTML 30.3% TypeScript 17.2% CSS 11% JavaScript 3.2%

Thème famille KA « éditorial sharp » (aligné sur Food-Ka / Lou-Ka)

- Typo : Space Grotesk (display) + Inter (texte) + JetBrains Mono (prix,
  micro-étiquettes) — remplace Fraunces/Outfit
- Signature famille : bordures encre, ombres décalées (boutons, cartes,
  recherche), chip « ·Ka » rotée dans le logo, grain de fond, kickers mono
- Palette Fabri-Ka conservée (papier crème, terracotta, pin) + miel #F2CF63
  en surlignage ; footer pin profond ; nav pilule à état actif pin/miel
- Couche d'override en fin de styles.css (jetons partagés --line,
  --shadow-off, --highlight — mêmes rôles que Food-Ka/Lou-Ka)
- Captures d'écran README refaites avec le nouveau thème

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed 1 mo ago (Aug 16, 2026) parent 11a5c03

13 changed files +260 −13

modified README.md +1 −1
@@ -97,7 +97,7 @@ flowchart LR
97 97 | **API** | Recherche FTS5, facettes, filtres catégorie/région/origine/prix, stats, rapport PDF, sync | `fabrika/web.py` |
98 98 | **SEO / SSR** | HTML complet dès la 1ʳᵉ requête sur toutes les routes, pages programmatiques, JSON-LD, sitemaps, 301/404/410 | `fabrika/seo.py` |
99 99 | **Comptes** | « Se connecter avec KA ID » (SSO du Groupe KA), favoris « Mon univers Ka » poussés au hub central | `fabrika/auth.py`, `fabrika/hubfav.py`, `fabrika/hubprofile.py` |
100 −| **Frontend** | « Chaleur artisanale, précision éditoriale » — Fraunces + Outfit, crème/terracotta/pin, PWA-lite, fr-CA | `frontend/` |
100 +| **Frontend** | Identité famille KA « éditorial sharp » (cf. Food-Ka/Lou-Ka) — Space Grotesk + Inter + JetBrains Mono, bordures encre, ombres décalées, palette crème/terracotta/pin/miel, PWA-lite, fr-CA | `frontend/` |
101 101
102 102 ## SEO & rendu serveur — 292 000+ pages indexables
103 103
modified docs/screenshots/accueil.png +0 −0

Binary file not shown.

modified docs/screenshots/boutique.png +0 −0

Binary file not shown.

modified docs/screenshots/boutiques.png +0 −0

Binary file not shown.

modified docs/screenshots/catalogue.png +0 −0

Binary file not shown.

modified docs/screenshots/categorie.png +0 −0

Binary file not shown.

modified docs/screenshots/mobile-produit.png +0 −0

Binary file not shown.

modified docs/screenshots/mobile.png +0 −0

Binary file not shown.

modified docs/screenshots/produit.png +0 −0

Binary file not shown.

modified docs/screenshots/stats.png +0 −0

Binary file not shown.

modified frontend/index.html +1 −1
@@ -16,7 +16,7 @@
16 16 <link rel="preconnect" href="https://fonts.googleapis.com" />
17 17 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
18 18 <link
19 − href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,700;9..144,900&family=Outfit:wght@400;500;600;700&display=swap"
19 + href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
20 20 rel="stylesheet"
21 21 />
22 22 <title>Fabri-Ka — Tous les produits québécois. Un seul endroit.</title>
modified frontend/src/App.tsx +2 −2
@@ -145,7 +145,7 @@ function Header() {
145 145 <header className="site-header">
146 146 <div className="site-header-inner">
147 147 <Link to="/" className="logo" aria-label="Fabri-Ka — Accueil">
148 − Fabri<span className="logo-dot">·</span>Ka
148 + Fabri<span className="logo-ka">·Ka</span>
149 149 </Link>
150 150 <nav className="site-nav" aria-label="Navigation principale">
151 151 <NavLink to="/produits">Produits</NavLink>
@@ -180,7 +180,7 @@ function Footer() {
180 180 <div className="site-footer-inner">
181 181 <div className="footer-brand">
182 182 <span className="logo logo-footer">
183 − Fabri<span className="logo-dot">·</span>Ka
183 + Fabri<span className="logo-ka">·Ka</span>
184 184 </span>
185 185 <p>Tous les produits québécois. Un seul endroit.</p>
186 186 </div>
modified frontend/src/styles.css +256 −9
@@ -1,10 +1,13 @@
1 1 /* ==========================================================================
2 − Fabri-Ka — chaleur artisanale, précision éditoriale
3 − Mobile-first · palette crème/encre/terracotta/pin
2 + Fabri-Ka — identité famille KA « éditorial sharp » (cf. Food-Ka / Lou-Ka)
3 + · Typo display Space Grotesk / texte Inter / micro-étiquettes JetBrains Mono
4 + · Signature : bordures encre + ombres décalées (néo-brutalisme raffiné)
5 + · Palette Fabri-Ka conservée : papier crème, encre chaude, terracotta
6 + #C4532E en accent, pin #234438 en profond, miel #F2CF63 en surlignage
4 7 ========================================================================== */
5 8
6 9 :root {
7 − --bg: #FAF6F0;
10 + --bg: #FAF6EE;
8 11 --ink: #1E1B16;
9 12 --accent: #C4532E;
10 13 --accent-dark: #A94525;
@@ -14,18 +17,27 @@
14 17 --white: #FFFFFF;
15 18 --muted: #6E6455;
16 19
20 + /* jetons famille KA (mêmes rôles que Food-Ka/Lou-Ka) */
21 + --line: rgba(30, 27, 22, 0.14);
22 + --line-strong: rgba(30, 27, 22, 0.85);
23 + --highlight: #F2CF63;
24 + --highlight-soft: #F9F0D2;
25 +
17 26 --origin-a: #234438;
18 27 --origin-b: #C4532E;
19 28 --origin-c: #8A6D3B;
20 29 --origin-d: #5B5B8A;
21 30 --origin-e: #999999;
22 31
23 − --font-display: 'Fraunces', Georgia, serif;
24 − --font-body: 'Outfit', system-ui, -apple-system, sans-serif;
32 + --font-display: 'Space Grotesk', system-ui, sans-serif;
33 + --font-body: 'Inter', system-ui, -apple-system, sans-serif;
34 + --font-mono: 'JetBrains Mono', ui-monospace, monospace;
25 35
26 − --radius: 8px;
27 − --radius-lg: 12px;
36 + --radius: 6px;
37 + --radius-lg: 10px;
28 38 --shadow-hover: 0 6px 18px rgba(30, 27, 22, 0.08);
39 + --shadow-off: 6px 6px 0 var(--ink);
40 + --shadow-off-soft: 8px 8px 0 rgba(30, 27, 22, 0.08);
29 41 --shadow-sheet: 0 -12px 40px rgba(30, 27, 22, 0.18);
30 42 --maxw: 1280px;
31 43
@@ -4112,12 +4124,12 @@ a.card:active {
4112 4124 line-height: 1.6;
4113 4125 }
4114 4126 .seo-page h1 {
4115 − font-family: 'Fraunces', serif;
4127 + font-family: var(--font-display);
4116 4128 font-size: 1.9rem;
4117 4129 margin: 0.4em 0;
4118 4130 }
4119 4131 .seo-page h2 {
4120 − font-family: 'Fraunces', serif;
4132 + font-family: var(--font-display);
4121 4133 font-size: 1.25rem;
4122 4134 margin: 1.6em 0 0.5em;
4123 4135 }
@@ -4193,3 +4205,238 @@ a.card:active {
4193 4205 margin: 18px 0;
4194 4206 align-items: center;
4195 4207 }
4208 +
4209 +/* ==========================================================================
4210 + Couche « famille KA » — même thème et display que Food-Ka / Lou-Ka
4211 + (éditorial sharp : bordures encre, ombres décalées, chip ·Ka, micro-mono).
4212 + Placée en fin de fichier : elle prime sur les règles historiques.
4213 + ========================================================================== */
4214 +
4215 +/* grain subtil — texture signature de la famille */
4216 +body::before {
4217 + content: "";
4218 + position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: 0.35;
4219 + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.02 0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
4220 +}
4221 +#root { position: relative; z-index: 1; }
4222 +
4223 +/* Space Grotesk plafonne à 700 (Fraunces montait à 900) */
4224 +h1, h2, h3, h4 {
4225 + font-weight: 700;
4226 + letter-spacing: -0.03em;
4227 + line-height: 1.08;
4228 +}
4229 +::selection { background: var(--highlight); color: var(--ink); }
4230 +
4231 +/* ---- header : trait d'encre + chip ·Ka rotée --------------------------- */
4232 +.site-header {
4233 + background: rgba(250, 246, 238, 0.88);
4234 + border-bottom: 2px solid var(--ink);
4235 +}
4236 +.logo {
4237 + font-weight: 700;
4238 + letter-spacing: -0.04em;
4239 + display: inline-flex;
4240 + align-items: center;
4241 +}
4242 +.logo-ka {
4243 + background: var(--pine);
4244 + color: var(--highlight);
4245 + padding: 2px 7px 4px;
4246 + border-radius: 6px;
4247 + margin-left: 3px;
4248 + transform: rotate(-2deg);
4249 + transition: transform 0.2s ease;
4250 + display: inline-block;
4251 +}
4252 +.logo:hover .logo-ka,
4253 +.logo:focus-visible .logo-ka { transform: rotate(0deg); }
4254 +
4255 +.site-nav a {
4256 + border: 1.5px solid transparent;
4257 + font-weight: 600;
4258 + border-radius: 999px;
4259 + transition: all 0.15s ease;
4260 +}
4261 +@media (hover: hover) {
4262 + .site-nav a:hover {
4263 + border-color: var(--ink);
4264 + color: var(--ink);
4265 + background: transparent;
4266 + }
4267 +}
4268 +.site-nav a.active,
4269 +.site-nav a[aria-current='page'] {
4270 + background: var(--pine);
4271 + color: var(--highlight);
4272 +}
4273 +
4274 +/* ---- recherche : champs encrés ----------------------------------------- */
4275 +.searchbar-field,
4276 +.catalog-searchbar-field {
4277 + border: 1.5px solid var(--ink);
4278 + border-radius: var(--radius);
4279 + background: var(--white);
4280 +}
4281 +.searchbar button[type='submit'] {
4282 + border: 1.5px solid var(--ink);
4283 + border-radius: var(--radius);
4284 + box-shadow: 3px 3px 0 var(--ink);
4285 + transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.15s ease;
4286 +}
4287 +.searchbar button[type='submit']:active {
4288 + transform: translate(2px, 2px);
4289 + box-shadow: 1px 1px 0 var(--ink);
4290 +}
4291 +.searchbar-kbd {
4292 + font-family: var(--font-mono);
4293 + border: 1px solid var(--line);
4294 + border-radius: 4px;
4295 +}
4296 +
4297 +/* ---- kicker / entêtes de section : micro-mono -------------------------- */
4298 +.hero-eyebrow,
4299 +.filter-label,
4300 +.footer-col-title {
4301 + font-family: var(--font-mono);
4302 + font-size: 11.5px;
4303 + font-weight: 500;
4304 + text-transform: uppercase;
4305 + letter-spacing: 0.14em;
4306 + color: var(--accent);
4307 +}
4308 +.hero-eyebrow::before { background: var(--accent); }
4309 +.section-header h2::before {
4310 + border-radius: 0;
4311 + background: var(--accent);
4312 +}
4313 +
4314 +/* ---- cartes : bordure encre + ombre décalée au survol ------------------- */
4315 +.card {
4316 + border: 1.5px solid var(--line);
4317 + border-radius: var(--radius-lg);
4318 + transition: border-color 0.15s ease, box-shadow 0.15s ease,
4319 + transform 0.15s ease;
4320 +}
4321 +@media (hover: hover) {
4322 + a.card:hover {
4323 + border-color: var(--ink);
4324 + box-shadow: var(--shadow-off-soft);
4325 + transform: translate(-2px, -2px);
4326 + }
4327 +}
4328 +a.card:active { border-color: var(--ink); }
4329 +
4330 +/* ---- chips catégories --------------------------------------------------- */
4331 +.chip {
4332 + border: 1.5px solid var(--line);
4333 + font-weight: 600;
4334 +}
4335 +@media (hover: hover) {
4336 + .chip:hover {
4337 + border-color: var(--ink);
4338 + background: var(--white);
4339 + box-shadow: 3px 3px 0 rgba(30, 27, 22, 0.12);
4340 + transform: translate(-1px, -1px);
4341 + }
4342 +}
4343 +.chip:active { border-color: var(--ink); background: var(--highlight-soft); }
4344 +.chip-count {
4345 + font-family: var(--font-mono);
4346 + font-size: 11px;
4347 + background: var(--sand);
4348 + border-radius: 999px;
4349 + padding: 2px 8px;
4350 +}
4351 +
4352 +/* ---- prix & étiquettes : mono ------------------------------------------- */
4353 +.price-chip {
4354 + font-family: var(--font-mono);
4355 + font-weight: 600;
4356 + letter-spacing: -0.02em;
4357 +}
4358 +.price-chip-muted { font-family: var(--font-mono); font-weight: 500; }
4359 +.tag,
4360 +.origin-badge,
4361 +.unavailable-badge,
4362 +.stats-newest-chip {
4363 + font-family: var(--font-mono);
4364 + text-transform: uppercase;
4365 + letter-spacing: 0.06em;
4366 + font-size: 10.5px;
4367 +}
4368 +
4369 +/* ---- boutons : encre + ombre décalée ------------------------------------ */
4370 +.btn {
4371 + border-radius: var(--radius);
4372 + font-weight: 600;
4373 +}
4374 +.btn-primary {
4375 + border: 1.5px solid var(--ink);
4376 + box-shadow: 3px 3px 0 var(--ink);
4377 + transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.15s ease;
4378 +}
4379 +@media (hover: hover) {
4380 + .btn-primary:hover {
4381 + background: var(--accent-dark);
4382 + transform: translate(-1px, -1px);
4383 + box-shadow: 4px 4px 0 var(--ink);
4384 + }
4385 +}
4386 +.btn-primary:active {
4387 + transform: translate(2px, 2px);
4388 + box-shadow: 1px 1px 0 var(--ink);
4389 +}
4390 +.btn-secondary {
4391 + border: 1.5px solid var(--ink);
4392 + background: var(--white);
4393 +}
4394 +@media (hover: hover) {
4395 + .btn-secondary:hover {
4396 + box-shadow: 3px 3px 0 rgba(30, 27, 22, 0.15);
4397 + transform: translate(-1px, -1px);
4398 + }
4399 +}
4400 +
4401 +/* ---- filtre flottant mobile --------------------------------------------- */
4402 +.filter-fab {
4403 + border: 1.5px solid var(--ink);
4404 + box-shadow: 3px 3px 0 var(--ink);
4405 + font-weight: 600;
4406 +}
4407 +.filter-fab:active {
4408 + transform: translate(2px, 2px);
4409 + box-shadow: 1px 1px 0 var(--ink);
4410 +}
4411 +
4412 +/* ---- barre d'onglets mobile ---------------------------------------------- */
4413 +.bottom-nav {
4414 + background: rgba(250, 246, 238, 0.96);
4415 + border-top: 2px solid var(--ink);
4416 +}
4417 +
4418 +/* ---- footer : bloc pin profond ------------------------------------------- */
4419 +.site-footer {
4420 + background: var(--pine);
4421 + border-top: 2px solid var(--ink);
4422 + color: rgba(250, 246, 238, 0.92);
4423 +}
4424 +.site-footer .logo,
4425 +.site-footer a,
4426 +.footer-brand p,
4427 +.footer-legal {
4428 + color: rgba(250, 246, 238, 0.92);
4429 +}
4430 +.site-footer .footer-col-title { color: var(--highlight); }
4431 +.site-footer a:hover { color: var(--highlight); }
4432 +.site-footer .logo-ka {
4433 + background: var(--highlight);
4434 + color: var(--pine);
4435 +}
4436 +
4437 +/* ---- contenu SSR (seo.py) aligné sur le thème ---------------------------- */
4438 +.seo-page h1, .seo-page h2 { font-family: var(--font-display); }
4439 +.seo-stats b { color: var(--accent); font-family: var(--font-mono); }
4440 +.seo-card a { font-weight: 600; }
4441 +.seo-card-price { font-family: var(--font-mono); color: var(--accent); }
4442 +.seo-card-media img { border: 1.5px solid var(--line); }
4196 4443