Implement hash routing, i18n, and responsive navigation components - #5
Merged
Conversation
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
…ding from call-to-action section
- 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prod