first commit
ci / build (push) Failing after 23s
deploy / deploy (push) Failing after 10m12s

This commit is contained in:
soroush.asadi
2026-05-31 12:47:02 +03:30
commit add78d8460
100 changed files with 15221 additions and 0 deletions
+855
View File
@@ -0,0 +1,855 @@
export type Locale = 'fa' | 'en';
export const LOCALES: Locale[] = ['fa', 'en'];
export const DEFAULT_LOCALE: Locale = 'fa';
/**
* Service identifiers stay locale-independent so they can key into
* routes (`/services/[slug]`), analytics events, and form values.
*/
export const SERVICE_IDS = [
'strategy',
'automation',
'llm-rag',
'architecture',
'mobile',
'google-stack',
] as const;
export type ServiceId = (typeof SERVICE_IDS)[number];
export const dict = {
fa: {
meta: {
title: 'سروش اسعدی — مهندس هوش مصنوعی، مشاور، معمار راهکار',
description:
'طراحی و پیاده‌سازی سامانه‌های هوش مصنوعی در مقیاس سازمانی — راهبرد، LLM و RAG، اتوماسیون عامل‌محور، زیرساخت ابری و استک گوگل.',
},
nav: {
services: 'خدمات',
stack: 'استک',
expertise: 'تخصص',
portfolio: 'نمونه‌کارها',
blog: 'بلاگ',
contact: 'تماس',
book: 'رزرو جلسه',
},
locale: {
switchTo: 'EN',
label: 'زبان',
},
hero: {
availability: 'پذیرش پروژه‌های منتخب فصل سوم ۲۰۲۶',
eyebrow: 'مهندس هوش مصنوعی · مشاور · معمار راهکار',
name: 'سروش اسعدی',
headlineLead: 'طراحی سامانه‌های',
headlineAccent: 'هوش مصنوعی',
headlineTrail: 'در مقیاس سازمانی.',
sub:
'از راهبرد تا تولید — ساخت پایپ‌لاین‌های LLM، عامل‌های خودکار، و معماری‌های ابری که در میلیون‌ها رویداد در روز پایدار می‌مانند.',
roles: [
'راهبرد هوش مصنوعی',
'مهندسی LLM و RAG',
'معماری راهکار',
'اتوماسیون عامل‌محور',
'استک گوگل کلود',
],
ctaPrimary: 'رزرو جلسه مشاوره',
ctaSecondary: 'مشاهده خدمات',
scroll: 'اسکرول',
metrics: [
{ value: '۱۸+', label: 'مدل هوش مصنوعی مستقر' },
{ value: '۴۰+', label: 'میکروسرویس تولید' },
{ value: '۱۲ms', label: 'تأخیر استنتاج' },
{ value: '۹۹٪', label: 'پایداری SLA' },
],
},
services: {
eyebrow: 'خدمات',
title: 'شش حوزه تخصصی',
sub:
'از اولین جلسه‌ی راهبرد تا استقرار تولید — یک شریک مهندسی برای کل چرخه‌ی عمر هوش مصنوعی شما.',
items: [
{
id: 'strategy',
title: 'راهبرد و نقشه راه هوش مصنوعی',
description:
'ارزیابی بلوغ سازمانی، شناسایی موارد کاربری با بیشترین بازده، و طراحی نقشه راه ۱۲–۱۸ ماهه با KPIهای روشن.',
tags: ['Discovery', 'ROI Mapping', 'Roadmap'],
color: 'electric',
},
{
id: 'automation',
title: 'اتوماسیون هوش مصنوعی',
description:
'ساخت عامل‌های خودکار و گردش‌کارهای n8n که فرایندهای دستی را به سامانه‌های قابل ممیزی تبدیل می‌کنند.',
tags: ['n8n', 'Agents', 'Workflows'],
color: 'violet',
},
{
id: 'llm-rag',
title: 'مهندسی LLM و RAG',
description:
'طراحی pipeline‌های RAG با پایگاه‌های برداری، evaluation framework، و سرویس‌دهی با تأخیر زیر ۵۰ میلی‌ثانیه.',
tags: ['RAG', 'Vector DB', 'Eval'],
color: 'magenta',
},
{
id: 'architecture',
title: 'معماری راهکار',
description:
'طراحی سامانه‌های توزیع‌شده روی Kubernetes با میکروسرویس‌ها، event streaming، و الگوهای پایداری در مقیاس بالا.',
tags: ['K8s', 'Microservices', 'Event-Driven'],
color: 'emerald',
},
{
id: 'mobile',
title: 'اپلیکیشن‌های موبایل هوش مصنوعی',
description:
'برنامه‌های Flutter، Swift و Kotlin با on-device inference، استریم LLM و تجربه‌ی کاربری بومی.',
tags: ['Flutter', 'Swift', 'Kotlin'],
color: 'electric',
},
{
id: 'google-stack',
title: 'تخصص استک گوگل',
description:
'استقرار روی Vertex AI، GKE و Gemini با بهینه‌سازی هزینه و الگوهای امنیتی سطح enterprise.',
tags: ['Vertex AI', 'GKE', 'Gemini'],
color: 'cyan',
},
],
},
dataflow: {
eyebrow: 'پایپ‌لاین',
title: 'از سند خام تا پاسخ قابل اتکا',
sub:
'مسیری که هر پرسش در یک سامانه‌ی RAG تولیدی طی می‌کند — هر مرحله قابل اندازه‌گیری، قابل ممیزی و بهینه‌شده برای تأخیر.',
caption: 'تأخیر سرتاسری زیر ۵۰ میلی‌ثانیه · هر مرحله مشاهده‌پذیر',
nodes: [
{
id: 'ingest',
label: 'دریافت',
desc: 'نرمال‌سازی، قطعه‌بندی و پاک‌سازی اسناد منبع',
accent: 'electric',
},
{
id: 'embed',
label: 'برداری‌سازی',
desc: 'تولید embedding و نمایه‌سازی در پایگاه برداری',
accent: 'violet',
},
{
id: 'retrieve',
label: 'بازیابی',
desc: 'جستجوی ترکیبی معنایی و کلیدواژه‌ای',
accent: 'cyan',
},
{
id: 'rerank',
label: 'بازرتبه‌بندی',
desc: 'مرتب‌سازی مجدد نامزدها با cross-encoder',
accent: 'magenta',
},
{
id: 'generate',
label: 'تولید',
desc: 'پاسخ مستند با ارجاع به منبع',
accent: 'emerald',
},
],
},
stack: {
eyebrow: 'استک',
title: 'ابزارهای روزانه',
sub:
'هر چه ساخته می‌شود از این پایه‌ها بیرون می‌آید — انتخاب‌شده برای عمر طولانی، نه ترند روز.',
categories: [
{
id: 'languages',
label: 'زبان‌ها',
items: ['Python', 'TypeScript', 'Go', 'Rust', 'SQL'],
},
{
id: 'mobile',
label: 'موبایل',
items: ['Flutter', 'Swift / SwiftUI', 'Kotlin', 'React Native'],
},
{
id: 'infra',
label: 'زیرساخت',
items: ['Kubernetes', 'Terraform', 'Postgres', 'Redis', 'Kafka', 'NATS'],
},
{
id: 'ai',
label: 'هوش مصنوعی',
items: ['Vertex AI', 'Gemini', 'OpenAI', 'Anthropic', 'LangGraph', 'Pinecone', 'pgvector'],
},
],
},
expertise: {
eyebrow: 'تخصص',
title: 'اعدادی که اهمیت دارند',
sub:
'سامانه‌هایی که در میلیون‌ها رویداد در روز پایدار می‌مانند — این‌ها معیارهایی هستند که اندازه می‌گیریم.',
bars: [
{ label: 'مهندسی LLM و RAG', value: 95 },
{ label: 'معماری ابری و Kubernetes', value: 92 },
{ label: 'سیستم‌های عامل‌محور و اتوماسیون', value: 90 },
{ label: 'استک گوگل کلود (Vertex / GKE)', value: 88 },
{ label: 'موبایل بومی و cross-platform', value: 82 },
],
},
blog: {
eyebrow: 'بلاگ',
title: 'یادداشت‌های مهندسی',
sub:
'یافته‌ها از پروژه‌های واقعی — نه ترجمه‌ی مقاله، نه فهرست hype.',
readMore: 'ادامه',
readTimeSuffix: 'دقیقه',
items: [
{
slug: 'rag-eval-framework',
category: 'LLM',
title: 'چارچوب ارزیابی RAG که در تولید کار می‌کند',
excerpt:
'چرا BLEU و ROUGE برای RAG ناکافی‌اند، و معیارهایی که در پروژه‌های واقعی تصمیم می‌سازند.',
readTime: 8,
},
{
slug: 'agentic-n8n-patterns',
category: 'Automation',
title: 'الگوهای عامل‌محور با n8n برای سازمان',
excerpt:
'چگونه n8n را با LangGraph ترکیب کنیم تا گردش‌کارهای قابل ممیزی بسازیم.',
readTime: 11,
},
{
slug: 'vertex-cost-control',
category: 'Google Stack',
title: 'کنترل هزینه روی Vertex AI در مقیاس بالا',
excerpt:
'سه ضدالگو که در ۸۰٪ پروژه‌های Vertex می‌بینم، و چگونه ۶۰٪ هزینه را کاهش دادیم.',
readTime: 6,
},
{
slug: 'k8s-llm-inference',
category: 'Infra',
title: 'استنتاج LLM روی Kubernetes با تأخیر زیر ۵۰ میلی‌ثانیه',
excerpt:
'الگوی استقرار با KEDA، GPU sharing، و request hedging برای سرویس‌دهی پایدار.',
readTime: 14,
},
{
slug: 'flutter-on-device-ai',
category: 'Mobile',
title: 'هوش مصنوعی on-device در Flutter',
excerpt:
'استفاده از Gemini Nano و LiteRT برای استنتاج آفلاین در اپلیکیشن‌های موبایل.',
readTime: 9,
},
{
slug: 'enterprise-ai-roadmap',
category: 'Strategy',
title: 'نقشه راه هوش مصنوعی سازمانی در ۹۰ روز',
excerpt:
'چارچوبی که برای CTOها می‌سازم — از کشف موارد کاربری تا اولین استقرار تولید.',
readTime: 7,
},
],
},
portfolio: {
eyebrow: 'نمونه‌کارها',
title: 'سامانه‌هایی که در تولید کار می‌کنند',
sub:
'گزیده‌ای از پروژه‌های واقعی — از پایپ‌لاین RAG تا مش داده رویدادمحور. روی هر کارت بزنید تا گالری و جزئیات معماری را ببینید.',
labels: {
role: 'نقش',
year: 'سال',
client: 'کارفرما',
stack: 'استک',
view: 'مشاهده پروژه',
gallery: 'گالری',
close: 'بستن',
next: 'بعدی',
prev: 'قبلی',
},
items: [
{
id: 'atlas-rag',
title: 'اطلس — پلتفرم RAG سازمانی',
client: 'بانک ردیف‌اول',
year: '۲۰۲۵',
role: 'مهندس ارشد هوش مصنوعی',
summary:
'دستیار دانش روی بیش از ۴ میلیون سند داخلی؛ بازیابی ترکیبی با pgvector و reranker، چارچوب ارزیابی اختصاصی و سرویس‌دهی با تأخیر زیر ۴۰ میلی‌ثانیه روی Vertex AI.',
accent: 'electric',
tags: ['RAG', 'pgvector', 'Vertex AI', 'Eval'],
metrics: [
{ value: '۴M+', label: 'سند نمایه‌شده' },
{ value: '۳۸ms', label: 'تأخیر p95' },
{ value: '۹۲٪', label: 'دقت پاسخ' },
],
cover: '/portfolio/atlas-rag/cover.svg',
gallery: [
'/portfolio/atlas-rag/01.svg',
'/portfolio/atlas-rag/02.svg',
'/portfolio/atlas-rag/03.svg',
],
},
{
id: 'sentinel-agents',
title: 'سنتینل — اتوماسیون عامل‌محور عملیات',
client: 'اسکیل‌آپ SaaS',
year: '۲۰۲۵',
role: 'معمار راهکار',
summary:
'سامانه پاسخ خودکار به رخدادها با ترکیب n8n و LangGraph؛ عامل‌های قابل ممیزی که هشدارها را دسته‌بندی، ریشه‌یابی و در صورت امکان ترمیم می‌کنند.',
accent: 'violet',
tags: ['n8n', 'LangGraph', 'Agents', 'Observability'],
metrics: [
{ value: '۷۰٪', label: 'کاهش MTTR' },
{ value: '۲۴/۷', label: 'پوشش on-call' },
{ value: '۱۵۰+', label: 'گردش‌کار خودکار' },
],
cover: '/portfolio/sentinel-agents/cover.svg',
gallery: [
'/portfolio/sentinel-agents/01.svg',
'/portfolio/sentinel-agents/02.svg',
'/portfolio/sentinel-agents/03.svg',
],
},
{
id: 'vertex-vision',
title: 'ورتکس ویژن — بینایی ماشین بلادرنگ',
client: 'زنجیره خرده‌فروشی',
year: '۲۰۲۴',
role: 'مهندس هوش مصنوعی',
summary:
'استنتاج بینایی بلادرنگ روی GKE با Triton و Vertex AI برای تحلیل قفسه و رفتار مشتری در صدها شعبه، با مقیاس‌پذیری خودکار مبتنی بر صف.',
accent: 'cyan',
tags: ['Vertex AI', 'GKE', 'Triton', 'Computer Vision'],
metrics: [
{ value: '۱.۲B', label: 'استنتاج در ماه' },
{ value: '۳۰۰+', label: 'شعبه' },
{ value: '۶۰٪', label: 'کاهش هزینه GPU' },
],
cover: '/portfolio/vertex-vision/cover.svg',
gallery: [
'/portfolio/vertex-vision/01.svg',
'/portfolio/vertex-vision/02.svg',
'/portfolio/vertex-vision/03.svg',
],
},
{
id: 'mirage-mobile',
title: 'میراژ — هوش مصنوعی روی دستگاه',
client: 'محصول مصرف‌کننده',
year: '۲۰۲۴',
role: 'سرپرست موبایل و هوش مصنوعی',
summary:
'اپلیکیشن Flutter با استنتاج کاملاً آفلاین به‌کمک Gemini Nano و LiteRT؛ تجربه‌ی استریم پاسخ بدون وابستگی به شبکه و با حفظ کامل حریم خصوصی.',
accent: 'magenta',
tags: ['Flutter', 'Gemini Nano', 'LiteRT', 'On-device'],
metrics: [
{ value: '۰', label: 'وابستگی شبکه' },
{ value: '<۸۰ms', label: 'پاسخ‌دهی' },
{ value: '۴.۸★', label: 'امتیاز کاربران' },
],
cover: '/portfolio/mirage-mobile/cover.svg',
gallery: [
'/portfolio/mirage-mobile/01.svg',
'/portfolio/mirage-mobile/02.svg',
'/portfolio/mirage-mobile/03.svg',
],
},
{
id: 'flux-stream',
title: 'فلاکس — مش داده رویدادمحور',
client: 'پلتفرم لجستیک',
year: '۲۰۲۳',
role: 'معمار پلتفرم',
summary:
'ستون فقرات استریمینگ با Kafka و NATS روی Kubernetes؛ بیش از ۴۰ میکروسرویس با الگوهای پایداری، tracing سراسری و تحویل دقیقاً یک‌بار.',
accent: 'emerald',
tags: ['Kafka', 'NATS', 'Kubernetes', 'Go'],
metrics: [
{ value: '۴۰+', label: 'میکروسرویس' },
{ value: '۲M/s', label: 'رویداد در ثانیه' },
{ value: '۹۹.۹٪', label: 'پایداری' },
],
cover: '/portfolio/flux-stream/cover.svg',
gallery: [
'/portfolio/flux-stream/01.svg',
'/portfolio/flux-stream/02.svg',
'/portfolio/flux-stream/03.svg',
],
},
{
id: 'oracle-forecast',
title: 'اوراکل — موتور پیش‌بینی تقاضا',
client: 'زنجیره تأمین',
year: '۲۰۲۳',
role: 'مهندس یادگیری ماشین',
summary:
'پایپ‌لاین پیش‌بینی سری‌زمانی روی BigQuery و dbt با بازآموزی خودکار؛ کاهش چشمگیر هدررفت موجودی و بهبود دقت برنامه‌ریزی تأمین.',
accent: 'electric',
tags: ['Forecasting', 'BigQuery', 'dbt', 'MLOps'],
metrics: [
{ value: '۲۳٪', label: 'کاهش هدررفت' },
{ value: '۸۹٪', label: 'دقت پیش‌بینی' },
{ value: 'روزانه', label: 'بازآموزی' },
],
cover: '/portfolio/oracle-forecast/cover.svg',
gallery: [
'/portfolio/oracle-forecast/01.svg',
'/portfolio/oracle-forecast/02.svg',
'/portfolio/oracle-forecast/03.svg',
],
},
],
},
contact: {
eyebrow: 'تماس',
title: 'یک جلسه ۳۰ دقیقه‌ای رزرو کنید',
sub:
'هیچ هزینه‌ای، هیچ تعهدی. کاربرد، چالش‌ها و قدم بعدی را با هم بررسی می‌کنیم.',
fields: {
name: 'نام',
company: 'شرکت',
service: 'خدمت مورد نظر',
budget: 'بودجه (تقریبی)',
message: 'پیام',
},
placeholders: {
name: 'نام و نام خانوادگی',
company: 'نام سازمان',
message: 'هدف، زمان‌بندی، و چالش‌های فعلی…',
},
budgets: ['کمتر از $10k', '$10k$50k', '$50k$200k', 'بیش از $200k'],
submit: 'ارسال درخواست',
note: 'پاسخ معمولاً ظرف ۲۴ ساعت کاری.',
},
footer: {
tagline: 'طراحی‌شده در تهران · ساخته‌شده برای enterprise',
rights: '© ۲۰۲۶ سروش اسعدی. تمام حقوق محفوظ است.',
},
},
en: {
meta: {
title: 'Soroush Asadi — AI Engineer · Consultant · Solution Architect',
description:
'Designing and shipping production-grade AI systems for the enterprise — strategy, LLM & RAG, agentic automation, cloud infrastructure, and the Google Stack.',
},
nav: {
services: 'Services',
stack: 'Stack',
expertise: 'Expertise',
portfolio: 'Work',
blog: 'Journal',
contact: 'Contact',
book: 'Book a call',
},
locale: {
switchTo: 'FA',
label: 'Language',
},
hero: {
availability: 'Available for select Q3 2026 engagements',
eyebrow: 'AI Engineer · Consultant · Solution Architect',
name: 'Soroush Asadi',
headlineLead: 'Architecting',
headlineAccent: 'production-grade AI',
headlineTrail: 'for the enterprise.',
sub:
'From strategy to deployment — building LLM pipelines, autonomous agents, and cloud architectures that hold up at millions of events per day.',
roles: [
'AI Strategy',
'LLM & RAG Engineering',
'Solution Architecture',
'Agentic Automation',
'Google Cloud Stack',
],
ctaPrimary: 'Book a consultation',
ctaSecondary: 'View services',
scroll: 'Scroll',
metrics: [
{ value: '18+', label: 'AI models in production' },
{ value: '40+', label: 'microservices shipped' },
{ value: '12ms', label: 'inference latency' },
{ value: '99%', label: 'SLA uptime' },
],
},
services: {
eyebrow: 'Services',
title: 'Six areas of practice',
sub:
'From the first strategy session to production rollout — one engineering partner for the full AI lifecycle.',
items: [
{
id: 'strategy',
title: 'AI Strategy & Roadmap',
description:
'Maturity assessment, highest-ROI use-case discovery, and a 1218 month roadmap with measurable KPIs.',
tags: ['Discovery', 'ROI Mapping', 'Roadmap'],
color: 'electric',
},
{
id: 'automation',
title: 'AI Automation',
description:
'Autonomous agents and n8n workflows that turn manual processes into auditable, observable systems.',
tags: ['n8n', 'Agents', 'Workflows'],
color: 'violet',
},
{
id: 'llm-rag',
title: 'LLM & RAG Engineering',
description:
'Production RAG pipelines with vector stores, evaluation frameworks, and sub-50ms serving.',
tags: ['RAG', 'Vector DB', 'Eval'],
color: 'magenta',
},
{
id: 'architecture',
title: 'Solution Architecture',
description:
'Distributed systems on Kubernetes — microservices, event streaming, and resilience patterns at scale.',
tags: ['K8s', 'Microservices', 'Event-Driven'],
color: 'emerald',
},
{
id: 'mobile',
title: 'Mobile AI Apps',
description:
'Flutter, Swift, and Kotlin apps with on-device inference, streaming LLM UX, and native polish.',
tags: ['Flutter', 'Swift', 'Kotlin'],
color: 'electric',
},
{
id: 'google-stack',
title: 'Google Stack Specialist',
description:
'Vertex AI, GKE, and Gemini deployments with cost optimization and enterprise security patterns.',
tags: ['Vertex AI', 'GKE', 'Gemini'],
color: 'cyan',
},
],
},
dataflow: {
eyebrow: 'Pipeline',
title: 'From raw document to trustworthy answer',
sub:
'The path every query takes through a production RAG system — each stage measurable, auditable, and tuned for latency.',
caption: 'Sub-50ms end-to-end · every stage observable',
nodes: [
{
id: 'ingest',
label: 'Ingest',
desc: 'Normalize, chunk, and clean source documents',
accent: 'electric',
},
{
id: 'embed',
label: 'Embed',
desc: 'Generate embeddings and index in the vector store',
accent: 'violet',
},
{
id: 'retrieve',
label: 'Retrieve',
desc: 'Hybrid semantic + keyword search',
accent: 'cyan',
},
{
id: 'rerank',
label: 'Rerank',
desc: 'Re-order candidates with a cross-encoder',
accent: 'magenta',
},
{
id: 'generate',
label: 'Generate',
desc: 'Grounded answer with source citations',
accent: 'emerald',
},
],
},
stack: {
eyebrow: 'Stack',
title: 'Daily tooling',
sub:
'Everything I ship sits on this foundation — chosen for longevity, not hype cycles.',
categories: [
{
id: 'languages',
label: 'Languages',
items: ['Python', 'TypeScript', 'Go', 'Rust', 'SQL'],
},
{
id: 'mobile',
label: 'Mobile',
items: ['Flutter', 'Swift / SwiftUI', 'Kotlin', 'React Native'],
},
{
id: 'infra',
label: 'Infrastructure',
items: ['Kubernetes', 'Terraform', 'Postgres', 'Redis', 'Kafka', 'NATS'],
},
{
id: 'ai',
label: 'AI / ML',
items: ['Vertex AI', 'Gemini', 'OpenAI', 'Anthropic', 'LangGraph', 'Pinecone', 'pgvector'],
},
],
},
expertise: {
eyebrow: 'Expertise',
title: 'The numbers that matter',
sub:
'Systems that survive millions of events per day — these are the metrics I optimize for.',
bars: [
{ label: 'LLM & RAG engineering', value: 95 },
{ label: 'Cloud architecture & Kubernetes', value: 92 },
{ label: 'Agentic systems & automation', value: 90 },
{ label: 'Google Cloud stack (Vertex / GKE)', value: 88 },
{ label: 'Native + cross-platform mobile', value: 82 },
],
},
blog: {
eyebrow: 'Journal',
title: 'Engineering notes',
sub:
'Findings from real engagements — not translated articles, not hype lists.',
readMore: 'Read',
readTimeSuffix: 'min',
items: [
{
slug: 'rag-eval-framework',
category: 'LLM',
title: 'A RAG evaluation framework that holds up in production',
excerpt:
'Why BLEU and ROUGE fall short for RAG, and the metrics that actually drive decisions in real projects.',
readTime: 8,
},
{
slug: 'agentic-n8n-patterns',
category: 'Automation',
title: 'Agentic patterns with n8n for the enterprise',
excerpt:
'How to combine n8n with LangGraph to build auditable, debuggable autonomous workflows.',
readTime: 11,
},
{
slug: 'vertex-cost-control',
category: 'Google Stack',
title: 'Vertex AI cost control at scale',
excerpt:
'Three anti-patterns I see in 80% of Vertex projects — and how we cut 60% of monthly spend.',
readTime: 6,
},
{
slug: 'k8s-llm-inference',
category: 'Infra',
title: 'Sub-50ms LLM inference on Kubernetes',
excerpt:
'Deployment pattern with KEDA, GPU sharing, and request hedging for stable serving.',
readTime: 14,
},
{
slug: 'flutter-on-device-ai',
category: 'Mobile',
title: 'On-device AI in Flutter',
excerpt:
'Using Gemini Nano and LiteRT for offline inference inside mobile apps.',
readTime: 9,
},
{
slug: 'enterprise-ai-roadmap',
category: 'Strategy',
title: 'A 90-day enterprise AI roadmap',
excerpt:
'The framework I build for CTOs — from use-case discovery to first production deployment.',
readTime: 7,
},
],
},
portfolio: {
eyebrow: 'Selected work',
title: 'Systems that run in production',
sub:
'A selection of real engagements — from RAG pipelines to event-driven data meshes. Tap any card for the gallery and the architecture behind it.',
labels: {
role: 'Role',
year: 'Year',
client: 'Client',
stack: 'Stack',
view: 'View project',
gallery: 'Gallery',
close: 'Close',
next: 'Next',
prev: 'Previous',
},
items: [
{
id: 'atlas-rag',
title: 'Atlas — Enterprise RAG Platform',
client: 'Tier-1 bank',
year: '2025',
role: 'Lead AI Engineer',
summary:
'A knowledge assistant over 4M+ internal documents — hybrid retrieval with pgvector and a reranker, a bespoke evaluation harness, and sub-40ms serving on Vertex AI.',
accent: 'electric',
tags: ['RAG', 'pgvector', 'Vertex AI', 'Eval'],
metrics: [
{ value: '4M+', label: 'docs indexed' },
{ value: '38ms', label: 'p95 latency' },
{ value: '92%', label: 'answer accuracy' },
],
cover: '/portfolio/atlas-rag/cover.svg',
gallery: [
'/portfolio/atlas-rag/01.svg',
'/portfolio/atlas-rag/02.svg',
'/portfolio/atlas-rag/03.svg',
],
},
{
id: 'sentinel-agents',
title: 'Sentinel — Agentic Ops Automation',
client: 'SaaS scale-up',
year: '2025',
role: 'Solution Architect',
summary:
'Autonomous incident response combining n8n and LangGraph — auditable agents that triage alerts, find root cause, and self-heal where it is safe to do so.',
accent: 'violet',
tags: ['n8n', 'LangGraph', 'Agents', 'Observability'],
metrics: [
{ value: '70%', label: 'MTTR reduction' },
{ value: '24/7', label: 'on-call coverage' },
{ value: '150+', label: 'automated flows' },
],
cover: '/portfolio/sentinel-agents/cover.svg',
gallery: [
'/portfolio/sentinel-agents/01.svg',
'/portfolio/sentinel-agents/02.svg',
'/portfolio/sentinel-agents/03.svg',
],
},
{
id: 'vertex-vision',
title: 'Vertex Vision — Realtime Vision Inference',
client: 'Retail chain',
year: '2024',
role: 'AI Engineer',
summary:
'Real-time vision inference on GKE with Triton and Vertex AI for shelf analytics and customer flow across hundreds of stores, autoscaled off a work queue.',
accent: 'cyan',
tags: ['Vertex AI', 'GKE', 'Triton', 'Computer Vision'],
metrics: [
{ value: '1.2B', label: 'inferences / mo' },
{ value: '300+', label: 'stores' },
{ value: '60%', label: 'GPU cost cut' },
],
cover: '/portfolio/vertex-vision/cover.svg',
gallery: [
'/portfolio/vertex-vision/01.svg',
'/portfolio/vertex-vision/02.svg',
'/portfolio/vertex-vision/03.svg',
],
},
{
id: 'mirage-mobile',
title: 'Mirage — On-device AI Suite',
client: 'Consumer product',
year: '2024',
role: 'Mobile + AI Lead',
summary:
'A Flutter app with fully offline inference via Gemini Nano and LiteRT — streaming response UX with zero network dependency and privacy preserved end to end.',
accent: 'magenta',
tags: ['Flutter', 'Gemini Nano', 'LiteRT', 'On-device'],
metrics: [
{ value: '0', label: 'network deps' },
{ value: '<80ms', label: 'response' },
{ value: '4.8★', label: 'user rating' },
],
cover: '/portfolio/mirage-mobile/cover.svg',
gallery: [
'/portfolio/mirage-mobile/01.svg',
'/portfolio/mirage-mobile/02.svg',
'/portfolio/mirage-mobile/03.svg',
],
},
{
id: 'flux-stream',
title: 'Flux — Event-Driven Data Mesh',
client: 'Logistics platform',
year: '2023',
role: 'Platform Architect',
summary:
'A streaming backbone on Kafka and NATS over Kubernetes — 40+ microservices with resilience patterns, end-to-end tracing, and exactly-once delivery.',
accent: 'emerald',
tags: ['Kafka', 'NATS', 'Kubernetes', 'Go'],
metrics: [
{ value: '40+', label: 'microservices' },
{ value: '2M/s', label: 'events / sec' },
{ value: '99.9%', label: 'uptime' },
],
cover: '/portfolio/flux-stream/cover.svg',
gallery: [
'/portfolio/flux-stream/01.svg',
'/portfolio/flux-stream/02.svg',
'/portfolio/flux-stream/03.svg',
],
},
{
id: 'oracle-forecast',
title: 'Oracle — Demand Forecasting Engine',
client: 'Supply chain',
year: '2023',
role: 'ML Engineer',
summary:
'A time-series forecasting pipeline on BigQuery and dbt with automated retraining — sharply reduced inventory waste and improved supply planning accuracy.',
accent: 'electric',
tags: ['Forecasting', 'BigQuery', 'dbt', 'MLOps'],
metrics: [
{ value: '23%', label: 'waste reduction' },
{ value: '89%', label: 'forecast accuracy' },
{ value: 'daily', label: 'retraining' },
],
cover: '/portfolio/oracle-forecast/cover.svg',
gallery: [
'/portfolio/oracle-forecast/01.svg',
'/portfolio/oracle-forecast/02.svg',
'/portfolio/oracle-forecast/03.svg',
],
},
],
},
contact: {
eyebrow: 'Contact',
title: 'Book a 30-minute call',
sub:
'No cost, no commitment. We map the use case, the constraints, and the next step together.',
fields: {
name: 'Name',
company: 'Company',
service: 'Service',
budget: 'Budget (rough)',
message: 'Message',
},
placeholders: {
name: 'Full name',
company: 'Organization',
message: 'Goal, timeline, current blockers…',
},
budgets: ['Under $10k', '$10k$50k', '$50k$200k', '$200k+'],
submit: 'Send request',
note: 'Typical reply within 24 working hours.',
},
footer: {
tagline: 'Designed in Tehran · Built for the enterprise',
rights: '© 2026 Soroush Asadi. All rights reserved.',
},
},
} as const;
export type Dict = typeof dict.en;
+95
View File
@@ -0,0 +1,95 @@
'use client';
import {
createContext,
useContext,
useEffect,
useMemo,
useState,
type ReactNode,
} from 'react';
import { DEFAULT_LOCALE, dict, type Dict, type Locale } from './dictionaries';
type Direction = 'rtl' | 'ltr';
type Ctx = {
locale: Locale;
dir: Direction;
t: Dict;
setLocale: (l: Locale) => void;
toggle: () => void;
};
const LocaleContext = createContext<Ctx | null>(null);
const STORAGE_KEY = 'sa.locale';
function dirFor(locale: Locale): Direction {
return locale === 'fa' ? 'rtl' : 'ltr';
}
export function LocaleProvider({
initialLocale,
content,
children,
}: {
initialLocale?: Locale;
/**
* Server-resolved content (dict defaults merged with admin overrides).
* When omitted we fall back to the in-code dictionary, so the provider keeps
* working in isolation (tests, storybook, etc.).
*/
content?: { fa: Dict; en: Dict };
children: ReactNode;
}) {
const [locale, setLocaleState] = useState<Locale>(initialLocale ?? DEFAULT_LOCALE);
const source = content ?? (dict as unknown as { fa: Dict; en: Dict });
// Hydrate from localStorage on the client.
useEffect(() => {
try {
const saved = window.localStorage.getItem(STORAGE_KEY) as Locale | null;
if (saved === 'fa' || saved === 'en') {
setLocaleState(saved);
}
} catch {
/* noop */
}
}, []);
// Reflect locale + direction on the html element without a reload.
useEffect(() => {
const html = document.documentElement;
html.lang = locale;
html.dir = dirFor(locale);
html.dataset.locale = locale;
}, [locale]);
const setLocale = (l: Locale) => {
setLocaleState(l);
try {
window.localStorage.setItem(STORAGE_KEY, l);
} catch {
/* noop */
}
};
const value = useMemo<Ctx>(
() => ({
locale,
dir: dirFor(locale),
t: source[locale],
setLocale,
toggle: () => setLocale(locale === 'fa' ? 'en' : 'fa'),
}),
[locale, source],
);
return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>;
}
export function useLocale() {
const ctx = useContext(LocaleContext);
if (!ctx) throw new Error('useLocale must be used inside <LocaleProvider>');
return ctx;
}