Add design spec for Ombrora hub landing page

Astro static site, FR/EN path-based i18n, light/dark theming, hub
linking to CVE Watch and Convert services.
This commit is contained in:
2026-08-02 14:27:50 +02:00
commit 0496e1390b
2 changed files with 238 additions and 0 deletions
@@ -0,0 +1,131 @@
# Ombrora Hub Landing Page — Design
## Purpose
A landing page at `www.ombrora.com` acting as a hub linking to Ombrora's existing services:
- CVE Watch — a CVE-tracking blog, published in French (`cve-fr.ombrora.com`) and English (`cve-en.ombrora.com`) as two locale-specific deployments of the same underlying service.
- Convert (`convert.ombrora.com`) — a file conversion tool (documents, audio, images, video, archives).
More services will be added to the hub over time; the design must make that cheap.
## Requirements
- Built with Astro, static output only (no SSR/SSR adapter) — required for SEO and for hosting on static shared hosting.
- Multilingual: French and English, via path-based routing (`/en/`, `/fr/`), symmetric (no unprefixed default locale route).
- Deployed to o2switch shared hosting: plain HTML/CSS/JS output uploaded to the host, no server-side runtime, `.htaccess` available for Apache-level rules.
- SEO-optimized: prerendered HTML, meta tags, hreflang, sitemap, robots.txt.
- Supports light and dark mode.
- No existing brand assets — visual direction is proposed as part of this design.
- Scope is minimal: hero + service cards + footer. No About/Contact/legal pages, no analytics.
## Tech stack & project structure
- Astro (latest stable), `output: 'static'` (Astro's default — no adapter needed).
- No UI framework — plain Astro components and CSS are sufficient for this scope.
- npm as package manager.
```
src/
components/ Header.astro, Footer.astro, ServiceCard.astro, LanguageSwitcher.astro, ThemeToggle.astro
i18n/ en.ts, fr.ts (UI strings), services.ts (service list, per-locale copy)
layouts/ BaseLayout.astro (head/meta/hreflang/OG tags, theme init script)
pages/
en/index.astro
fr/index.astro
public/
.htaccess (root language redirect)
robots.txt
astro.config.mjs (i18n config, sitemap integration)
```
## Routing & i18n
`astro.config.mjs`:
```js
i18n: {
locales: ['en', 'fr'],
defaultLocale: 'en',
routing: { prefixDefaultLocale: true }
}
```
This produces symmetric `/en/` and `/fr/` routes (no bare unprefixed locale route). Astro's `astro:i18n` helpers (e.g. `getRelativeLocaleUrl`) generate cross-locale links for the language switcher and hreflang tags.
`public/.htaccess` handles the bare `www.ombrora.com/` root with a real server-side redirect based on the `Accept-Language` header:
```apache
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{HTTP:Accept-Language} fr [NC]
RewriteRule ^$ /fr/ [R=302,L]
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^$ /en/ [R=302,L]
```
French-preferring browsers land on `/fr/`; everything else defaults to `/en/`. No JavaScript redirect needed.
## Content model
`src/i18n/services.ts` is the single source of truth for the service cards. `url` may be a plain string (same URL regardless of locale) or a `{ en, fr }` object (locale-specific URL) — `ServiceCard.astro` resolves whichever shape is present against the current locale. Adding a future service, whether single-domain or per-locale-domain, means adding one entry here.
```ts
export const services = [
{
id: 'cve',
url: { en: 'https://cve-en.ombrora.com', fr: 'https://cve-fr.ombrora.com' },
name: { en: 'CVE Watch', fr: 'Veille CVE' },
description: { en: '...', fr: '...' },
},
{
id: 'convert',
url: 'https://convert.ombrora.com',
name: { en: 'Convert', fr: 'Convert' },
description: { en: '...', fr: '...' },
},
]
```
Note: CVE Watch is one logical service with two locale-specific deployments (matching the existing `cve-fr`/`cve-en` split), rendered as a single card whose link target depends on the hub's current locale — not two separate cards.
`src/i18n/en.ts` / `fr.ts` hold flat key-value UI strings (hero title/subtitle, nav labels, footer text), looked up directly in templates (e.g. `t.hero.title`) — no i18n library needed for this scope.
## Pages & components
- **BaseLayout.astro**: `<html lang>`, meta description, canonical URL, hreflang alternates (en, fr, x-default → en), Open Graph/Twitter card tags, favicon, global CSS, and the pre-paint theme-init script (see Theming).
- **Header.astro**: Ombrora wordmark, LanguageSwitcher (links to the equivalent page in the other locale, not just the other locale's root), ThemeToggle.
- **Hero**: short tagline introducing Ombrora as a hub for security and utility tools.
- **ServiceCard.astro × 2**: name, one-line description, a tag (e.g. "CVE Blog", "File Converter"), outbound link resolved per current locale.
- **Footer.astro**: copyright, optional contact mailto. No legal/About pages in this scope.
## Visual direction
Dark, technical aesthetic fitting a security/CVE tracker and dev utility tool: neutral dark/light backgrounds, one accent color (cool cyan or violet) for links and highlights, a clean sans-serif for body text with a monospace accent for tags/labels. No decorative gimmicks.
## Theming (light & dark mode)
Implemented via CSS custom properties (`--bg`, `--fg`, `--accent`, etc.) on `:root`, with `[data-theme="dark"]` / `[data-theme="light"]` overrides.
- **Default**: follows system preference (`prefers-color-scheme`), applied by an inline `<script>` in `BaseLayout` that runs before first paint (avoids flash of wrong theme) and sets `data-theme` on `<html>`.
- **Manual override**: a toggle button in the Header flips `data-theme` and persists the choice to `localStorage`; on later visits the stored preference takes precedence over system preference.
- No extra dependency — CSS variables plus a small vanilla script.
## SEO
- `@astrojs/sitemap` integration generating a sitemap covering both locale routes.
- Per-page `<title>`, meta description, canonical URL, and hreflang alternates in `BaseLayout`.
- `robots.txt` allowing all crawlers, referencing the sitemap.
- Semantic HTML (`<main>`, `<section>`, correct heading hierarchy), fully prerendered — no client-side rendering of critical content.
## Build & deploy
- `astro build` outputs static HTML/CSS/JS to `dist/`.
- Deployment to o2switch is a manual upload of `dist/` (including `.htaccess`, which Astro copies through from `public/` unchanged). No CI/CD pipeline in this scope.
## Out of scope
- About/Contact/legal pages.
- Analytics/tracking.
- Any service beyond CVE Watch and Convert (future services are added by extending `services.ts`, not by redesigning the page).
- CI/CD automation for deployment.