# Portfolio Site `06 · portfolio-site · Open source` الموقع الذي تقرأه. React · Vite · TypeScript مع CSS قائم على tokens، محتوى EN/RU/AR typed، مرايا Markdown، telemetry تراعي الخصوصية، وnavigation واعية بالroute. **النطاق:** Solo · مستمر **الدور:** Engineering portfolio · 2025–2026 --- ## السياق > ست حالات لا يستطيع recruiter فتحها. وموقع واحد يستطيع. من أصل ستة مشاريع معروضة، خمسة خلف نطاق مغلق أو NDA — client work، internal tooling، وR&D. لا يستطيع recruiter فتحها أو diff history. الموقع نفسه هو artifact العام الوحيد الذي يستطيع reviewer تدقيقه فورا: DevTools، network، CSS، view-source. كل تفصيل يراه المستخدم هو أيضا قرار يراه المهندس. القيد مزدوج: يجب أن يقرأه recruiter خلال خمس ثوان — cards ثابتة الشكل، spec-sheets mono، ASCII diagrams. ويجب أن يصمد أمام senior eye بطيئة — token-first design، i18n مخصص، view transitions، وHero ember field لا يسخن iPhones. ## حقائق | | | |---|---| | **النطاق** | Solo · مستمر | | **الأسطح** | Home + 6 cases · EN/RU/AR · dark/light · 3 palettes | | **المصدر** | مستودع GitHub عام · CV PDF · أزرار copy-as-Markdown | | **التقنيات** | React 18 · Vite · TypeScript · CSS variables | | **المحتوى** | Typed dictionaries · public/private content trees · مرايا Markdown مولدة | | **القياس** | أحداث دون ملفات تعريف ارتباط إلى same-origin · dashboard للمدير فقط | | **الحركة** | View transitions · يحترم prefers-reduced-motion | | **الحالة** | Open source · live | ## المعمارية ### شجرة providers + routing ```text // src/theme/ThemeContext.tsx // src/i18n/LangContext.tsx ``` **ترتيب providers مهم.** ThemeProvider في الخارج حتى تكتب palette على `` قبل أن يقرأ أي child متغيرات اللون. LangProvider بعده حتى يكون `useT()` متاحا في كل مكان. Loader وscroll restoration وanalytics داخل router لأنها تحتاج routed content أو `useLocation()`. **مساران وظيفيان + fallback.** `/` يعرض home، و`/cases/:slug` يعرض case study، و`*` يعود إلى home للروابط غير المعروفة. slug whitelist يعيش في `src/config/cases.ts` وتستهلكه Nav وProjectDetailPage؛ server analytics لديه allowlists خاصة به. **لا code-splitting بعد.** المساران يشحنان في bundle واحد. Lighthouse ما زال أخضر؛ يعاد النظر عندما يظهر route ثالث. ### سلسلة حلّ tokens ```text 1 ThemeContext theme = 'dark' → palette = 'ochre' │ ▼ writes data-attrs on 2 │ ▼ tokens.css matches via attribute selectors 3 [data-theme="dark"] → --bg --fg --line [data-palette="ochre"][data-theme="dark"] → --accent --accent-soft │ ▼ CSS modules imported by styles.css consume via var() 4 .hero h1 { color: var(--fg) } .chip { background: color-mix(in oklab, var(--bg) 10%, …) } ``` **Theme يحدد palette.** الاشتقاق deterministic: dark → ochre وlight → electric. كلا `data-theme` و`data-palette` يكتبان على ``. CSS يبدل عبر attribute selectors؛ صفر branching في JS لكل عنصر. **Token file + CSS modules، بلا Tailwind.** `tokens.css` هو مصدر الحقيقة للألوان والمسافات والخطوط والزوايا. `styles.css` مجرد entry يستورد base وhome وmedia وcase-study وruntime. نظام tokens يقوم بدور Tailwind config، والselectors تقوم بدور utility classes. **oklch + color-mix للخلفيات.** استخدام كثيف لـ `color-mix(in oklab, var(--bg) X%, transparent)` للطبقات الملوّنة — hero chips، case-study glows، diagram backdrops. يتجنب opacity hacks على اللون الخطأ. ### Loader + مراحل دخول الواجهة ```text T=0 T=400 ms T=900 ms │ │ │ ▼ ▼ ▼ pulse → rush → gone hairline two whiteish blurred loader unmounted opacity pulses run from 15% / 85% hero/about reveal 0.22-0.7 toward center (600 ms) (staggered) at T+400 ms of rush: html.is-loading removed (was set synchronously by inline