Skip to content

Implement hash routing, i18n, and responsive navigation components - #5

Merged
ffillouxdev merged 139 commits into
mainfrom
claude
Aug 14, 2026
Merged

Implement hash routing, i18n, and responsive navigation components#5
ffillouxdev merged 139 commits into
mainfrom
claude

Conversation

@ffillouxdev

Copy link
Copy Markdown
Owner

Prod

ffillouxdev and others added 30 commits April 13, 2026 18:24
Set up client-side hash routing with i18next for internationalization.
Routes: / (identification key), /catalogue, /privacy, /legal.
Browser language auto-detection with fallback to English.
Language selector in navbar persisted to localStorage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create responsive header with D-CAS logo and language dropdown
- Add bottom navbar with Home, Catalog, and More menu items
- Implement dropdown menu for Privacy and Legal links
- Update layout.ts to split nav into header() and navbar()
- Add icon emojis for navigation (🏠 home, 📚 catalog, ⋯ more)
- Update i18n translations for navbar items
- Add main content bottom padding to avoid navbar overlap
- Update CLAUDE.md to document English-only commits

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Replace bottom navbar with a single top header bar:
- D-CAS v2.0.0 logo on the left
- Nav links (home, catalog, more) with SVG icons inline
- Language selector (english 🇬🇧 ▼) on the right
- Active link highlighted in green
- "More" dropdown for privacy & legal pages

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Move header HTML + logic into dedicated component file
- Export bindHeaderEvents() to keep event wiring in one place
- layout.ts becomes a thin re-export barrel
- Update all views and router to use header() instead of nav()

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Adjust header: stacked logo, justify-between, hr separator
- Center all h1 titles in main content areas

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add border-gray-200 to hr for light gray color
- Fix English catalogue path to /catalog (matches router)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add checkbox in "More" dropdown, checked by default
- Register/unregister service worker based on toggle state
- Add network-first SW with cache fallback (public/sw.js)
- Persist preference in localStorage (dcas-offline)
- Add i18n translations for offline label (en/fr/es)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Bottom bar with catalog, home, more icons (visible < md)
- Desktop nav hidden on mobile, bottom bar hidden on desktop
- Mobile "more" dropdown with offline toggle, privacy, legal
- Sync offline checkbox state between mobile and desktop
- Add bottom padding on mobile to avoid navbar overlap

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…catalogue

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…bile navbar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…orrectly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…arch styles, change hr border color to gray-300
ffillouxdev and others added 26 commits June 1, 2026 11:19
- scripts/verify-build.js: use node: protocol imports, extract nested template
- public/sw.js: globalThis over self, verify message origin (CRITICAL fix),
  remove unused catch bindings
- src/views/catalog.ts: dataset API over setAttribute/removeAttribute,
  extract nested ternaries
- src/router.ts: globalThis over window
- src/components/header.ts: globalThis over window, includes() over some()
…o-image placeholder

- SEO: keyword-rich home title, per-route descriptions, OG image (1200x630),
  Twitter summary_large_image; add H1 to catalog (sr-only) and about pages
- Legal/RGPD: fill legal notice & privacy policy with official CIRAD data
  (publisher, director of publication, host, data controller, DPO, user
  rights, CNIL), add connection-logs section
- Rename contact email sugarcane-diseases@ -> canedr@cirad.fr (EN/FR/ES)
- PWA: generate icon-192/icon-512 (circular, black border) and og-image
  from the CaneDr logo; add manifest, robots.txt, sitemap, llms.txt
- Result view: CaneDr badge placeholder for diseases without photos,
  responsive size (smaller on mobile)
- Service worker cache bump v6 -> v8
- About: shrink CIRAD logo on mobile
- Add deploy/nginx-cache.conf (cache policy snippet)
…dup cache headers

- sw.js: match '/datas/diseases-img' (without trailing slash) so the WebP
  folder '/datas/diseases-img-webp/' is covered by the offline image cache
  (#4); bump cache v8 -> v9
- deploy/canedr.conf: track the server block; serve manifest.webmanifest as
  application/manifest+json (#2); collapse the duplicate Cache-Control on
  /assets/ into a single header (#3)
Make the trilingual site actually indexable per language.

- routes.ts: shared language-aware routing model (EN at root, FR /fr/, ES /es/)
  with localized slugs, urlFor() and resolvePath() helpers
- router.ts: derive language from the URL prefix; per-page canonical, og:url,
  og:locale and hreflang alternates updated on navigation
- i18n.ts: language comes from the URL (drop localStorage detector); smaller bundle
- header.ts: nav links and the language switcher build/navigate prefixed URLs
- scripts/prerender.mjs: after vite build, render each page x language to a
  static HTML file (correct <head> + view markup) via Vite SSR, no headless
  browser; also generate a multilingual sitemap.xml with hreflang
- package.json: build now runs the prerenderer
- remove the static public/sitemap.xml (now generated)
Now that every valid route is prerendered to its own file, nginx no longer
needs to fall back to /index.html (which served the SPA shell with a 200 for
any URL — a soft-404 that hurts SEO).

- prerender.mjs: generate a static dist/404.html (noindex) from the app header
  + not-found view
- deploy/canedr.conf: 'try_files $uri $uri/ =404' + 'error_page 404 /404.html'
  so unknown URLs return a 404 status with the prerendered page
notFoundView() (used in dev/preview and on client-side navigation to unknown
URLs) now matches the prerendered 404.html: responsive CaneDr logo above the
message.
feat(seo): language-prefixed URLs (/fr/ /es/) + build-time prerendering
The committed lock was missing @sonar/scan while package.json declared it,
so 'npm ci' refused to install (lock out of sync) and every CI job failed
early. Commit the in-sync lockfile.
Prerendered pages live at /fr/catalogue/index.html, so nginx 301-redirects
/fr/catalogue -> /fr/catalogue/. Canonicals/hreflang/sitemap pointed at the
no-slash form, causing a redirect on every canonical URL. urlFor() now emits
the trailing slash so canonical == served URL (no redirect).
Drop the GitHub Actions SonarCloud analysis job; code quality now runs
through a local SonarQube instance. Also ignore the local scanner's
.scannerwork/ output directory.
…e detection

- Welcome popup on first visit (any entry page): 404-style logo, short
  tool description, en|fr|es switcher, close cross and Enter button.
  Dismissal is remembered via a local technical preference
  (dcas-welcome-seen), same category as the language and offline flags —
  no consent banner needed, privacy policy unchanged.
- Browser language detection on first visit only: unprefixed (English)
  URLs are rewritten via history.replaceState to /fr/ or /es/ when the
  browser language matches; explicit /fr/ and /es/ URLs always win, any
  other language stays English.
- New welcome.* i18n keys in EN/FR/ES.
- The 404 page button used an inline onclick handler, which the
  Content-Security-Policy (script-src 'self') blocks in production.
  Replace it with a plain link to the home page, in both the runtime
  view (router.ts) and the prerendered 404.html (prerender.mjs).
- Commit package-lock.json (was gitignored) so installs are reproducible
  and dependency updates are reviewable.
@ffillouxdev ffillouxdev self-assigned this Aug 14, 2026
@ffillouxdev ffillouxdev added the enhancement New feature or request label Aug 14, 2026
@ffillouxdev
ffillouxdev merged commit 93df41a into main Aug 14, 2026
4 checks passed
@ffillouxdev
ffillouxdev deleted the claude branch August 14, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant