4c759851ce
deploy / deploy (push) Successful in 24s
Replace the flat minimal sections with a bento layout (ui-ux-pro-max "Bento Box Grid" style) while keeping the light theme and single blue accent. - Bento grid system in CSS: 4-col -> 2-col -> 1-col, varied spans (span-2, row-2), 22px tiles, hover lift, dark/accent/tint tile variants - Hero is now a bento: dark name/anchor tile + value-prop tile + accent availability tile + social tile - Services: bento tiles with a tinted featured tile and a dark AI tile - Stack: four category tiles (AI/ML tinted) - Portfolio: featured 2x2 tile + colored covers per project - Pipeline / expertise / blog / contact kept as different layouts for rhythm Verified: 4-col desktop, clean 1-col mobile with no horizontal overflow, no console errors. Tailwind bundle rebuilt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
400 lines
31 KiB
Plaintext
400 lines
31 KiB
Plaintext
@page
|
|
@model SoroushAsadi.Pages.IndexModel
|
|
@{
|
|
var fa = Model.IsFa;
|
|
var locale = Model.Locale;
|
|
}
|
|
|
|
<!-- ─── HERO (bento) ─────────────────────────────────────────────────── -->
|
|
<section id="top" class="px-5 pt-24 pb-12 sm:px-8 sm:pt-28">
|
|
<div class="mx-auto max-w-6xl">
|
|
<div class="bento">
|
|
|
|
<!-- Name / anchor tile -->
|
|
<div class="tile tile-dark span-2 row-2 reveal">
|
|
<span class="kicker @(fa ? "font-fa" : "")" style="color:#a1a1aa">@(fa ? "مهندس نرمافزار و هوش مصنوعی" : "Software & AI Engineer")</span>
|
|
<h1 class="mt-3 @(fa ? "font-fa" : "")" style="font-size:clamp(2.4rem,5.5vw,4rem)">@(fa ? "سروش اسعدی" : "Soroush Asadi")</h1>
|
|
<p class="t-sub mt-3 text-[1rem] @(fa ? "font-fa" : "")">@(fa ? "معمار سیستم. از ایده تا اجرا." : "Solution architect. From idea to production.")</p>
|
|
<div class="mt-auto flex flex-wrap gap-3 pt-8">
|
|
<a href="#contact" class="btn">
|
|
@(fa ? "رزرو جلسه" : "Book a call")
|
|
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" class="@(fa ? "rotate-180" : "")" aria-hidden="true"><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></svg>
|
|
</a>
|
|
<a href="#portfolio" class="btn-ghost btn-on-dark">@(fa ? "نمونهکارها" : "View work")</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Value-prop tile -->
|
|
<div class="tile span-2 reveal" style="transition-delay:.06s">
|
|
<p class="mt-auto text-balance leading-snug text-zinc-800 @(fa ? "font-fa" : "")" style="font-size:clamp(1.15rem,2vw,1.5rem)">
|
|
@(fa ? "نرمافزار، اپلیکیشنهای سازمانی و " : "I build software, enterprise apps, and ")<span class="accent-text font-semibold">@(fa ? "راهکارهای هوش مصنوعی" : "AI solutions")</span>@(fa ? " میسازم که در عمل و در مقیاس واقعی کار میکنند." : " that hold up in production, at real scale.")
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Availability tile -->
|
|
<div class="tile tile-accent reveal" style="transition-delay:.12s">
|
|
<span class="inline-flex items-center gap-2 text-[.82rem]" style="color:rgba(255,255,255,.9)"><span style="width:7px;height:7px;border-radius:99px;background:#fff;display:inline-block"></span>@(fa ? "وضعیت" : "Status")</span>
|
|
<p class="mt-auto pt-6 text-[1.05rem] font-semibold @(fa ? "font-fa" : "")" style="color:#fff">@(fa ? "پذیرای پروژههای جدید" : "Open for new projects")</p>
|
|
</div>
|
|
|
|
<!-- Social tile -->
|
|
<div class="tile reveal" style="transition-delay:.18s">
|
|
<span class="kicker @(fa ? "font-fa" : "")">@(fa ? "ارتباط" : "Connect")</span>
|
|
<div class="mt-auto flex items-center gap-2.5 pt-6">
|
|
<a class="social" href="https://www.linkedin.com/in/soroushdes/" target="_blank" rel="noopener" aria-label="LinkedIn"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M4.98 3.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5ZM3 9h4v12H3V9Zm6 0h3.8v1.64h.05c.53-1 1.83-2.06 3.76-2.06 4.02 0 4.76 2.65 4.76 6.1V21h-4v-5.4c0-1.29-.02-2.95-1.8-2.95-1.8 0-2.07 1.4-2.07 2.85V21H9V9Z"/></svg></a>
|
|
<a class="social" href="https://www.instagram.com/soroushasadicom/" target="_blank" rel="noopener" aria-label="Instagram"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.2" cy="6.8" r="1.1" fill="currentColor" stroke="none"/></svg></a>
|
|
<a class="social" href="mailto:code.soroush@gmail.com" aria-label="Email"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/></svg></a>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ─── SERVICES (text-block grid) ───────────────────────────────────── -->
|
|
<section id="services" class="px-5 py-24 sm:px-8 sm:py-28">
|
|
<div class="mx-auto max-w-6xl">
|
|
<div class="sec-head">
|
|
<h2>@(fa ? "شش کاری که انجام میدهم" : "Six areas of practice")</h2>
|
|
<p class="lede">@(fa ? "از همان جلسهی اول تا وقتی محصول روی پای خودش میایستد، کنارتان هستم؛ در تمام مسیر مهندسی و محصول." : "From the first idea to production rollout, one engineering partner across the whole product.")</p>
|
|
</div>
|
|
|
|
<div class="bento">
|
|
@{
|
|
var services = fa ? new[]{
|
|
("apps","اپلیکیشنهای وب و سازمانی","پلتفرمهای وب و SaaS از صفر تا صد: داشبورد، چندمستاجری، صورتحساب و پنل مدیریت، ساختهشده برای رشد.",new[]{"Web","SaaS","Dashboards"}),
|
|
("mobile","اپلیکیشنهای موبایل","اپهای بومی و چندسکویی با Flutter، Swift و Kotlin، با حسی روان و نزدیک به تجربهی بومی.",new[]{"Flutter","Swift","Kotlin"}),
|
|
("architecture","معماری راهکار و زیرساخت ابری","سیستمهای توزیعشده روی Kubernetes؛ میکروسرویس، استریم رویداد، و پایداری زیر بار سنگین.",new[]{"K8s","Microservices","Cloud"}),
|
|
("llm-rag","راهکارهای هوش مصنوعی","قابلیتهای LLM و RAG، عاملها و اتوماسیون که داخل محصول واقعی کار میکنند، نه فقط دمو.",new[]{"LLM","RAG","Agents"}),
|
|
("automation","اتوماسیون و یکپارچهسازی","ابزارهایتان را به هم وصل میکنم و کارهای دستی را حذف؛ با گردشکارهای n8n، API و وبهوک.",new[]{"n8n","APIs","Webhooks"}),
|
|
("strategy","راهبرد و نقشهی راه","راهبرد فنی، بازبینی معماری، و نقشهی راهی روشن از ایده تا عرضه.",new[]{"Discovery","Architecture","Roadmap"}),
|
|
} : new[]{
|
|
("apps","Web & enterprise apps","End-to-end web platforms and SaaS: dashboards, multi-tenant, billing, and admin, built to scale.",new[]{"Web","SaaS","Dashboards"}),
|
|
("mobile","Mobile apps","Native and cross-platform apps with Flutter, Swift, and Kotlin, with a smooth native feel.",new[]{"Flutter","Swift","Kotlin"}),
|
|
("architecture","Solution architecture & cloud","Distributed systems on Kubernetes: microservices, event streaming, and resilience at scale.",new[]{"K8s","Microservices","Cloud"}),
|
|
("llm-rag","AI solutions","LLM and RAG features, agents, and automation built into real products, not just demos.",new[]{"LLM","RAG","Agents"}),
|
|
("automation","Automation & integrations","Connect your tools and remove manual work with n8n workflows, APIs, and webhooks.",new[]{"n8n","APIs","Webhooks"}),
|
|
("strategy","Strategy & roadmap","Technical strategy, architecture review, and a clear roadmap from idea to launch.",new[]{"Discovery","Architecture","Roadmap"}),
|
|
};
|
|
}
|
|
@{ int si = 0; }
|
|
@foreach (var (id, title, desc, tags) in services)
|
|
{
|
|
var (spanCls, variant) = id switch {
|
|
"apps" => ("span-2", "tile-tint"),
|
|
"llm-rag" => ("span-2", "tile-dark"),
|
|
_ => ("", ""),
|
|
};
|
|
var descCls = variant == "tile-dark" ? "t-sub" : "text-zinc-600";
|
|
<article class="tile reveal @spanCls @variant" style="transition-delay:@(si * 60)ms">
|
|
<span class="tile-icon" aria-hidden="true">@Html.Raw(ServiceIcon(id))</span>
|
|
<h3 class="mt-4 text-lg font-semibold @(fa ? "font-fa" : "")">@title</h3>
|
|
<p class="mt-2.5 text-[.93rem] leading-relaxed @descCls">@desc</p>
|
|
<div class="mt-auto flex flex-wrap gap-1.5 pt-5">
|
|
@foreach (var tag in tags) { <span class="chip">@tag</span> }
|
|
</div>
|
|
</article>
|
|
si++;
|
|
}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ─── PIPELINE (horizontal stepper) ────────────────────────────────── -->
|
|
<section id="dataflow" class="px-5 py-24 sm:px-8 sm:py-28">
|
|
<div class="mx-auto max-w-6xl">
|
|
<div class="sec-head">
|
|
<h2>@(fa ? "از سند خام تا پاسخ قابل اتکا" : "From raw document to a trustworthy answer")</h2>
|
|
<p class="lede">@(fa ? "مسیری که هر پرسش در یک سامانهی RAG واقعی طی میکند. هر مرحله را میشود اندازه گرفت، دنبال کرد و برای سرعت بهتر کرد." : "The path every query takes through a production RAG system. Each stage is measurable, auditable, and tuned for latency.")</p>
|
|
</div>
|
|
|
|
<ol class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-3 lg:grid-cols-5">
|
|
@{
|
|
var nodes = fa ? new[]{
|
|
("دریافت","نرمالسازی، تکهتکهکردن و پاکسازی سندهای منبع"),
|
|
("برداریسازی","ساخت embedding و نمایهکردن در پایگاه برداری"),
|
|
("بازیابی","جستجوی ترکیبی معنایی و کلیدواژهای"),
|
|
("بازرتبهبندی","چیدن دوبارهی نتایج با cross-encoder"),
|
|
("تولید","پاسخ مستند همراه با ذکر منبع"),
|
|
} : new[]{
|
|
("Ingest","Normalize, chunk, and clean source documents"),
|
|
("Embed","Generate embeddings and index in the vector store"),
|
|
("Retrieve","Hybrid semantic and keyword search"),
|
|
("Rerank","Re-order candidates with a cross-encoder"),
|
|
("Generate","Grounded answer with source citations"),
|
|
};
|
|
int stepN = 0;
|
|
}
|
|
@foreach (var (nlabel, ndesc) in nodes)
|
|
{
|
|
stepN++;
|
|
<li class="reveal border-t border-zinc-200 pt-4" style="transition-delay:@((stepN-1) * 40)ms">
|
|
<span class="font-display text-sm text-zinc-500">@stepN.ToString("D2")</span>
|
|
<h3 class="mt-2 text-base font-semibold @(fa ? "font-fa" : "")">@nlabel</h3>
|
|
<p class="mt-1.5 text-[.85rem] leading-relaxed text-zinc-600">@ndesc</p>
|
|
</li>
|
|
}
|
|
</ol>
|
|
<p class="mt-8 text-sm text-zinc-500">@(fa ? "تأخیر کل زیر ۵۰ میلیثانیه؛ هر مرحله قابل مشاهده." : "Sub-50ms end-to-end, every stage observable.")</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ─── STACK (grouped tag clusters) ─────────────────────────────────── -->
|
|
<section id="stack" class="px-5 py-24 sm:px-8 sm:py-28">
|
|
<div class="mx-auto max-w-6xl">
|
|
<div class="sec-head">
|
|
<h2>@(fa ? "ابزار روزمره" : "Daily tooling")</h2>
|
|
<p class="lede">@(fa ? "هر چیزی که میسازم روی اینها بنا میشود؛ انتخابشان کردهام چون میمانند، نه چون مد روزند." : "Everything I ship sits on this foundation, chosen for longevity, not hype cycles.")</p>
|
|
</div>
|
|
|
|
<div class="bento">
|
|
@{
|
|
var cats = fa ? new[]{
|
|
("زبانها", new[]{"Python","TypeScript","Go","Rust","SQL"}),
|
|
("موبایل", new[]{"Flutter","Swift / SwiftUI","Kotlin","React Native"}),
|
|
("زیرساخت", new[]{"Kubernetes","Terraform","Postgres","Redis","Kafka","NATS"}),
|
|
("هوش مصنوعی", new[]{"Vertex AI","Gemini","OpenAI","Anthropic","LangGraph","Pinecone","pgvector"}),
|
|
} : new[]{
|
|
("Languages", new[]{"Python","TypeScript","Go","Rust","SQL"}),
|
|
("Mobile", new[]{"Flutter","Swift / SwiftUI","Kotlin","React Native"}),
|
|
("Infrastructure",new[]{"Kubernetes","Terraform","Postgres","Redis","Kafka","NATS"}),
|
|
("AI / ML", new[]{"Vertex AI","Gemini","OpenAI","Anthropic","LangGraph","Pinecone","pgvector"}),
|
|
};
|
|
}
|
|
@{ int ci = 0; }
|
|
@foreach (var (catLabel, items) in cats)
|
|
{
|
|
<div class="tile reveal @(ci == 3 ? "tile-tint" : "")" style="transition-delay:@(ci * 60)ms">
|
|
<h3 class="text-sm font-semibold @(fa ? "font-fa" : "")">@catLabel</h3>
|
|
<div class="mt-4 flex flex-wrap gap-1.5">
|
|
@foreach (var item in items) { <span class="chip">@item</span> }
|
|
</div>
|
|
</div>
|
|
ci++;
|
|
}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ─── EXPERTISE (definition list) ──────────────────────────────────── -->
|
|
<section id="expertise" class="px-5 py-24 sm:px-8 sm:py-28">
|
|
<div class="mx-auto max-w-4xl">
|
|
<div class="sec-head">
|
|
<h2>@(fa ? "جاهایی که عمیق شدهام" : "What I go deep on")</h2>
|
|
<p class="lede">@(fa ? "سامانههایی که روزانه میلیونها رویداد را تاب میآورند. اینها همان چیزهاییاند که سالها رویشان کار کردهام." : "Systems that survive millions of events per day. These are the areas I optimize for.")</p>
|
|
</div>
|
|
|
|
<dl>
|
|
@{
|
|
var areas = fa ? new[]{
|
|
("معماری نرمافزار و سیستمهای توزیعشده","میکروسرویس، استریم رویداد و الگوهای پایداری زیر بار سنگین."),
|
|
("اپلیکیشنهای وب و سازمانی","پلتفرمهای چندمستاجری، داشبورد و سیستمهای پرترافیک."),
|
|
("راهکارهای هوش مصنوعی (LLM و RAG)","بازیابی، ارزیابی و تولید پاسخ مستند، داخل محصول واقعی."),
|
|
("زیرساخت ابری و Kubernetes","استقرار، مقیاسپذیری خودکار و حواسجمعی روی هزینه."),
|
|
("موبایل بومی و چندسکویی","Flutter، Swift و Kotlin برای اپهای روان و سریع."),
|
|
} : new[]{
|
|
("Software architecture & distributed systems","Microservices, event streaming, and resilience patterns at scale."),
|
|
("Web & enterprise applications","Multi-tenant platforms, dashboards, and high-traffic systems."),
|
|
("AI solutions (LLM & RAG)","Retrieval, evals, and grounded generation, inside real products."),
|
|
("Cloud infrastructure & Kubernetes","Deployment, autoscaling, and real cost discipline."),
|
|
("Native & cross-platform mobile","Flutter, Swift, and Kotlin for smooth, fast apps."),
|
|
};
|
|
}
|
|
@foreach (var (alabel, adesc) in areas)
|
|
{
|
|
<div class="reveal grid grid-cols-1 gap-1 border-t border-zinc-200 py-5 sm:grid-cols-[1fr_1.5fr] sm:gap-8">
|
|
<dt class="text-base font-semibold @(fa ? "font-fa" : "")">@alabel</dt>
|
|
<dd class="text-[.95rem] leading-relaxed text-zinc-600">@adesc</dd>
|
|
</div>
|
|
}
|
|
</dl>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ─── PORTFOLIO (card grid, typographic covers) ────────────────────── -->
|
|
<section id="portfolio" class="px-5 py-24 sm:px-8 sm:py-28">
|
|
<div class="mx-auto max-w-6xl">
|
|
<div class="sec-head">
|
|
<h2>@(fa ? "نمونهکارهای منتخب" : "Selected work")</h2>
|
|
<p class="lede">@(fa ? "محصولاتی که خودم طراحی و ساختهام. روی هر کارت بزنید تا خودِ سایت را ببینید." : "Products I have designed and built. Tap any card to open the live site.")</p>
|
|
</div>
|
|
|
|
<div class="bento">
|
|
@{
|
|
var projects = fa ? new[]{
|
|
("hamkadr","همکادر","hamkadr.ir","بازاری که کادر درمان را برای شیفت و استخدام به بیمارستانها و کلینیکها وصل میکند؛ با پروفایل، فیلتر، تقویم هفتگی و اپ موبایل.",new[]{"Marketplace","Healthcare","Mobile"}),
|
|
("meezi","میزی","meezi.ir","سامانهی یکپارچه برای کافه و رستوران: سفارش با QR، صندوق فروش، انبار، کارکنان و تحلیل فروش، روی زیرساخت داخلی.",new[]{"SaaS","POS","Analytics"}),
|
|
("bargevasat","برگ وسط","bargevasat.ir","بازی آنلاین حکم بهصورت بلادرنگ مقابل بازیکنان واقعی یا رباتهای هوشمند؛ با لیگ، رتبهبندی، جایزهی روزانه و همگامسازی چنددستگاهه.",new[]{"Realtime","Multiplayer","Game"}),
|
|
("flatrender","فلترندر","flatrender.ir","استودیوی هوش مصنوعی که بیش از ۱۲۰۰ قالب را در چند دقیقه به ویدیو و تصویر آمادهی انتشار تبدیل میکند؛ بر پایهی ثانیهی رندر. در نسخهی بتا.",new[]{"AI","Video","SaaS"}),
|
|
} : new[]{
|
|
("hamkadr","Hamkadr","hamkadr.ir","A marketplace connecting healthcare staff with hospitals and clinics for shifts and hiring, with profiles, filters, weekly scheduling, and a mobile app.",new[]{"Marketplace","Healthcare","Mobile"}),
|
|
("meezi","Meezi","meezi.ir","An all-in-one SaaS for cafes and restaurants: QR ordering, POS, inventory, staff, and sales analytics, hosted in Iran.",new[]{"SaaS","POS","Analytics"}),
|
|
("bargevasat","Barge Vasat","bargevasat.ir","A real-time multiplayer Hokm card game against people or AI bots, with leagues, rankings, daily rewards, and cross-device play.",new[]{"Realtime","Multiplayer","Game"}),
|
|
("flatrender","Flatrender","flatrender.ir","An AI studio that turns 1,200+ templates into platform-ready videos and images in minutes, billed by render-seconds. In beta.",new[]{"AI","Video","SaaS"}),
|
|
};
|
|
}
|
|
@{ int pi = 0; }
|
|
@foreach (var (pid, pname, pdomain, pdesc, ptags) in projects)
|
|
{
|
|
var initial = char.ToUpperInvariant(pid[0]);
|
|
var (spanCls, coverBg, coverFg) = pi switch {
|
|
0 => ("span-2 row-2", "#18181b", "#fafafa"),
|
|
1 => ("span-2", "#2563eb", "#ffffff"),
|
|
2 => ("", "#eff4ff", "#2563eb"),
|
|
_ => ("", "#f4f4f5", "#a1a1aa"),
|
|
};
|
|
<a href="https://@pdomain" target="_blank" rel="noopener" aria-label="@pname"
|
|
class="group tile tile-link reveal @spanCls" style="padding:0;transition-delay:@(pi * 60)ms">
|
|
<div class="pcover" style="background:@coverBg;@(pi == 0 ? "min-height:210px" : "min-height:104px")">
|
|
<span class="font-display font-bold" style="font-size:@(pi == 0 ? "5rem" : "2.6rem");color:@coverFg">@initial</span>
|
|
</div>
|
|
<div class="flex flex-1 flex-col p-5">
|
|
<div class="mb-3 flex flex-wrap gap-1.5">
|
|
@foreach (var tag in ptags) { <span class="chip">@tag</span> }
|
|
</div>
|
|
<h3 class="text-[1.1rem] font-semibold @(fa ? "font-fa" : "")">@pname</h3>
|
|
<p class="mt-1 text-[.78rem] text-zinc-500" dir="ltr">@pdomain</p>
|
|
<p class="mt-2.5 text-[.88rem] leading-relaxed text-zinc-600 @(pi == 0 ? "" : "line-clamp-3")">@pdesc</p>
|
|
<span class="arrow-link mt-auto pt-4">
|
|
@(fa ? "مشاهدهی سایت" : "Visit site")
|
|
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 17 17 7"/><path d="M8 7h9v9"/></svg>
|
|
</span>
|
|
</div>
|
|
</a>
|
|
pi++;
|
|
}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ─── BLOG (editorial list) ────────────────────────────────────────── -->
|
|
<section id="blog" class="px-5 py-24 sm:px-8 sm:py-28">
|
|
<div class="mx-auto max-w-4xl">
|
|
<div class="sec-head">
|
|
<h2>@(fa ? "یادداشتهای مهندسی" : "Engineering notes")</h2>
|
|
<p class="lede">@(fa ? "درسهایی از پروژههای واقعی. نه ترجمهی مقاله، نه شعار توخالی." : "Findings from real engagements. Not translated articles, not hype lists.")</p>
|
|
</div>
|
|
|
|
<div class="border-b border-zinc-200">
|
|
@{
|
|
var posts = fa ? new[]{
|
|
("rag-eval-framework","LLM","چارچوب ارزیابی RAG که در عمل جواب میدهد","چرا BLEU و ROUGE برای RAG کافی نیستند، و معیارهایی که واقعاً به تصمیم کمک میکنند.",8),
|
|
("agentic-n8n-patterns","Automation","الگوهای عاملمحور با n8n برای سازمان","چطور n8n را با LangGraph ترکیب کنیم تا گردشکارهای خودکار و قابلردیابی بسازیم.",11),
|
|
("vertex-cost-control","Google Stack","کنترل هزینه روی Vertex AI در مقیاس بالا","سه اشتباه رایج که در بیشتر پروژههای Vertex میبینم، و اینکه چطور ۶۰٪ هزینه را کم کردیم.",6),
|
|
("k8s-llm-inference","Infra","اجرای LLM روی Kubernetes با تأخیر زیر ۵۰ میلیثانیه","الگوی استقرار با KEDA، اشتراک GPU و request hedging برای سرویسدهی پایدار.",14),
|
|
("flutter-on-device-ai","Mobile","هوش مصنوعی روی دستگاه در Flutter","استفاده از Gemini Nano و LiteRT برای پردازش آفلاین در اپهای موبایل.",9),
|
|
("enterprise-ai-roadmap","Strategy","نقشهی راه هوش مصنوعی سازمانی در ۹۰ روز","چارچوبی که برای مدیران فنی میچینم؛ از پیدا کردن بهترین ایده تا اولین اجرای واقعی.",7),
|
|
} : new[]{
|
|
("rag-eval-framework","LLM","A RAG evaluation framework that holds up in production","Why BLEU and ROUGE fall short for RAG, and the metrics that actually drive decisions in real projects.",8),
|
|
("agentic-n8n-patterns","Automation","Agentic patterns with n8n for the enterprise","How to combine n8n with LangGraph to build auditable, debuggable autonomous workflows.",11),
|
|
("vertex-cost-control","Google Stack","Vertex AI cost control at scale","Three anti-patterns I see in 80% of Vertex projects, and how we cut 60% of monthly spend.",6),
|
|
("k8s-llm-inference","Infra","Sub-50ms LLM inference on Kubernetes","Deployment pattern with KEDA, GPU sharing, and request hedging for stable serving.",14),
|
|
("flutter-on-device-ai","Mobile","On-device AI in Flutter","Using Gemini Nano and LiteRT for offline inference inside mobile apps.",9),
|
|
("enterprise-ai-roadmap","Strategy","A 90-day enterprise AI roadmap","The framework I build for CTOs, from use-case discovery to first production deployment.",7),
|
|
};
|
|
}
|
|
@foreach (var (slug, cat, btitle, excerpt, readTime) in posts)
|
|
{
|
|
<a href="/blog/@slug" class="group reveal grid grid-cols-1 gap-2 border-t border-zinc-200 py-6 sm:grid-cols-[8rem_1fr] sm:gap-8">
|
|
<div class="flex items-baseline justify-between sm:flex-col sm:gap-1">
|
|
<span class="kicker">@cat</span>
|
|
<span class="text-[.78rem] text-zinc-500">@readTime @(fa ? "دقیقه" : "min")</span>
|
|
</div>
|
|
<div>
|
|
<h3 class="text-[1.1rem] font-semibold transition-colors group-hover:text-accent @(fa ? "font-fa" : "")">@btitle</h3>
|
|
<p class="mt-1.5 text-[.9rem] leading-relaxed text-zinc-600">@excerpt</p>
|
|
<span class="arrow-link mt-3">
|
|
@(fa ? "خواندن" : "Read")
|
|
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="@(fa ? "rotate-180" : "")" aria-hidden="true"><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></svg>
|
|
</span>
|
|
</div>
|
|
</a>
|
|
}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ─── CONTACT ──────────────────────────────────────────────────────── -->
|
|
<section id="contact" class="px-5 py-24 sm:px-8 sm:py-28">
|
|
<div class="mx-auto max-w-2xl">
|
|
<div class="sec-head">
|
|
<h2>@(fa ? "رزرو یک جلسهی ۳۰ دقیقهای" : "Book a 30-minute call")</h2>
|
|
<p class="lede">@(fa ? "بدون هزینه، بدون تعهد. با هم میبینیم چه میخواهید، چه محدودیتهایی هست، و قدم بعد چیست." : "No cost, no commitment. We map the use case, the constraints, and the next step together.")</p>
|
|
</div>
|
|
|
|
<form id="contact-form" class="card space-y-5 p-6 sm:p-8"
|
|
data-success-msg="@(fa ? "پیام رسید! معمولاً ظرف ۲۴ ساعت کاری جواب میدهم." : "Sent. Typical reply within 24 working hours.")"
|
|
data-error-msg="@(fa ? "یک مشکلی پیش آمد. لطفاً دوباره تلاش کنید." : "Something went wrong. Please try again.")">
|
|
<input type="hidden" name="locale" value="@locale" />
|
|
|
|
<div class="grid grid-cols-1 gap-5 sm:grid-cols-2">
|
|
<div>
|
|
<label class="flabel" for="name">@(fa ? "نام" : "Name")<span class="text-red-600" aria-hidden="true"> *</span></label>
|
|
<input id="name" name="name" type="text" required autocomplete="name" placeholder="@(fa ? "نام و نام خانوادگی" : "Full name")" class="field" />
|
|
</div>
|
|
<div>
|
|
<label class="flabel" for="company">@(fa ? "سازمان" : "Company")</label>
|
|
<input id="company" name="company" type="text" autocomplete="organization" placeholder="@(fa ? "نام سازمان" : "Organization")" class="field" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 gap-5 sm:grid-cols-2">
|
|
<div>
|
|
<label class="flabel" for="service">@(fa ? "خدمت" : "Service")<span class="text-red-600" aria-hidden="true"> *</span></label>
|
|
<select id="service" name="service" required class="field">
|
|
<option value="" disabled selected>@(fa ? "انتخاب کنید" : "Select…")</option>
|
|
@if (fa)
|
|
{
|
|
<option value="apps">اپلیکیشن وب و سازمانی</option>
|
|
<option value="mobile">اپلیکیشن موبایل</option>
|
|
<option value="architecture">معماری و زیرساخت ابری</option>
|
|
<option value="ai">راهکار هوش مصنوعی</option>
|
|
<option value="automation">اتوماسیون و یکپارچهسازی</option>
|
|
<option value="strategy">راهبرد و نقشهی راه</option>
|
|
}
|
|
else
|
|
{
|
|
<option value="apps">Web & enterprise apps</option>
|
|
<option value="mobile">Mobile apps</option>
|
|
<option value="architecture">Solution architecture & cloud</option>
|
|
<option value="ai">AI solutions</option>
|
|
<option value="automation">Automation & integrations</option>
|
|
<option value="strategy">Strategy & roadmap</option>
|
|
}
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="flabel" for="budget">@(fa ? "بودجه (تقریبی)" : "Budget (rough)")<span class="text-red-600" aria-hidden="true"> *</span></label>
|
|
<select id="budget" name="budget" required class="field">
|
|
<option value="" disabled selected>@(fa ? "انتخاب کنید" : "Select…")</option>
|
|
<option value="under-10k">@(fa ? "زیر ۱۰ هزار دلار" : "Under $10k")</option>
|
|
<option value="10-50k">@(fa ? "۱۰ تا ۵۰ هزار دلار" : "$10k - $50k")</option>
|
|
<option value="50-200k">@(fa ? "۵۰ تا ۲۰۰ هزار دلار" : "$50k - $200k")</option>
|
|
<option value="200k-plus">@(fa ? "بیش از ۲۰۰ هزار دلار" : "$200k+")</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="flabel" for="message">@(fa ? "پیام" : "Message")<span class="text-red-600" aria-hidden="true"> *</span></label>
|
|
<textarea id="message" name="message" required rows="4" placeholder="@(fa ? "هدف، بازهی زمانی، و چیزی که الان گیرتان انداخته…" : "Goal, timeline, current blockers…")" class="field resize-none"></textarea>
|
|
</div>
|
|
|
|
<button type="submit" class="btn w-full">@(fa ? "ارسال پیام" : "Send request")</button>
|
|
<p id="contact-status" role="status" aria-live="polite" class="mt-1 text-sm text-zinc-500">@(fa ? "معمولاً ظرف ۲۴ ساعت کاری جواب میدهم." : "Typical reply within 24 working hours.")</p>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
@functions {
|
|
static string ServiceIcon(string id) => id switch {
|
|
"strategy" => """<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M9 20H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h4"/><polyline points="9,9 4,9"/><polyline points="9,12 4,12"/><polyline points="9,15 4,15"/><rect x="9" y="2" width="6" height="6"/><path d="M15 8h4a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-4"/></svg>""",
|
|
"automation" => """<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.22 4.22l2.12 2.12M17.66 17.66l2.12 2.12M2 12h3M19 12h3M4.22 19.78l2.12-2.12M17.66 6.34l2.12-2.12"/></svg>""",
|
|
"llm-rag" => """<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>""",
|
|
"architecture" => """<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><rect x="2" y="3" width="6" height="6"/><rect x="16" y="3" width="6" height="6"/><rect x="9" y="15" width="6" height="6"/><path d="M5 9v3h14V9M12 12v3"/></svg>""",
|
|
"mobile" => """<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><rect x="5" y="2" width="14" height="20" rx="2"/><path d="M12 18h.01"/></svg>""",
|
|
"apps" => """<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 9h18"/><path d="M7 6.5h.01"/></svg>""",
|
|
_ => """<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/></svg>""",
|
|
};
|
|
}
|