16

Website

The Next.js landing page in website/

4 min read7 sections

The website/ folder holds the CleanLens marketing landing page and the documentation pages that render this docs/ folder. It is a separate application: it does not import the extension's code, has its own package.json and lockfile, and is not part of the extension package.

Stack

PieceVersion / choice
FrameworkNext.js 16 (App Router)
UIReact 19, Tailwind CSS 4
Internationalizationi18next + react-i18next, accept-language
3D backgroundThree.js
AnimationGSAP (@gsap/react)
Docs renderingmarked (Markdown), shiki (code highlighting), github-slugger (heading ids)
FontsAlexandria, IBM Plex Sans Arabic, IBM Plex Sans, JetBrains Mono (via next/font/google)
Node≥ 20.9

Running it

bash
cd website
npm install
npm run dev     # http://localhost:3000 → redirects to /ar, /en or /tr
npm run build
npm start
npm run lint

next.config.ts sets turbopack.root to the website/ folder, because the extension's own lockfile one level up would otherwise confuse Next.js about the project root.

Structure

text
website/
├── app/
│   ├── [locale]/
│   │   ├── layout.tsx      fonts, <html lang/dir>, metadata, theme bootstrap
│   │   ├── page.tsx        renders HomePageContent for the locale
│   │   ├── docs/page.tsx   docs home (cards per group)
│   │   ├── docs/[slug]/page.tsx   one doc page
│   │   └── globals.css
│   ├── i18n/
│   │   ├── settings.js     languages, fallback, RTL list, cookie name
│   │   ├── index.js        server-side getTranslation()
│   │   └── locales/{ar,en,tr}/translation.json
│   └── icon.png
├── components/
│   ├── ForPages/Home/      one folder per page section (see below)
│   ├── ForPages/Docs/      DocsShell, DocsSidebar, DocArticle, DocToc, docs.css
│   └── Global/             Navbar, LanguageSwitcher, Footer, ThemeToggle,
│                           BackToTop, CopyCommandButton, RichText, Icons
├── lib/constants.ts        Marketplace URL, extension id, install command,
│                           EXTENSION_VERSION, theme storage key
├── lib/docs.ts             reads and renders docs/*.md (build time)
├── proxy.ts                locale redirect (Next.js 16 "proxy", formerly middleware)
└── public/images/

Page sections

components/ForPages/Home/HomePageContent.tsx renders, in order:

SectionFolderContent
BackgroundScene/Animated 3D Git-graph scene (Three.js)
HeroHero/Title, typing install command, tilt card
Vibe codingVibeCoding/Demo of findings on AI-generated code
ProblemProblem/Why blame-based attribution is unfair (legacy-file example)
PipelinePipeline/The analysis steps
ScoringScoring/The score formula, sample developer card
RulesRules/The 14 rules
UsageUsage/Extension vs. CLI tabs
AudienceAudience/Who it is for
PrivacyPrivacy/Local-only guarantees
LimitsLimits/Honest limitations
RoadmapRoadmap/Planned work
Final CTAFinalCta/Install call-to-action

Motion/ScrollAnimations.tsx adds GSAP scroll effects.

Documentation pages

The navbar's Documentation button opens /<locale>/docs. The pages are built from the repository's docs/ folder at build time (fully static).

RouteContent
/<locale>/docsDocs home: a highlighted card for the customization guide, then one card per doc, grouped like docs/README.md
/<locale>/docs/<slug>One doc: sidebar, article, "On this page", previous/next

The slug is the file name without its number: 08-scoring.md → /en/docs/scoring.

Where the content comes from (lib/docs.ts):

  • The list, order, groups, titles and summaries are parsed from the tables in docs/README.md (or docs/<locale>/README.md), so adding a row there adds a page.
  • /ar/... reads docs/ar/, /tr/... reads docs/tr/, /en/... reads docs/. A missing translation falls back to English (shown left-to-right).
  • The docs/ folder is found next to website/ whether the server is started from website/ or from the repository root. Set CLEANLENS_DOCS_DIR to override. Deployments must include the docs/ folder at build time.

Rendering:

  • Headings get ids with github-slugger; translated headings reuse the English ids by position (see 15).
  • Links to other docs become site links; links to repository files (source code, top-level README) are shown as plain text because the repository is private.
  • Code blocks are highlighted with shiki in light and dark themes and have a Copy button. Tables scroll horizontally on small screens. Blockquotes render as callouts.

Interface: sidebar with search (press / or Ctrl/Cmd+K; matches titles, summaries and section headings), an "On this page" list that follows the scroll, previous/next links, a mobile drawer below 960 px, and right-to-left layout for Arabic. UI labels are in docs.* keys of the translation files.

Languages

  • Supported: Arabic (ar, default and fallback, RTL), English (en), Turkish (tr).
  • All text lives in app/i18n/locales/<lng>/translation.json.
  • dirFor(lng) sets dir="rtl" for Arabic.
  • Rich text in translations uses tags mapped in components/Global/RichText/RichText.tsx: <hl> (highlight), <code>, <kbd>, <mk> (Marketplace link), and others.

Locale routing (proxy.ts)

For any path without a locale prefix, the visitor is redirected to a locale chosen from, in order: the i18next cookie → the Accept-Language header → Arabic. When a page is visited under a locale, that locale is saved in the cookie. Static assets (_next, images, assets, favicon.ico, …) are not redirected.

Adding a language

  1. Add the code to languages in app/i18n/settings.js (and to rtlLanguages if RTL).
  2. Create app/i18n/locales/<code>/translation.json with the same keys as en.
  3. Add its labels to LABELS and SHORT in components/Global/Navbar/LanguageSwitcher.tsx (the switcher lists every entry of languages).
  4. Add the font subset in app/[locale]/layout.tsx if the script needs one.

Theme

Light is the default. The visitor's choice is stored in localStorage under cleanlens-theme (THEME_KEY) and applied by the layout before paint, to avoid a flash of the wrong theme.

Release checklist for the site

  • Update EXTENSION_VERSION in lib/constants.ts to match package.json.
  • If rules, scoring or limitations changed, update the matching sections in all three translation files.