Covers Tailwind CSS setup, dark mode via next-themes, flag image language switcher, SEO metadata + JSON-LD, and full layout for home and status pages. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.0 KiB
7.0 KiB
Ombrora -- Refonte UI minimaliste
Date : 2026-08-10 Statut : Approuve
Contexte
L'application est fonctionnelle mais entierement non stylee (inline styles uniquement). Objectifs : interface minimaliste, SEO-optimisee, light/dark mode, language switcher avec drapeaux images.
Stack technique ajoutee
| Package | Role | Compatibilite o2switch |
|---|---|---|
tailwindcss + @tailwindcss/postcss |
Styles utility-first, compile en CSS statique | OK (build-time) |
next-themes |
Dark/light mode via class sur <html> |
OK (pure JS) |
Flag SVGs locaux dans /public/flags/ |
Drapeaux langue | OK (assets statiques) |
Aucun package avec bindings natifs.
Fichiers touches
Nouveaux
tailwind.config.tssrc/app/globals.csssrc/components/Header.tsxsrc/components/ThemeToggle.tsxsrc/components/ReassuranceSection.tsxpublic/flags/en.svgpublic/flags/fr.svgpublic/flags/es.svgpublic/flags/it.svg
Modifies
src/app/[locale]/layout.tsx-- ThemeProvider, Inter font, JSON-LD, metadata completesrc/app/[locale]/page.tsx-- hero + form + reassurancesrc/app/[locale]/status/[uuid]/page.tsx-- layout status restyleesrc/components/SubmitForm.tsx-- Tailwind, UI refaitesrc/components/StatusView.tsx-- Tailwind, UI refaitesrc/components/LanguageSwitcher.tsx--<img>drapeaux SVGmessages/en.json,fr.json,es.json,it.json-- cles SEO + reassurance
Design
Palette
Light : bg-white / text-gray-900 / accent violet-600
Dark : bg-slate-950 / text-gray-50 / accent violet-400
Input : border-gray-200 / dark:border-slate-700
Card : bg-gray-50 / dark:bg-slate-900
Tailwind strategy : darkMode: 'class' dans tailwind.config.ts.
Typographie
next/font/google avec Inter (subsets latin, latin-ext). Latin-ext couvre les accents FR/ES/IT. Preload automatique par Next.js, zero CDN runtime.
Layout -- Page home
<header> Logo | ThemeToggle | LanguageSwitcher </header>
<main>
<section> <!-- hero -->
<h1>Telechargez vos videos gratuitement</h1>
<p>Sous-titre</p>
<!-- glow violet radial derriere l'input -->
<SubmitForm /> <!-- URL + bouton inline, options compactes dessous -->
</section>
<section> <!-- reassurance -->
<ReassuranceSection /> <!-- 4 cards -->
</section>
</main>
<footer> Copyright Ombrora </footer>
Layout -- Page status
<header> (identique) </header>
<main>
<section>
<h1>Statut du telechargement</h1>
<StatusView /> <!-- card centree -->
</section>
</main>
Composant SubmitForm
- Input URL : pleine largeur,
rounded-xl, bouton violet inline a droite (rounded-r-xl) - Glow :
divabsolue violetblur-3xl opacity-15positionnee derriere l'input, visible en both modes - Options : ligne flex sous l'input -- Format (select), Qualite (select), Sous-titres (checkbox styled), Options avancees (collapse/details)
- Bouton submit :
bg-violet-600 hover:bg-violet-700 dark:bg-violet-500+ spinner animate-spin quand loading - Erreur : texte rouge sous les options
Composant StatusView
- Card
max-w-md mx-auto rounded-2xl border bg-gray-50 dark:bg-slate-900 p-6 - PENDING/PROCESSING : spinner
animate-spinviolet + texte statut - DONE : bouton telechargement violet, nom fichier, taille, expiration en
text-sm text-gray-500 - FAILED : bloc
bg-red-50 dark:bg-red-950 border-red-200avec<pre>pour le message d'erreur - FILE_DELETED : message informatif gris
Composant Header
<header class="sticky top-0 z-50 border-b bg-white/80 dark:bg-slate-950/80 backdrop-blur">- Logo : "Ombrora" texte, "O" en
text-violet-600 - Droite : ThemeToggle + LanguageSwitcher
- Padding
px-6 py-3, flex justify-between
Composant ThemeToggle
- Bouton icon-only, SVG lune (dark) ou soleil (light) inline
- Pas de librairie d'icones -- SVG paths hardcodes (moon :
M 12 3 a 6 6 0 0 0 9 9 ..., sun : rayons simples) aria-label="Basculer le theme"
Composant LanguageSwitcher
- Flex row, gap-2
- Chaque locale :
<button>avec<img src="/flags/{loc}.svg" alt="{nom_langue}" width="28" height="20" /> - Actif :
opacity-100 ring-2 ring-violet-500 rounded-sm - Inactif :
opacity-40 hover:opacity-70 - SVG sources : telecharger depuis
https://flagcdn.com/w40/{code}.pngequivalents SVG ou utiliserflag-iconsopen-source (MIT)
Composant ReassuranceSection
4 cards en grille grid grid-cols-2 md:grid-cols-4 gap-4 :
| Icone SVG | Titre | Sous-titre |
|---|---|---|
| Cadeau | Gratuit | Sans compte, sans inscription |
| Eclair | Rapide | Pret en quelques secondes |
| Verrou | Prive | Aucune donnee conservee |
| Film | Multi-format | mp4, mp3, webm, mkv -- jusqu'en 1080p |
Chaque card : rounded-xl border p-4 bg-gray-50 dark:bg-slate-900 text-center.
SEO
Metadata (par locale, dans generateMetadata du layout)
{
title: t('meta.title'), // "Ombrora -- Telechargeur de videos gratuit"
description: t('meta.description'), // ~155 chars, locale-specific
robots: { index: true, follow: true },
openGraph: {
title, description,
url: `${process.env.NEXT_PUBLIC_BASE_URL}/${locale}`,
siteName: 'Ombrora',
locale,
},
alternates: {
canonical: `${process.env.NEXT_PUBLIC_BASE_URL}/${locale}`,
languages: { en: '/en', fr: '/fr', es: '/es', it: '/it' },
},
}
HTML semantique
<html lang={locale}>: deja en place<header>,<main>,<section aria-labelledby="hero-heading">,<footer><h1>unique par page (traduit)<h2>pour titres reassurance<h1>sur status page : "Statut du telechargement"
JSON-LD (WebApplication)
Injecte dans <head> via <script type="application/ld+json"> dans le layout :
{
"@context": "https://schema.org",
"@type": "WebApplication",
"name": "Ombrora",
"url": "${process.env.NEXT_PUBLIC_BASE_URL}",
"description": "Telechargeur de videos gratuit, rapide et prive.",
"applicationCategory": "MultimediaApplication",
"operatingSystem": "Web",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "EUR"
}
}
Traductions -- nouvelles cles
A ajouter dans chaque messages/*.json :
"meta": {
"title": "Ombrora -- Telechargeur de videos gratuit",
"description": "Telechargez vos videos YouTube, Vimeo et plus en mp4, mp3, webm -- gratuit, rapide, sans compte."
},
"reassurance": {
"free": "Gratuit",
"freeDesc": "Sans compte, sans inscription",
"fast": "Rapide",
"fastDesc": "Pret en quelques secondes",
"private": "Prive",
"privateDesc": "Aucune donnee conservee",
"formats": "Multi-format",
"formatsDesc": "mp4, mp3, webm, mkv -- jusqu'en 1080p"
},
"footer": {
"copyright": "© 2026 Ombrora"
}
Contraintes
- Pas de CSS framework avec runtime JS (Tailwind compile en statique)
- Pas de librairie d'icones externe -- SVG inline pour ThemeToggle, SVG fichiers pour drapeaux
- Flag SVGs stockes dans
/public/flags/(pas de CDN runtime) next/font/googlepour Inter (preload auto, pas de FOUT)next-themes: ajoutersuppressHydrationWarningsur<html>pour eviter hydration mismatch