150 lines
6.1 KiB
Markdown
150 lines
6.1 KiB
Markdown
|
|
# Branding & assets pipeline — apps/web
|
|||
|
|
|
|||
|
|
Single source of truth for how Talas / Veza brand assets enter the codebase.
|
|||
|
|
Reference brand spec : [`CHARTE_GRAPHIQUE_TALAS.md`](../../../../Documents/TG__Talas_Group/05_EXPERIENCE_UTILISATEUR/CHARTE_GRAPHIQUE_TALAS.md).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Architecture
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
apps/web/
|
|||
|
|
├── public/
|
|||
|
|
│ ├── favicon.svg # SVG favicon (Mizu cyan placeholder)
|
|||
|
|
│ ├── icons/ # PWA icons (PNG, 72x72 to 512x512)
|
|||
|
|
│ ├── fonts/ # Self-hosted woff2 (Space Grotesk, Inter, JetBrains Mono)
|
|||
|
|
│ └── manifest.json # PWA manifest (theme_color = #0098B5 SUMI accent)
|
|||
|
|
└── src/
|
|||
|
|
├── components/
|
|||
|
|
│ ├── branding/
|
|||
|
|
│ │ ├── Logo.tsx # SOLE entry point for Talas / Veza wordmark + symbol
|
|||
|
|
│ │ ├── Logo.stories.tsx
|
|||
|
|
│ │ ├── assets/
|
|||
|
|
│ │ │ ├── SymbolPlaceholder.tsx # Geometric placeholder, swap for hand-drawn
|
|||
|
|
│ │ │ ├── TalasWordmark.tsx # (P0.1 artist deliverable — 3 variants)
|
|||
|
|
│ │ │ └── VezaWordmark.tsx # (P1.1 artist deliverable — 1 variant)
|
|||
|
|
│ │ └── index.ts
|
|||
|
|
│ └── icons/
|
|||
|
|
│ ├── SumiIcon.tsx # Wrapper : prefers hand-drawn, falls back to Lucide
|
|||
|
|
│ └── sumi/ # Hand-drawn calligraphic icons (10 prioritaires)
|
|||
|
|
│ ├── Play.tsx
|
|||
|
|
│ ├── Pause.tsx (TODO)
|
|||
|
|
│ └── ...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Logo component
|
|||
|
|
|
|||
|
|
**Always use `<Logo />`** instead of inline `<h2>VEZA</h2>` style markup.
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
import { Logo } from '@/components/branding';
|
|||
|
|
|
|||
|
|
// Default (wordmark, md, theme-aware color)
|
|||
|
|
<Logo brand="veza" />
|
|||
|
|
|
|||
|
|
// Lockup with tagline
|
|||
|
|
<Logo brand="veza" variant="lockup" size="lg" tagline="STREAMING" />
|
|||
|
|
|
|||
|
|
// Symbol only (favicon-style usage)
|
|||
|
|
<Logo brand="talas" variant="symbol" size="sm" />
|
|||
|
|
|
|||
|
|
// Cyan accent
|
|||
|
|
<Logo brand="veza" variant="lockup" color="cyan" />
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
API : see [Logo.stories.tsx](../src/components/branding/Logo.stories.tsx) for all variants in Storybook.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Asset deliverables — current status
|
|||
|
|
|
|||
|
|
Per `BRIEF_ARTISTE_IDENTITE_VISUELLE.md` (artist Renaud, 15 avril 2026) and Sprint 3 :
|
|||
|
|
|
|||
|
|
| Asset | Priority | Status | Location |
|
|||
|
|
|-------|----------|--------|----------|
|
|||
|
|
| TALAS wordmark × 3 (propre, sauvage, vertical) | P0.1 | ⏳ awaiting artist | `branding/assets/TalasWordmark.tsx` (pending) |
|
|||
|
|
| Hero image post-apo | P0.2 | ⏳ awaiting artist | `public/hero/` (pending) |
|
|||
|
|
| VEZA wordmark × 1 (tag fluide) | P1.1 | ⏳ awaiting artist | `branding/assets/VezaWordmark.tsx` (pending) |
|
|||
|
|
| 3-5 textures de liaison | P1.2 | ⏳ awaiting artist | `public/textures/` (pending) |
|
|||
|
|
| 3 symboles iconiques (enso, onde, libre) | P1.3 | ⏳ awaiting artist | `branding/assets/Symbol.tsx` (pending) |
|
|||
|
|
| Talas symbole (calligraphique) | — | 🟡 placeholder | `branding/assets/SymbolPlaceholder.tsx` |
|
|||
|
|
| Favicon SVG | — | 🟡 placeholder | `public/favicon.svg` |
|
|||
|
|
| 10 Sumi icons (play/pause/search/...) | — | 🟡 1/10 stubbed | `components/icons/sumi/` |
|
|||
|
|
| washi.png texture | — | ✅ inline SVG (feTurbulence) | `src/index.css:456` (no external file) |
|
|||
|
|
| Fonts (Space Grotesk + Inter + JetBrains Mono) | — | ✅ self-hosted | `public/fonts/*.woff2` |
|
|||
|
|
| PWA icons (PNG, 9 sizes) | — | 🟡 generic placeholders | `public/icons/icon-*.png` |
|
|||
|
|
|
|||
|
|
### Naming convention
|
|||
|
|
|
|||
|
|
- Wordmarks : `{brand}_wordmark_{variant}.svg` then exported as React component
|
|||
|
|
- Example : `talas_wordmark_propre.svg` → `TalasWordmarkPropre.tsx`
|
|||
|
|
- Symbols : `{brand}_symbol_{type}.svg`
|
|||
|
|
- Hero / textures : `{kind}_{number}.png` (raw scans), processed to `webp` for prod
|
|||
|
|
- Always store source SVGs (vectorized) ; processed bitmaps in build
|
|||
|
|
|
|||
|
|
### Format requirements (per BRIEF_ARTISTE §5)
|
|||
|
|
|
|||
|
|
- **Scan minimum 600 DPI** (1200 if available). PNG/TIFF only — no JPG (bleeding edges on ink).
|
|||
|
|
- **One artwork per file**. Naming : `talas_wordmark_sauvage_01.png` etc.
|
|||
|
|
- **No retouching** before delivery — clean fond, niveaux, détourage handled in apps/web preprocessing.
|
|||
|
|
- **Paper white** (not cream) ; **encre de Chine** (not brown-tinted black) ; aquarelle limited to terreuse palette.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## How to integrate a delivered asset
|
|||
|
|
|
|||
|
|
### Wordmark (e.g. TALAS propre)
|
|||
|
|
|
|||
|
|
1. Receive `talas_wordmark_propre_01.png` (scan 600+ DPI).
|
|||
|
|
2. Clean fond + isolate ink in Inkscape : `File → Import → Select-by-color (white) → Delete → Trace bitmap`.
|
|||
|
|
3. Export SVG with `currentColor` fills + transparent background.
|
|||
|
|
4. Save as `apps/web/src/components/branding/assets/TalasWordmark.tsx` :
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
import type { SVGProps } from 'react';
|
|||
|
|
export default function TalasWordmark(props: SVGProps<SVGSVGElement>) {
|
|||
|
|
return (
|
|||
|
|
<svg viewBox="0 0 240 60" xmlns="http://www.w3.org/2000/svg" {...props}>
|
|||
|
|
{/* Pasted SVG paths here, fills set to currentColor */}
|
|||
|
|
</svg>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
5. Update `Logo.tsx` to use `<TalasWordmark />` for `brand='talas'` instead of the
|
|||
|
|
text fallback. (Detect via prop or via fallback chain.)
|
|||
|
|
6. Storybook will show it automatically.
|
|||
|
|
|
|||
|
|
### Sumi icon (e.g. Pause)
|
|||
|
|
|
|||
|
|
1. Receive `pause_01.png` from artist.
|
|||
|
|
2. Vectorize manually in Inkscape (no auto-trace — preserves irregularity).
|
|||
|
|
3. Save as `apps/web/src/components/icons/sumi/Pause.tsx`.
|
|||
|
|
4. Add export to `components/icons/sumi/index.ts`.
|
|||
|
|
5. At call site :
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
import { SumiIcon } from '@/components/icons/SumiIcon';
|
|||
|
|
import { PauseIcon } from '@/components/icons/sumi';
|
|||
|
|
import { Pause } from 'lucide-react';
|
|||
|
|
|
|||
|
|
<SumiIcon sumi={PauseIcon} fallback={Pause} size={24} />
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The `SumiIcon` wrapper handles the "use hand-drawn if available, else Lucide
|
|||
|
|
fallback" logic, so you can drop hand-drawn icons in progressively.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Brand color guard
|
|||
|
|
|
|||
|
|
ESLint rule (`eslint.config.js` `no-restricted-syntax` for hex literals) blocks
|
|||
|
|
new hardcoded colors. To fix a warning :
|
|||
|
|
|
|||
|
|
- CSS context (JSX style/className/template literal) : use `var(--sumi-*)`.
|
|||
|
|
- TS / canvas context : `import { ColorVizIndigo } from '@veza/design-system/tokens-generated';`.
|
|||
|
|
|
|||
|
|
Source of truth for all colors : `packages/design-system/tokens/primitive/color.json`.
|