Skip to content

About

Bilingual EN/AR portfolio built with Next.js 14 — right-to-left as a first-class layout mode, not a translation layer.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Abdulrahman Mohammed — Portfolio

A bilingual (English / Arabic) portfolio site, built as a single Next.js app where right-to-left is a first-class layout mode rather than a translation layer.

Live: arcode-portfolio.netlify.app · English · العربية


The interesting part: bidirectional layout

Most sites treat RTL as a checkbox. It isn't one — layout, typography, numerals, punctuation and even the direction a progress bar grows all change. This codebase handles it structurally rather than with per-component patches:

  • dir is set once, server-side, from the route segment. Every component inherits it; there is not a single dir={isArabic ? …} in the tree.
  • Logical properties throughout — ms-/me-, ps-/pe-, start-/end-, text-start/text-end. Physical left/right utilities survive only where the geometry genuinely is not directional.
  • rtl: / ltr: Tailwind variants registered in tailwind.config.ts (Tailwind v3 does not ship them; they arrive in v4).
  • Arabic typography is not Latin typography. Letter-spacing is zeroed — tracking breaks the joins of a connected script — text-transform is disabled, leading opens from 0.88 to 1.25, and display sizes step down per breakpoint so an Arabic heading occupies the same block as its English counterpart.
  • Latin islands (email, coordinates, version strings, the UTC clock) opt back out with dir="ltr" and keep their Latin face and tracking.
  • Direction-aware motion — CSS has no logical transform-origin, so progress and fill bars use an origin-inline-start helper, and the marquee reverses so it never scrolls against the reading direction.

Each language is a real, indexable URL (/en, /ar) with its own metadata, canonical link and hreflang alternates. / redirects by cookie, then Accept-Language, then English.


Stack

Layer Tooling
Framework Next.js 14 (App Router) · React 18 · TypeScript 5
Styling TailwindCSS 3
Motion Framer Motion · GSAP
Smooth scroll @studio-freight/lenis
3D Three.js (vanilla — no R3F, for bundle size)
Type Space Grotesk · Inter · Space Mono · IBM Plex Sans Arabic
Contact form Web3Forms (no backend)

Selected work featured on the site

# Project Year Stack Live
01 Why Did I Get It Wrong — AI math-mistake analyzer 2024 React · Groq API · RTL · Tailwind wdigiw-v2.netlify.app
02 Bayt Halab — luxury restaurant site 2026 HTML/CSS · RTL · Responsive bayt-halab.netlify.app
03 Wily's Iraq — fine-dining concept site 2026 Next.js · Reservations · Dark UI wilysiq.netlify.app
04 TaskLock — Android focus app 2026 Flutter · Android —

Running it

npm install
npm run dev          # http://localhost:3000 → redirects to /en or /ar

Contact form

Submissions are forwarded by Web3Forms. Without a key the endpoint returns 503 with a real error — it will not pretend a message was delivered.

  1. Register your address at web3forms.com and verify it.
  2. Create .env.local at the project root (Next.js does not read .env files from inside app/):
    WEB3FORMS_ACCESS_KEY=your-access-key-here
    
  3. In production, set the same variable in your host's dashboard (Netlify → Site configuration → Environment variables) and redeploy.

Content

All copy for both languages lives in one file:

app/lib/content.ts     # portfolioContent: Record<Locale, PortfolioContent>

Add a locale by extending Locale, adding its block, and listing it in locales; routing, metadata, sitemap and the language toggle all read from there.


Structure

app/
├── [locale]/
│   ├── layout.tsx            # root layout — sets lang/dir, per-locale metadata
│   └── page.tsx
├── api/contact/route.ts      # Web3Forms endpoint, bilingual errors
├── components/
│   ├── animations/           # Reveal, SplitHeading
│   ├── layout/               # Navbar, Footer, SmoothScroll, Theme/LanguageProvider
│   ├── sections/             # Hero, About, Skills, Projects, Services, Contact, Marquee
│   ├── three/                # WireSphere, KineticGrid
│   └── ui/                   # CustomCursor, LoaderScreen, CommandMenu, …
├── lib/content.ts            # ← all content, both locales
├── globals.css               # tokens, RTL/Arabic typography, keyframes
└── sitemap.ts
middleware.ts                 # locale detection and redirect

Interactions

Trigger Effect
⌘K / Ctrl K Command palette
EN / ع in the header Switch language (navigates to /en or /ar)
Theme button Light ⇄ dark
Hover skill cards Invert + expand tag list
Hover project images Scale + "View" reveal → live demo
Konami code, or type studio Easter egg

Accessibility & performance

  • Semantic landmarks, visible :focus-visible rings, aria-label on icon-only controls
  • prefers-reduced-motion shortens every animation and skips the intro loader entirely
  • Intro loader is time-boxed to 800ms and shown once per session
  • Custom cursor and the 3D scene are gated to fine-pointer devices
  • next/font self-hosts all four families — no layout shift, no render-blocking request

Credits

Designed and built by Abdulrahman Mohammed — Baghdad, Iraq.

Lenis · Three.js · Framer Motion · Web3Forms

About

Bilingual EN/AR portfolio built with Next.js 14 — right-to-left as a first-class layout mode, not a translation layer.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages