Skip to content

Latest commit

 

History

40 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ihab Khaled — Portfolio & CV

The source for the personal portfolio and CV site of Ihab Khaled, Senior Software Engineer — built as a real production Next.js application rather than a template with placeholder content. It started life on a strict frontend engineering OS (NextRanger) and kept every guardrail that OS enforces: module-first architecture, machine-checked layer boundaries, TDD gates, and security/performance/a11y/i18n baselines — same discipline you'd expect from production backend work, applied to a CV site.

What's actually on the site

  • 17 fully translated locales (en ar fr it de hi fa th ja zh es pt ko tr ru id nl), locale-prefixed URLs, reciprocal hreflang, and real RTL layouts for Arabic and Persian — not just mirrored CSS, but Arabic/Persian prose for every section including case studies.
  • Case-study project pages sourced from a typed project catalog, enriched at request time with live GitHub data (stars, primary language, license, last-activity) that degrades to static fallback values on any failure or rate limit — the page never breaks because GitHub did.
  • A working contact form (Zod-validated, rate-limited, SMTP via nodemailer) that fails safely to a "email me directly" state when no transport is configured, rather than pretending to succeed.
  • A downloadable, redacted CV PDF, generated straight from the resume page's own print stylesheet — one source of truth for the on-screen and PDF resume.
  • Installable as a PWA with an offline fallback route, and JSON-LD structured data (Person, WebSite, BreadcrumbList, SoftwareSourceCode) on the pages that warrant it.
  • No fake numbers. Skill levels are grouped by depth of production experience, not rendered as percentages; every "years of experience" figure and every stat is one Ihab can defend.

Quick start

nvm use
corepack enable
npm install
npm run dev        # http://localhost:3000

The pinned toolchain is Node 24.18.0 and npm 12.0.1; .nvmrc, .node-version, and packageManager keep local and CI installs identical. Copy .env.example to .env and fill in only what you need — the site renders fully with every variable at its default (GitHub calls fall back to static data without GITHUB_TOKEN; the contact form reports itself unavailable without SMTP credentials).

Gates:

npm run lint             # ESLint, --max-warnings=0
npm run typecheck        # stable TypeScript 7 over app/test/node configs
npm run typecheck:compat # TypeScript 6 API compatibility for ESLint/tooling
npm run test:coverage    # Vitest + coverage thresholds
npm run build            # next build --turbopack
npm run test:e2e:install # one-time Playwright browser install (chromium for this project)
npm run test:e2e:baseline # explicit, reviewed refresh of every current-OS baseline
npm run test:e2e         # Playwright (builds and starts the prod server itself)
npm run test:a11y        # axe + keyboard suites
npm run test:visual      # screenshot baselines
npm run security:audit   # runtime graph, every severity
npm run security:scan    # Trivy: vuln + secret + misconfig
npm run quality:dead-code  # knip
npm run quality:circular   # dependency-cruiser
npm run validate         # everything above, in order

First-time e2e setup (repeatable on any OS): run these two local-binary one-time steps before the first npm run validate:

npm run test:e2e:install   # playwright install chromium
npm run test:e2e:baseline  # playwright test src/tests/visual --update-snapshots=all

Visual baselines are per-OS (*-chromium-linux.png, *-chromium-win32.png, …). CI runs on Linux and is compare-only — it fails when a Linux baseline is missing or changed. Generate or refresh Linux baselines from a matching Linux environment (CI itself, or a container built the same way .github/workflows/e2e.yml provisions its runner), never cross-platform from Windows or macOS; see testing/visual-testing-standard.md.

Architecture in one breath

src/app routes and composes; src/modules/<feature> owns each feature through strict layers (components are TSX-only, hooks orchestrate, services/gateways speak HTTP, mappers translate wire↔domain, queries own the cache, stores hold client-only state); src/shared is generic; src/packages wraps every vendor exactly once; src/tests proves all of it; src/proxy.ts signs every response with a nonce CSP.

Canonical source tree

src/
  app/            routes, layouts, route handlers — [locale]/ (about, experience, projects,
                  projects/[slug], skills, resume, contact, offline), api/ (contact, health)
  modules/        about, contact, experience, github-profile, profile (home + public identity),
                  projects, pwa, resume, site-navigation, skills, ui-preferences, health
  shared/         config, constants, enums, errors, i18n keys, generic components
  packages/       axios, query, zustand, zod, date, forms, i18n, toast, icons, mailer,
                  ui-primitives, virtuoso, link, image, navigation, env, browser,
                  storage, logger, headers — one owner per vendor
  shared/fonts/   Space Grotesk (display), Inter (body), IBM Plex Mono (utility), and
                  Noto Sans Arabic/Devanagari/Thai — selected per :lang(), one owner
  tests/          setup, msw, unit, integration, e2e, accessibility, visual, factories
  proxy.ts        per-request nonce Content-Security-Policy
eslint/           split flat configs + the frontend-architecture plugin (14 rules)
rules/ skills/ agents/ context/ memory/ testing/ docs/   the governance brain

The full annotated map lives in context/architecture-map.md.

The component / container / hook / query / service split

Layer File suffix May contain
Component .component.tsx JSX from pre-computed props — nothing else
Container .container.tsx 'use client' + reason; wires hooks to JSX
Hook .hook.ts orchestration, translation, view models
Query .queries.ts etc. TanStack Query bound to key builders
Service .service.ts use-cases; React does not exist here
Gateway .gateway.ts HTTP wire contracts, Zod-validated
Mapper/Helper/Util .mapper.ts pure logic, 100% branch-covered
Types/Enums/Consts .types.ts declarations only; enums are as const

See rules/02-components-and-containers.md and the real examples quoted in context/reference-patterns.md.

Every library has one owner

Raw vendor imports outside their owner wrapper fail the lint gate (frontend-architecture/no-raw-package-imports). The complete vendor → owner → facade table is in context/package-boundaries.md. Adding a package means adding a wrapper: skills/create-package-wrapper.md.

Reference modules

  • projects — the flagship: a typed catalog, category filters, case-study pages that merge static content with live GitHub data and degrade safely, and full JSON-LD structured data.
  • contact — schema-validated form with server-side rate limiting, a real SMTP send path, and a distinct "service unavailable" state instead of a silent failure.
  • github-profile — the server-only GitHub REST integration: optional token, typed responses, and a static fallback so a GitHub outage or rate limit never breaks a page.
  • ui-preferences — Zustand for true client global state (theme/direction) with validated persistence and DOM sync through facades.
  • health — the smallest possible module: one service, one route handler, one test.

Testing strategy

TDD is policy (rules/15-testing-and-coverage.md): pure logic first, then services/schemas/mappers, then integration through real providers with MSW, then Playwright happy/negative paths, axe scans, keyboard walks, and visual baselines across desktop/tablet/mobile and LTR/RTL/dark theme. Standards live under testing/.

Security and performance defaults

Nonce-based CSP with strict-dynamic (src/proxy.ts), static security headers (next.config.ts), Zod-validated public/server env split with a server-only guard, sanitized error keys, safe external links (rel="noopener noreferrer" on every one), Trivy + audit gates — see rules/11-security.md. Server Components first, justified client boundaries, virtualization for long lists — see rules/12-performance.md.

Guides

  • Translation guide — how the 17 locale catalogs are structured and kept in parity, and the workflow for adding or updating translated copy.
  • Content update guide — how to add a job, a project, or a skill without touching architecture: which files to edit, in what order.
  • PWA and offline behavior — what "installable" means here, and what the offline fallback route does and doesn't cover.
  • GitHub integration — how live repository data is fetched, cached, and safely degraded to static fallback values.

AI tool compatibility

The governance layer this repo inherited is still live and still enforced — useful both for any coding agent extending this site and as a demonstration of how the discipline holds up in practice, not just in theory. Point an agent at its entrypoint and it inherits the whole system:

Task-shaped playbooks live in skills/; reviewer personas in agents/; durable decisions and pitfalls in memory/.

How to add a new feature

Follow skills/create-module.md: plan tests first, scaffold the module layers, expose a public surface via index.ts, add route + nav constants, add message keys to every locale catalog, and run the gates. The full lifecycle template is under docs/features/_template/.

How to add a new package wrapper

skills/create-package-wrapper.md: install, create src/packages/<owner>/ with an index.ts facade and app-owned types, register the boundary in eslint/package-boundaries.config.mjs, document it in context/package-boundaries.md, and test the facade.

License / status

Private repository — personal portfolio, not a template for reuse. The underlying architecture it was built on, NextRanger, is the place to look for a clonable starting point.

About

Production-grade personal portfolio and CV built with Next.js: 17 locales, RTL support, live GitHub project data, case studies, downloadable PDF resume, PWA/offline support, secure contact form, SEO/JSON-LD, accessibility, strict architecture, TDD, security and performance gates.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages