feat: real Bangla/English toggle for the home page (Hero through Footer)
The BN/EN button already worked (state + persistence), but almost nothing on the page actually responded to it — Hero showed both languages stacked at once, the home service cards' Bangla name was hardcoded on regardless of language, and everything else (About, Skills, Testimonials, own-products showcase, Timeline, Nav chrome, Footer) had zero language awareness at all. Wired `lang` through to every home-page section, added ~15 new *Bn content fields to data.jsx (service kind/description/highlights, testimonials, own-products, experience, metrics), and fixed the two literal stacking bugs (Hero tagline, home service card names). Also fixed the language toggle button being hidden below 640px — mobile had no way to reach it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+19
-19
@@ -166,7 +166,7 @@ function App() {
|
||||
if (route.startsWith('services/')) {
|
||||
const id = route.slice('services/'.length);
|
||||
const svc = (PORTFOLIO_DATA.services || []).find(s => s.id === id);
|
||||
if (svc) return <T.ServiceDetailPage svc={svc} />;
|
||||
if (svc) return <T.ServiceDetailPage svc={svc} lang={lang} />;
|
||||
window.location.hash = '#/services';
|
||||
return null;
|
||||
}
|
||||
@@ -175,34 +175,34 @@ function App() {
|
||||
case 'services':
|
||||
return <T.ServicesPage lang={lang} />;
|
||||
case 'stack':
|
||||
return <T.StackPage />;
|
||||
return <T.StackPage lang={lang} />;
|
||||
case 'agents':
|
||||
return <T.AgentsPage />;
|
||||
return <T.AgentsPage lang={lang} />;
|
||||
case 'timeline':
|
||||
return <T.TimelinePage />;
|
||||
return <T.TimelinePage lang={lang} />;
|
||||
case 'contact':
|
||||
return <T.ContactPage lang={lang} />;
|
||||
case 'pricing':
|
||||
return <T.PricingPage />;
|
||||
return <T.PricingPage lang={lang} />;
|
||||
case 'blog':
|
||||
return <T.BlogPage />;
|
||||
return <T.BlogPage lang={lang} />;
|
||||
case 'case-studies':
|
||||
return <T.CaseStudiesPage />;
|
||||
return <T.CaseStudiesPage lang={lang} />;
|
||||
case 'privacy':
|
||||
return <T.PrivacyPage />;
|
||||
return <T.PrivacyPage lang={lang} />;
|
||||
case 'terms':
|
||||
return <T.TermsPage />;
|
||||
return <T.TermsPage lang={lang} />;
|
||||
default:
|
||||
return (
|
||||
<main style={density === "compact" ? { fontSize: 14.5 } : undefined}>
|
||||
<T.Hero headlinePrefix={tweaks.heroHeadlinePrefix} headlineSuffix={tweaks.heroHeadlineSuffix} lang={lang} />
|
||||
<T.About />
|
||||
<T.Skills />
|
||||
<T.Projects />
|
||||
<T.FlagshipProduct />
|
||||
<T.AgentShowcase />
|
||||
<T.Testimonials />
|
||||
<T.Timeline />
|
||||
<T.About lang={lang} />
|
||||
<T.Skills lang={lang} />
|
||||
<T.Projects lang={lang} />
|
||||
<T.FlagshipProduct lang={lang} />
|
||||
<T.AgentShowcase lang={lang} />
|
||||
<T.Testimonials lang={lang} />
|
||||
<T.Timeline lang={lang} />
|
||||
<T.Contact lang={lang} />
|
||||
</main>
|
||||
);
|
||||
@@ -213,9 +213,9 @@ function App() {
|
||||
<>
|
||||
<T.Nav {...navProps} />
|
||||
{renderPage()}
|
||||
<T.Footer />
|
||||
<T.CommandPalette open={paletteOpen} onClose={() => setPaletteOpen(false)} />
|
||||
<T.ChatboxWidget />
|
||||
<T.Footer lang={lang} />
|
||||
<T.CommandPalette open={paletteOpen} onClose={() => setPaletteOpen(false)} lang={lang} />
|
||||
<T.ChatboxWidget lang={lang} />
|
||||
|
||||
<window.TweaksPanel title="Tweaks">
|
||||
<window.TweakSection label="Theme" />
|
||||
|
||||
+122
-4
@@ -20,20 +20,27 @@ const PORTFOLIO_DATA = {
|
||||
},
|
||||
|
||||
metrics: [
|
||||
{ label: "Years shipping", value: "7+" },
|
||||
{ label: "Agents in production", value: "40+" },
|
||||
{ label: "Enterprise clients", value: "12" },
|
||||
{ label: "Uptime maintained", value: "99.98%" },
|
||||
{ label: "Years shipping", labelBn: "বছর ধরে শিপিং", value: "7+" },
|
||||
{ label: "Agents in production", labelBn: "প্রোডাকশনে এজেন্ট", value: "40+" },
|
||||
{ label: "Enterprise clients", labelBn: "এন্টারপ্রাইজ ক্লায়েন্ট", value: "12" },
|
||||
{ label: "Uptime maintained", labelBn: "আপটাইম বজায়", value: "99.98%" },
|
||||
],
|
||||
|
||||
about: {
|
||||
pitch: "I build the systems that act on behalf of teams — agents that triage, route, decide, and execute. The work spans the full stack: model orchestration, eval harnesses, queue infrastructure, dashboards, on-chain settlement, and the tedious connective tissue that turns a clever demo into something a CFO will sign off on.",
|
||||
pitchBn: "আমি এমন সিস্টেম তৈরি করি যা টিমের হয়ে সরাসরি কাজ করে — এজেন্ট যা বিচার করে, route করে, সিদ্ধান্ত নেয়, এবং কাজ সম্পন্ন করে। কাজের পরিধি পুরো স্ট্যাক জুড়ে: মডেল অর্কেস্ট্রেশন, eval harness, queue ইনফ্রাস্ট্রাকচার, ড্যাশবোর্ড, on-chain settlement, এবং সেই ক্লান্তিকর সংযোগকারী কাজ যা একটা চটকদার ডেমোকে এমন কিছুতে পরিণত করে যাতে একজন CFO সই করতে রাজি হয়।",
|
||||
bullets: [
|
||||
"Designed agent runtimes for fintech & MLM platforms moving 8-figure GMV",
|
||||
"Built orchestration layers across OpenAI, Anthropic, vLLM, and self-hosted models",
|
||||
"Shipped Web3 settlement rails — wallets, signers, on-chain audit trails",
|
||||
"Lead architect on three SaaS dashboards now serving 50k+ daily users",
|
||||
],
|
||||
bulletsBn: [
|
||||
"৮-অঙ্কের GMV চলমান fintech ও MLM প্ল্যাটফর্মের জন্য এজেন্ট রানটাইম ডিজাইন",
|
||||
"OpenAI, Anthropic, vLLM, এবং self-hosted মডেল জুড়ে অর্কেস্ট্রেশন লেয়ার তৈরি",
|
||||
"Web3 settlement rail শিপ করেছি — ওয়ালেট, সাইনার, on-chain অডিট ট্রেইল",
|
||||
"তিনটা SaaS ড্যাশবোর্ডের লিড আর্কিটেক্ট, যা এখন ৫০k+ দৈনিক ইউজার সার্ভ করে",
|
||||
],
|
||||
},
|
||||
|
||||
stack: {
|
||||
@@ -79,8 +86,11 @@ const PORTFOLIO_DATA = {
|
||||
name: "Website & Webapp Development",
|
||||
nameBn: "ওয়েবসাইট ও ওয়েবঅ্যাপ ডেভেলপমেন্ট",
|
||||
kind: "Core Service",
|
||||
kindBn: "কোর সার্ভিস",
|
||||
description:
|
||||
"From landing pages to full SaaS dashboards — pixel-perfect, fast, and built to scale. SvelteKit, Next.js, React, Tailwind.",
|
||||
descriptionBn:
|
||||
"ল্যান্ডিং পেজ থেকে শুরু করে সম্পূর্ণ SaaS ড্যাশবোর্ড পর্যন্ত — pixel-perfect, দ্রুত, এবং স্কেল করার উপযোগী করে তৈরি। SvelteKit, Next.js, React, Tailwind।",
|
||||
stack: ["SvelteKit", "Next.js", "React", "Tailwind", "PostgreSQL"],
|
||||
impact: { primary: "50k+", secondary: "daily users served" },
|
||||
color: "violet",
|
||||
@@ -91,8 +101,11 @@ const PORTFOLIO_DATA = {
|
||||
name: "AI Agent & Automation",
|
||||
nameBn: "এআই এজেন্ট ও অটোমেশন",
|
||||
kind: "Core Service",
|
||||
kindBn: "কোর সার্ভিস",
|
||||
description:
|
||||
"Custom AI agents that triage, decide, and execute — integrated with your tools via n8n, Anthropic, and OpenAI.",
|
||||
descriptionBn:
|
||||
"কাস্টম এআই এজেন্ট যা নিজে বিচার করে, সিদ্ধান্ত নেয় ও কাজ সম্পন্ন করে — n8n, Anthropic ও OpenAI-এর মাধ্যমে আপনার টুলসের সাথে যুক্ত।",
|
||||
stack: ["Anthropic Claude", "n8n", "LangGraph", "Node.js", "Hono"],
|
||||
impact: { primary: "1.2M+", secondary: "agent runs / month" },
|
||||
color: "cyan",
|
||||
@@ -103,8 +116,11 @@ const PORTFOLIO_DATA = {
|
||||
name: "Web3 & Blockchain",
|
||||
nameBn: "ওয়েব৩ ও ব্লকচেইন",
|
||||
kind: "Specialist Service",
|
||||
kindBn: "স্পেশালিস্ট সার্ভিস",
|
||||
description:
|
||||
"Wallets, smart contracts, multi-chain bridges, and on-chain audit trails. Gasless UX that hides complexity from end users.",
|
||||
descriptionBn:
|
||||
"ওয়ালেট, স্মার্ট কন্ট্রাক্ট, মাল্টি-চেইন ব্রিজ, এবং অন-চেইন অডিট ট্রেইল। Gasless UX যা জটিলতা ইউজারের কাছ থেকে লুকিয়ে রাখে।",
|
||||
stack: ["Solidity", "viem", "wagmi", "Cloudflare Workers"],
|
||||
impact: { primary: "12 chains", secondary: "EVM + Solana" },
|
||||
color: "green",
|
||||
@@ -115,8 +131,11 @@ const PORTFOLIO_DATA = {
|
||||
name: "MT5 EA & Trading Automation",
|
||||
nameBn: "MT5 EA ও ট্রেডিং অটোমেশন",
|
||||
kind: "Specialist Service",
|
||||
kindBn: "স্পেশালিস্ট সার্ভিস",
|
||||
description:
|
||||
"Expert Advisors, real-time P&L dashboards, risk envelopes, and one-click kill switches for MetaTrader 5 platforms.",
|
||||
descriptionBn:
|
||||
"Expert Advisor, রিয়েল-টাইম P&L ড্যাশবোর্ড, রিস্ক এনভেলপ, এবং MetaTrader 5 প্ল্যাটফর্মের জন্য এক-ক্লিক kill switch।",
|
||||
stack: ["MQL5", "Go", "ClickHouse", "WebSockets", "React"],
|
||||
impact: { primary: "<80ms", secondary: "tick-to-render latency" },
|
||||
color: "amber",
|
||||
@@ -127,8 +146,11 @@ const PORTFOLIO_DATA = {
|
||||
name: "Browser Scraping & Data Pipeline",
|
||||
nameBn: "ব্রাউজার স্ক্র্যাপিং ও ডেটা পাইপলাইন",
|
||||
kind: "Specialist Service",
|
||||
kindBn: "স্পেশালিস্ট সার্ভিস",
|
||||
description:
|
||||
"Playwright/Puppeteer scrapers, proxy rotation, structured data extraction, and ETL pipelines into your DB or warehouse.",
|
||||
descriptionBn:
|
||||
"Playwright/Puppeteer স্ক্র্যাপার, প্রক্সি রোটেশন, structured ডেটা এক্সট্র্যাকশন, এবং আপনার DB বা warehouse-এ ETL পাইপলাইন।",
|
||||
stack: ["Playwright", "Puppeteer", "Python", "Airflow", "PostgreSQL"],
|
||||
impact: { primary: "10M+", secondary: "records extracted / month" },
|
||||
color: "violet",
|
||||
@@ -139,8 +161,11 @@ const PORTFOLIO_DATA = {
|
||||
name: "Infrastructure & DevOps",
|
||||
nameBn: "ইনফ্রাস্ট্রাকচার ও ডেভঅপস",
|
||||
kind: "Specialist Service",
|
||||
kindBn: "স্পেশালিস্ট সার্ভিস",
|
||||
description:
|
||||
"VPS setup, Docker, Coolify, Traefik, CI/CD pipelines, SSL, monitoring, and zero-downtime deploys on your own cloud.",
|
||||
descriptionBn:
|
||||
"VPS সেটআপ, Docker, Coolify, Traefik, CI/CD পাইপলাইন, SSL, মনিটরিং, এবং আপনার নিজের cloud-এ zero-downtime ডিপ্লয়।",
|
||||
stack: ["Docker", "Coolify", "Traefik", "GitHub Actions", "PostgreSQL"],
|
||||
impact: { primary: "99.98%", secondary: "uptime maintained" },
|
||||
color: "cyan",
|
||||
@@ -150,9 +175,12 @@ const PORTFOLIO_DATA = {
|
||||
name: "AI-Powered Meta Ads",
|
||||
nameBn: "এআই-চালিত মেটা অ্যাডস",
|
||||
kind: "Growth Service",
|
||||
kindBn: "গ্রোথ সার্ভিস",
|
||||
badge: "NEW · Meta MCP",
|
||||
description:
|
||||
"AI agents connected directly to Meta's official API — optimizing bids, rotating creatives, and reallocating budgets every 15 minutes. Not a human checking ads twice a day. A system that never sleeps.",
|
||||
descriptionBn:
|
||||
"Meta-এর official API-এর সাথে সরাসরি যুক্ত এআই এজেন্ট — প্রতি ১৫ মিনিটে bid অপ্টিমাইজ করে, creative পাল্টায়, বাজেট পুনর্বণ্টন করে। দিনে দুইবার মানুষ চেক করার মতো না — এমন একটা সিস্টেম যা কখনো ঘুমায় না।",
|
||||
stack: ["Meta MCP", "Meta Ads API", "n8n", "Claude AI", "Anthropic"],
|
||||
impact: { primary: "5×", secondary: "ROAS vs. manual management" },
|
||||
color: "rose",
|
||||
@@ -164,15 +192,26 @@ const PORTFOLIO_DATA = {
|
||||
"Daily AI-written performance reports to your inbox",
|
||||
"Full Meta API access via official MCP integration",
|
||||
],
|
||||
highlightsBn: [
|
||||
"প্রতি ১৫ মিনিটে রিয়েল-টাইম bid ও বাজেট অপ্টিমাইজেশন",
|
||||
"১০০+ অ্যাড ভ্যারিয়েন্ট একসাথে এআই দিয়ে A/B টেস্ট",
|
||||
"স্বয়ংক্রিয় audience expansion ও lookalike generation",
|
||||
"Creative fatigue detection — burnout হওয়ার আগেই থামায়",
|
||||
"প্রতিদিন এআই-লিখিত পারফরম্যান্স রিপোর্ট আপনার ইনবক্সে",
|
||||
"অফিসিয়াল MCP integration-এর মাধ্যমে সম্পূর্ণ Meta API অ্যাক্সেস",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "whatsapp-messenger-bot",
|
||||
name: "WhatsApp & Messenger Sales Bot",
|
||||
nameBn: "হোয়াটসঅ্যাপ ও মেসেঞ্জার সেলস বট",
|
||||
kind: "Automation · Live",
|
||||
kindBn: "অটোমেশন · লাইভ",
|
||||
badge: "LIVE · Try it on WhatsApp",
|
||||
description:
|
||||
"A Bengali sales assistant that answers your customers 24/7 on WhatsApp and Messenger — with the real product photo, the real price, and the real discount pulled straight from your own database. It takes the order too. Running live on our own shop right now; message it and see.",
|
||||
descriptionBn:
|
||||
"একটা বাংলা সেলস অ্যাসিস্ট্যান্ট যা WhatsApp ও Messenger-এ আপনার কাস্টমারদের ২৪/৭ উত্তর দেয় — আসল প্রোডাক্ট ছবি, আসল দাম, আসল ছাড় সহ, সরাসরি আপনার নিজের ডেটাবেস থেকে। অর্ডারও নেয়। আমাদের নিজের দোকানে এখনই লাইভ চলছে; মেসেজ করে দেখুন।",
|
||||
stack: ["WhatsApp Cloud API", "Meta Graph API", "Cloudflare Workers", "n8n", "Gemini", "Supabase"],
|
||||
impact: { primary: "24/7", secondary: "replies in Bengali, in seconds" },
|
||||
color: "emerald",
|
||||
@@ -183,6 +222,13 @@ const PORTFOLIO_DATA = {
|
||||
"Remembers the conversation, so \"ওইটা দেখান\" works",
|
||||
"Flags suspicious COD orders and hands angry customers to a human",
|
||||
],
|
||||
highlightsBn: [
|
||||
"দাম ও ছবি আসে আপনার ডেটাবেস থেকে — এআই কখনো নিজে দাম লেখে না, তাই ভুল দাম বলার সুযোগই নেই",
|
||||
"প্রতিটা উত্তরে আসল প্রোডাক্ট ছবি পাঠায়, শুধু লিংক না",
|
||||
"সম্পূর্ণ অর্ডার — নাম, ঠিকানা, ফোন — সরাসরি আপনার সিস্টেমে জমা করে",
|
||||
"কথোপকথন মনে রাখে, তাই \"ওইটা দেখান\" বললেও বোঝে",
|
||||
"সন্দেহজনক COD অর্ডার চিহ্নিত করে ও রাগান্বিত কাস্টমারকে মানুষের কাছে পাঠায়",
|
||||
],
|
||||
demo: "https://wa.me/8801712426871?text=Medicube%20er%20ki%20ki%20product%20ache%3F",
|
||||
},
|
||||
{
|
||||
@@ -190,9 +236,12 @@ const PORTFOLIO_DATA = {
|
||||
name: "Social Media Autopilot",
|
||||
nameBn: "সোশ্যাল মিডিয়া অটোপাইলট",
|
||||
kind: "Automation · Live",
|
||||
kindBn: "অটোমেশন · লাইভ",
|
||||
badge: "LIVE · Running daily",
|
||||
description:
|
||||
"Your Facebook page posts itself. Daily product carousels and spotlights, pulled from your own catalog, captioned in Bengali and watermarked automatically — every day, without anyone opening a laptop. Running on our own page right now.",
|
||||
descriptionBn:
|
||||
"আপনার Facebook পেজ নিজে থেকেই পোস্ট করে। দৈনিক প্রোডাক্ট carousel ও spotlight, আপনার নিজের ক্যাটালগ থেকে নেওয়া, বাংলায় ক্যাপশন সহ ও স্বয়ংক্রিয়ভাবে watermark করা — প্রতিদিন, কারো ল্যাপটপ না খুলেই। আমাদের নিজের পেজে এখনই চলছে।",
|
||||
stack: ["n8n", "Meta Graph API", "Supabase", "Sharp", "Gemini"],
|
||||
impact: { primary: "0", secondary: "minutes of manual posting" },
|
||||
color: "blue",
|
||||
@@ -203,15 +252,25 @@ const PORTFOLIO_DATA = {
|
||||
"Rotates brands and products so the page never looks repetitive",
|
||||
"Posts keep going out whether you're at the shop or asleep",
|
||||
],
|
||||
highlightsBn: [
|
||||
"দৈনিক মাল্টি-প্রোডাক্ট carousel — আসল ছবি, আসল দাম, আপনার ক্যাটালগ থেকে",
|
||||
"বাংলা ক্যাপশন আপনার জন্য লেখা, আপনার ব্র্যান্ড দিয়ে watermark করা",
|
||||
"প্রতিটা কার্ড সরাসরি সেই প্রোডাক্টের পেজে নিয়ে যায়, শুধু হোমপেজ না",
|
||||
"ব্র্যান্ড ও প্রোডাক্ট ঘুরিয়ে দেখায় যাতে পেজ কখনো একঘেয়ে না লাগে",
|
||||
"আপনি দোকানে থাকুন বা ঘুমান, পোস্ট চলতেই থাকে",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "ecommerce-full",
|
||||
name: "Complete Online Shop",
|
||||
nameBn: "সম্পূর্ণ অনলাইন দোকান",
|
||||
kind: "Bundle · End to end",
|
||||
kindBn: "বান্ডল · এন্ড টু এন্ড",
|
||||
badge: "EVERYTHING IN ONE",
|
||||
description:
|
||||
"The whole shop, one roof: the website, the WhatsApp sales bot, courier booking, daily social posts, and Meta ads — built, connected, and run together. This is exactly what we run for our own brand, so you are buying a system that already sells, not a plan.",
|
||||
descriptionBn:
|
||||
"পুরো দোকান, এক ছাদের নিচে: ওয়েবসাইট, WhatsApp সেলস বট, কুরিয়ার বুকিং, দৈনিক সোশ্যাল পোস্ট, এবং Meta অ্যাডস — সব তৈরি, সংযুক্ত ও একসাথে চালানো। এটাই আমরা নিজেদের ব্র্যান্ডের জন্য চালাই, তাই আপনি একটা পরিকল্পনা না, একটা already-বিক্রি-করা সিস্টেম কিনছেন।",
|
||||
stack: ["React", "Supabase", "WhatsApp Cloud API", "n8n", "Meta Ads", "Steadfast"],
|
||||
impact: { primary: "1", secondary: "team, running all of it" },
|
||||
color: "violet",
|
||||
@@ -223,15 +282,26 @@ const PORTFOLIO_DATA = {
|
||||
"Daily auto-posts and Meta ad campaigns driving the traffic",
|
||||
"One team accountable for the whole chain, not five vendors",
|
||||
],
|
||||
highlightsBn: [
|
||||
"আসল স্টক, ছাড় ও cash on delivery সহ স্টোরফ্রন্ট",
|
||||
"WhatsApp বট ২৪/৭ বাংলায় উত্তর দেয় ও অর্ডার নেয়",
|
||||
"অর্ডার এক ড্যাশবোর্ডে আসে — ওয়েবসাইট ও বট একসাথে",
|
||||
"ড্যাশবোর্ড থেকে না বেরিয়েই কুরিয়ার বুকিং ও ট্র্যাকিং",
|
||||
"দৈনিক অটো-পোস্ট ও Meta অ্যাড ক্যাম্পেইন ট্রাফিক আনে",
|
||||
"পুরো চেইনের জন্য একটাই দায়বদ্ধ টিম, পাঁচটা vendor না",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "courier-mcp",
|
||||
name: "Aura Courier MCP",
|
||||
nameBn: "অরা কুরিয়ার MCP",
|
||||
kind: "Connector · Live",
|
||||
kindBn: "কানেক্টর · লাইভ",
|
||||
badge: "LIVE · MCP Connector",
|
||||
description:
|
||||
"One Model Context Protocol connector for every Bangladesh courier. Add it to Claude, plug in your own courier keys, and book & track parcels — Steadfast & Pathao — straight from a conversation. Your shop's logistics, agentic.",
|
||||
descriptionBn:
|
||||
"বাংলাদেশের প্রতিটা কুরিয়ারের জন্য একটাই Model Context Protocol কানেক্টর। Claude-এ যোগ করুন, নিজের কুরিয়ার key বসান, আর কথোপকথন থেকেই পার্সেল বুক ও ট্র্যাক করুন — Steadfast ও Pathao। আপনার দোকানের লজিস্টিক্স, এজেন্টিক।",
|
||||
stack: ["MCP", "Steadfast", "Pathao", "Claude", "TypeScript"],
|
||||
impact: { primary: "1", secondary: "connector · every courier" },
|
||||
color: "amber",
|
||||
@@ -242,6 +312,13 @@ const PORTFOLIO_DATA = {
|
||||
"Works in Claude Desktop, Claude Code, or hosted",
|
||||
"Open source — anyone can add it in seconds",
|
||||
],
|
||||
highlightsBn: [
|
||||
"Claude থেকেই পার্সেল বুক ও ট্র্যাক — ড্যাশবোর্ড ঘোরাঘুরি লাগবে না",
|
||||
"একটা URL, আপনার নিজের কুরিয়ার key — আমরা কিছুই সংরক্ষণ করি না",
|
||||
"Steadfast ও Pathao লাইভ · RedX ও Paperfly আসছে",
|
||||
"Claude Desktop, Claude Code, বা hosted — সব জায়গায় কাজ করে",
|
||||
"ওপেন সোর্স — যে কেউ কয়েক সেকেন্ডে যোগ করতে পারে",
|
||||
],
|
||||
demo: "https://courier.auraajenticai.cloud",
|
||||
repo: "https://github.com/auraajenticai/aura-courier-mcp",
|
||||
},
|
||||
@@ -254,6 +331,7 @@ const PORTFOLIO_DATA = {
|
||||
company: "FinSync BD",
|
||||
service: "AI Agent & Automation",
|
||||
text: "Aura built an n8n + Claude pipeline that processes our reconciliation in 5 seconds — what took our team 2 hours manually. The system hasn't failed once in 6 months.",
|
||||
textBn: "Aura একটা n8n + Claude পাইপলাইন বানিয়েছে যা আমাদের reconciliation ৫ সেকেন্ডে করে ফেলে — যা আগে আমাদের টিমের ম্যানুয়ালি ২ ঘণ্টা লাগত। সিস্টেমটা ৬ মাসে একবারও fail করেনি।",
|
||||
avatar: "FR",
|
||||
color: "cyan",
|
||||
},
|
||||
@@ -263,6 +341,7 @@ const PORTFOLIO_DATA = {
|
||||
company: "AlphaEdge Capital",
|
||||
service: "MT5 EA & Trading",
|
||||
text: "The EA outperformed our manual strategy by 340% over 3 months. The kill-switch and risk envelope features gave our risk team the confidence to scale.",
|
||||
textBn: "৩ মাসে EA আমাদের ম্যানুয়াল স্ট্র্যাটেজিকে ৩৪০% ছাড়িয়ে গেছে। Kill-switch ও risk envelope ফিচার আমাদের risk টিমকে স্কেল করার আত্মবিশ্বাস দিয়েছে।",
|
||||
avatar: "TH",
|
||||
color: "amber",
|
||||
},
|
||||
@@ -272,6 +351,7 @@ const PORTFOLIO_DATA = {
|
||||
company: "Growth Labs",
|
||||
service: "AI-Powered Meta Ads",
|
||||
text: "From 1.8× to 5.2× ROAS in 8 weeks. The AI rotates creatives before fatigue hits — something no human campaign manager was catching fast enough.",
|
||||
textBn: "৮ সপ্তাহে ROAS ১.৮× থেকে ৫.২×। fatigue হওয়ার আগেই এআই creative পাল্টে দেয় — কোনো মানুষ campaign manager এত দ্রুত ধরতে পারছিল না।",
|
||||
avatar: "SM",
|
||||
color: "rose",
|
||||
},
|
||||
@@ -281,6 +361,7 @@ const PORTFOLIO_DATA = {
|
||||
company: "TradeStack",
|
||||
service: "Web3 & Blockchain",
|
||||
text: "Delivered a multi-chain settlement layer with gasless UX in 6 weeks. The on-chain audit trail is what sold us — our compliance team loves it.",
|
||||
textBn: "৬ সপ্তাহে gasless UX সহ multi-chain settlement layer ডেলিভার করেছে। on-chain audit trail-ই আমাদের convince করেছে — আমাদের compliance টিম এটা খুব পছন্দ করে।",
|
||||
avatar: "AC",
|
||||
color: "green",
|
||||
},
|
||||
@@ -441,8 +522,11 @@ const PORTFOLIO_DATA = {
|
||||
id: "snehalata",
|
||||
name: "Snehalata",
|
||||
tagline: "AI-Powered Clothing Ecosystem",
|
||||
taglineBn: "এআই-চালিত ক্লথিং ইকোসিস্টেম",
|
||||
description:
|
||||
"Aura's own multi-vendor clothing marketplace for Bangladesh. Vendors register, list products, and sell — while Gemini AI handles style refinement, virtual try-on, fraud audits, and a 24/7 Bengali-language chat assistant. Built end-to-end on Aura's stack.",
|
||||
descriptionBn:
|
||||
"বাংলাদেশের জন্য Aura-র নিজস্ব multi-vendor ক্লথিং মার্কেটপ্লেস। Vendor-রা রেজিস্টার করে, প্রোডাক্ট লিস্ট করে, বিক্রি করে — আর Gemini AI স্টাইল রিফাইনমেন্ট, ভার্চুয়াল ট্রাই-অন, fraud audit, এবং ২৪/৭ বাংলা চ্যাট অ্যাসিস্ট্যান্ট সামলায়। সম্পূর্ণ Aura-র নিজের স্ট্যাকে তৈরি।",
|
||||
url: "https://www.snehalata.com",
|
||||
badge: "Ecosystem",
|
||||
stack: ["SvelteKit", "Supabase", "Gemini AI", "Tailwind", "Vercel"],
|
||||
@@ -454,14 +538,25 @@ const PORTFOLIO_DATA = {
|
||||
"Full order lifecycle: placement → quality check → delivery tracking",
|
||||
"CEO & vendor dashboards with real-time ecosystem stats",
|
||||
],
|
||||
featuresBn: [
|
||||
"এআই-চালিত vendor onboarding audit সহ multi-vendor মার্কেটপ্লেস",
|
||||
"প্রতিটা প্রোডাক্টের জন্য Gemini-চালিত ভার্চুয়াল ট্রাই-অন ও স্টাইল ট্রান্সফার",
|
||||
"শপিং গাইডেন্সের জন্য ২৪/৭ বাংলা এআই চ্যাট অ্যাসিস্ট্যান্ট",
|
||||
"বাংলাদেশ জেলা-ভিত্তিক vendor ও প্রোডাক্ট ফিল্টারিং",
|
||||
"সম্পূর্ণ অর্ডার লাইফসাইকেল: অর্ডার → কোয়ালিটি চেক → ডেলিভারি ট্র্যাকিং",
|
||||
"রিয়েল-টাইম ইকোসিস্টেম পরিসংখ্যান সহ CEO ও vendor ড্যাশবোর্ড",
|
||||
],
|
||||
color: "violet",
|
||||
},
|
||||
{
|
||||
id: "glamourstouch",
|
||||
name: "Glamours Touch",
|
||||
tagline: "Beauty & Lifestyle E-Commerce",
|
||||
taglineBn: "বিউটি ও লাইফস্টাইল ই-কমার্স",
|
||||
description:
|
||||
"Aura's own live e-commerce brand in the beauty & lifestyle space. We built it, we run it, we sell from it — end to end. Custom storefront, product catalog, cart, payment integration, and admin dashboard. Not a demo. A real business.",
|
||||
descriptionBn:
|
||||
"বিউটি ও লাইফস্টাইল সেক্টরে Aura-র নিজস্ব লাইভ ই-কমার্স ব্র্যান্ড। আমরাই বানিয়েছি, আমরাই চালাই, আমরাই বিক্রি করি — শুরু থেকে শেষ পর্যন্ত। কাস্টম স্টোরফ্রন্ট, প্রোডাক্ট ক্যাটালগ, কার্ট, পেমেন্ট ইন্টিগ্রেশন, এবং অ্যাডমিন ড্যাশবোর্ড। কোনো ডেমো না। একটা আসল ব্যবসা।",
|
||||
url: "https://glamourstouch.com",
|
||||
badge: "Live Product",
|
||||
stack: ["React", "Vite", "Supabase", "Tailwind", "Vercel"],
|
||||
@@ -473,6 +568,14 @@ const PORTFOLIO_DATA = {
|
||||
"Admin dashboard for orders, products & analytics",
|
||||
"Daily automated Facebook product posts — no manual posting",
|
||||
],
|
||||
featuresBn: [
|
||||
"৫৬০+ প্রোডাক্ট ক্যাটালগ, আসল স্টক ও ছাড়ের দাম সহ",
|
||||
"পুরো বাংলাদেশে cash on delivery, order tracking বিল্ট-ইন",
|
||||
"WhatsApp ও Messenger সেলস বট ২৪/৭ বাংলায় কাস্টমারদের উত্তর দেয়",
|
||||
"মোবাইল-ফার্স্ট রেসপনসিভ স্টোরফ্রন্ট ডিজাইন",
|
||||
"অর্ডার, প্রোডাক্ট ও অ্যানালিটিক্সের জন্য অ্যাডমিন ড্যাশবোর্ড",
|
||||
"দৈনিক স্বয়ংক্রিয় Facebook প্রোডাক্ট পোস্ট — ম্যানুয়াল পোস্টিং লাগে না",
|
||||
],
|
||||
color: "rose",
|
||||
},
|
||||
],
|
||||
@@ -604,37 +707,52 @@ const PORTFOLIO_DATA = {
|
||||
{
|
||||
year: "2024 — Present",
|
||||
role: "Founder & Principal Engineer",
|
||||
roleBn: "ফাউন্ডার ও প্রিন্সিপাল ইঞ্জিনিয়ার",
|
||||
company: "Aura Ajentic Cloud",
|
||||
kind: "Product",
|
||||
kindBn: "প্রোডাক্ট",
|
||||
detail: "Building the agent runtime layer — orchestration, evals, observability — used by 12 enterprise teams.",
|
||||
detailBn: "এজেন্ট রানটাইম লেয়ার তৈরি করছি — অর্কেস্ট্রেশন, evals, observability — যা ১২টা এন্টারপ্রাইজ টিম ব্যবহার করে।",
|
||||
},
|
||||
{
|
||||
year: "2022 — 2024",
|
||||
role: "Staff Full-Stack Engineer",
|
||||
roleBn: "স্টাফ ফুল-স্ট্যাক ইঞ্জিনিয়ার",
|
||||
company: "Confidential · Fintech",
|
||||
kind: "Contract",
|
||||
kindBn: "কন্ট্রাক্ট",
|
||||
detail: "Led the rebuild of an MLM compensation engine, ran the migration from monolith to multi-tenant.",
|
||||
detailBn: "একটা MLM কম্পেনসেশন ইঞ্জিনের পুনর্নির্মাণের নেতৃত্ব দিয়েছি, monolith থেকে multi-tenant-এ migration চালিয়েছি।",
|
||||
},
|
||||
{
|
||||
year: "2021 — 2022",
|
||||
role: "Senior Engineer · Web3",
|
||||
roleBn: "সিনিয়র ইঞ্জিনিয়ার · ওয়েব৩",
|
||||
company: "Stealth DeFi protocol",
|
||||
kind: "Contract",
|
||||
kindBn: "কন্ট্রাক্ট",
|
||||
detail: "Wallet UX, signer abstraction, on-chain settlement rails. Shipped before the protocol announced.",
|
||||
detailBn: "Wallet UX, signer abstraction, on-chain settlement rail। প্রোটোকল ঘোষণা করার আগেই শিপ করেছি।",
|
||||
},
|
||||
{
|
||||
year: "2019 — 2021",
|
||||
role: "Full-Stack Engineer",
|
||||
roleBn: "ফুল-স্ট্যাক ইঞ্জিনিয়ার",
|
||||
company: "Series-B SaaS",
|
||||
kind: "Full-time",
|
||||
kindBn: "ফুল-টাইম",
|
||||
detail: "Owned the dashboard surface area — billing, RBAC, integrations. Pushed app from 4k to 28k DAU.",
|
||||
detailBn: "ড্যাশবোর্ডের পুরো অংশের দায়িত্বে ছিলাম — billing, RBAC, integration। অ্যাপকে 4k থেকে 28k DAU-তে নিয়ে গেছি।",
|
||||
},
|
||||
{
|
||||
year: "2018 — 2019",
|
||||
role: "Software Engineer",
|
||||
roleBn: "সফটওয়্যার ইঞ্জিনিয়ার",
|
||||
company: "Agency · Remote",
|
||||
kind: "Full-time",
|
||||
kindBn: "ফুল-টাইম",
|
||||
detail: "Cut my teeth shipping React + Node products across e-commerce, logistics, and edtech.",
|
||||
detailBn: "e-commerce, logistics, ও edtech জুড়ে React + Node প্রোডাক্ট শিপ করে হাতেখড়ি হয়েছে।",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+22
-16
@@ -120,10 +120,26 @@ const TerminalRain = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const HERO_TXT = {
|
||||
en: {
|
||||
pill: "Accepting new projects · Q3 2026",
|
||||
viewServices: "View Services",
|
||||
getQuote: "Get a Quote",
|
||||
lastShipped: "Last shipped: 2 days ago",
|
||||
},
|
||||
bn: {
|
||||
pill: "নতুন প্রজেক্ট নেওয়া হচ্ছে · Q3 2026",
|
||||
viewServices: "সার্ভিস দেখুন",
|
||||
getQuote: "কোট নিন",
|
||||
lastShipped: "সর্বশেষ শিপড: ২ দিন আগে",
|
||||
},
|
||||
};
|
||||
|
||||
const Hero = ({ headlinePrefix, headlineSuffix, lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const prefix = headlinePrefix || "Agentic AI &";
|
||||
const suffix = headlineSuffix || "automation engineer";
|
||||
const t = HERO_TXT[lang] || HERO_TXT.en;
|
||||
|
||||
return (
|
||||
<section id="top" style={{
|
||||
@@ -158,7 +174,7 @@ const Hero = ({ headlinePrefix, headlineSuffix, lang = "en" }) => {
|
||||
boxShadow: "0 0 10px var(--good)",
|
||||
animation: "pulse-dot 2s infinite",
|
||||
}} />
|
||||
Accepting new projects · Q3 2026
|
||||
{t.pill}
|
||||
</div>
|
||||
|
||||
{/* headline */}
|
||||
@@ -189,17 +205,7 @@ const Hero = ({ headlinePrefix, headlineSuffix, lang = "en" }) => {
|
||||
lineHeight: 1.55,
|
||||
color: "var(--text-dim)",
|
||||
}}>
|
||||
{D.brand.tagline}
|
||||
</p>
|
||||
<p style={{
|
||||
marginTop: 8,
|
||||
maxWidth: 620,
|
||||
fontSize: 14,
|
||||
lineHeight: 1.6,
|
||||
color: "var(--text-faint)",
|
||||
fontFamily: "var(--font-sans)",
|
||||
}}>
|
||||
{D.brand.taglineBn}
|
||||
{lang === "bn" ? D.brand.taglineBn : D.brand.tagline}
|
||||
</p>
|
||||
|
||||
{/* CTAs */}
|
||||
@@ -219,7 +225,7 @@ const Hero = ({ headlinePrefix, headlineSuffix, lang = "en" }) => {
|
||||
onMouseEnter={e => e.currentTarget.style.transform = "translateY(-1px)"}
|
||||
onMouseLeave={e => e.currentTarget.style.transform = "none"}
|
||||
>
|
||||
View Services <Icons.Arrow size={14} />
|
||||
{t.viewServices} <Icons.Arrow size={14} />
|
||||
</a>
|
||||
<a href="#contact" style={{
|
||||
display: "inline-flex",
|
||||
@@ -234,7 +240,7 @@ const Hero = ({ headlinePrefix, headlineSuffix, lang = "en" }) => {
|
||||
borderRadius: 10,
|
||||
textDecoration: "none",
|
||||
}}>
|
||||
Get a Quote <Icons.ArrowUpRight size={14} />
|
||||
{t.getQuote} <Icons.ArrowUpRight size={14} />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -252,7 +258,7 @@ const Hero = ({ headlinePrefix, headlineSuffix, lang = "en" }) => {
|
||||
<span>·</span>
|
||||
<span>{D.brand.domain}</span>
|
||||
<span>·</span>
|
||||
<span>Last shipped: 2 days ago</span>
|
||||
<span>{t.lastShipped}</span>
|
||||
</div>
|
||||
|
||||
{/* metric strip */}
|
||||
@@ -282,7 +288,7 @@ const Hero = ({ headlinePrefix, headlineSuffix, lang = "en" }) => {
|
||||
fontFamily: "var(--font-mono)",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.06em",
|
||||
}}>{m.label}</div>
|
||||
}}>{lang === "bn" ? m.labelBn : m.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
+19
-13
@@ -1,16 +1,23 @@
|
||||
// Top nav — minimal, sticky, blurred — mobile-responsive
|
||||
const NAV_LINKS = [
|
||||
{ id: "services", label: "Services", url: "#/services" },
|
||||
{ id: "case-studies", label: "Case Studies", url: "#/case-studies" },
|
||||
{ id: "pricing", label: "Pricing", url: "#/pricing" },
|
||||
{ id: "blog", label: "Blog", url: "#/blog" },
|
||||
{ id: "contact", label: "Contact", url: "#/contact" },
|
||||
{ id: "services", label: "Services", labelBn: "সার্ভিস", url: "#/services" },
|
||||
{ id: "case-studies", label: "Case Studies", labelBn: "কেস স্টাডি", url: "#/case-studies" },
|
||||
{ id: "pricing", label: "Pricing", labelBn: "মূল্য", url: "#/pricing" },
|
||||
{ id: "blog", label: "Blog", labelBn: "ব্লগ", url: "#/blog" },
|
||||
{ id: "contact", label: "Contact", labelBn: "যোগাযোগ", url: "#/contact" },
|
||||
]
|
||||
|
||||
const NAV_TXT = {
|
||||
en: { search: "Search", getQuote: "Get a Quote", clientLogin: "Client Login" },
|
||||
bn: { search: "খুঁজুন", getQuote: "কোট নিন", clientLogin: "ক্লায়েন্ট লগইন" },
|
||||
};
|
||||
|
||||
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }) => {
|
||||
const [scrolled, setScrolled] = React.useState(false);
|
||||
const [menuOpen, setMenuOpen] = React.useState(false);
|
||||
const links = NAV_LINKS;
|
||||
const t = NAV_TXT[lang] || NAV_TXT.en;
|
||||
const bn = lang === "bn";
|
||||
|
||||
React.useEffect(() => {
|
||||
const onScroll = () => setScrolled(window.scrollY > 12);
|
||||
@@ -72,7 +79,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
e.currentTarget.style.color = isActive ? "var(--text)" : "var(--text-dim)";
|
||||
e.currentTarget.style.background = isActive ? "var(--line)" : "transparent";
|
||||
}}
|
||||
>{l.label}</a>
|
||||
>{bn && l.labelBn ? l.labelBn : l.label}</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
@@ -91,7 +98,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
fontSize: 12.5,
|
||||
}}>
|
||||
<Icons.Search size={13} />
|
||||
<span>Search</span>
|
||||
<span>{t.search}</span>
|
||||
<kbd style={{
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: 10.5,
|
||||
@@ -138,7 +145,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
textDecoration: "none",
|
||||
whiteSpace: "nowrap",
|
||||
}}>
|
||||
Get a Quote
|
||||
{t.getQuote}
|
||||
</a>
|
||||
|
||||
<a href="https://auth.auraajenticai.cloud/login" className="nav-login-btn" style={{
|
||||
@@ -154,7 +161,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
textDecoration: "none",
|
||||
whiteSpace: "nowrap",
|
||||
}}>
|
||||
Client Login <Icons.Arrow size={13} />
|
||||
{t.clientLogin} <Icons.Arrow size={13} />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -196,7 +203,6 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
.nav-search-btn { display: none !important; }
|
||||
.nav-quote-btn { display: none !important; }
|
||||
.nav-badge { display: none !important; }
|
||||
.nav-lang-btn { display: none !important; }
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.nav-login-btn { display: none !important; }
|
||||
@@ -235,7 +241,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
display: "block",
|
||||
borderBottom: "1px solid var(--line)",
|
||||
}}
|
||||
>{l.label}</a>
|
||||
>{bn && l.labelBn ? l.labelBn : l.label}</a>
|
||||
))}
|
||||
<div style={{ display: "flex", gap: 8, marginTop: 14, flexWrap: "wrap" }}>
|
||||
<button onClick={() => { onToggleTheme(); setMenuOpen(false); }} style={{
|
||||
@@ -273,7 +279,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
fontSize: 13,
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>Get a Quote</a>
|
||||
>{t.getQuote}</a>
|
||||
<a
|
||||
href="https://auth.auraajenticai.cloud/login"
|
||||
onClick={() => setMenuOpen(false)}
|
||||
@@ -286,7 +292,7 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
borderRadius: 8,
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>Client Login</a>
|
||||
>{t.clientLogin}</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
+27
-21
@@ -7,9 +7,16 @@ const colorMap = {
|
||||
amber: { bg: "rgba(251, 191, 36, 0.08)", border: "rgba(251, 191, 36, 0.25)", text: "#fcd34d" },
|
||||
};
|
||||
|
||||
const ProjectCard = ({ p }) => {
|
||||
const PROJ_TXT = {
|
||||
en: { liveUseCase: "Live Use Case", noRepo: "No repository linked", viewRepo: "View repository" },
|
||||
bn: { liveUseCase: "লাইভ ব্যবহার দেখুন", noRepo: "রিপোজিটরি যুক্ত নেই", viewRepo: "রিপোজিটরি দেখুন" },
|
||||
};
|
||||
|
||||
const ProjectCard = ({ p, lang = "en" }) => {
|
||||
const tint = colorMap[p.color] || colorMap.violet;
|
||||
const [hover, setHover] = React.useState(false);
|
||||
const t = PROJ_TXT[lang] || PROJ_TXT.en;
|
||||
const bn = lang === "bn";
|
||||
|
||||
return (
|
||||
<article
|
||||
@@ -64,7 +71,7 @@ const ProjectCard = ({ p }) => {
|
||||
letterSpacing: "0.06em",
|
||||
}}>
|
||||
<span style={{ width: 6, height: 6, borderRadius: "50%", background: tint.text }} />
|
||||
{p.kind}
|
||||
{bn ? p.kindBn : p.kind}
|
||||
</div>
|
||||
<div style={{
|
||||
position: "absolute",
|
||||
@@ -76,7 +83,7 @@ const ProjectCard = ({ p }) => {
|
||||
background: tint.bg,
|
||||
border: `1px solid ${tint.border}`,
|
||||
borderRadius: 4,
|
||||
}}>{p.kind}</div>
|
||||
}}>{bn ? p.kindBn : p.kind}</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 24, position: "relative" }}>
|
||||
@@ -85,15 +92,7 @@ const ProjectCard = ({ p }) => {
|
||||
fontSize: 20,
|
||||
fontWeight: 500,
|
||||
letterSpacing: "-0.02em",
|
||||
}}>{p.name}</h3>
|
||||
{p.nameBn && (
|
||||
<div style={{
|
||||
marginTop: 4,
|
||||
fontSize: 12,
|
||||
color: "var(--text-faint)",
|
||||
fontFamily: "var(--font-sans)",
|
||||
}}>{p.nameBn}</div>
|
||||
)}
|
||||
}}>{bn && p.nameBn ? p.nameBn : p.name}</h3>
|
||||
|
||||
<p style={{
|
||||
marginTop: 12,
|
||||
@@ -101,7 +100,7 @@ const ProjectCard = ({ p }) => {
|
||||
fontSize: 14,
|
||||
lineHeight: 1.55,
|
||||
color: "var(--text-dim)",
|
||||
}}>{p.description}</p>
|
||||
}}>{bn && p.descriptionBn ? p.descriptionBn : p.description}</p>
|
||||
|
||||
{/* Stack badges */}
|
||||
<div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 20 }}>
|
||||
@@ -153,7 +152,7 @@ const ProjectCard = ({ p }) => {
|
||||
borderRadius: 8,
|
||||
color: "var(--text-dim)",
|
||||
textDecoration: "none",
|
||||
}} title="View repository"><Icons.Github size={14} /></a>
|
||||
}} title={t.viewRepo}><Icons.Github size={14} /></a>
|
||||
) : (
|
||||
<span style={{
|
||||
width: 34, height: 34,
|
||||
@@ -161,7 +160,7 @@ const ProjectCard = ({ p }) => {
|
||||
border: "1px solid var(--line)",
|
||||
borderRadius: 8,
|
||||
color: "var(--line-strong)",
|
||||
}} title="No repository linked"><Icons.Github size={14} /></span>
|
||||
}} title={t.noRepo}><Icons.Github size={14} /></span>
|
||||
)}
|
||||
{p.demo && (
|
||||
<a href={p.demo} target="_blank" rel="noopener noreferrer" style={{
|
||||
@@ -175,7 +174,7 @@ const ProjectCard = ({ p }) => {
|
||||
fontWeight: 500,
|
||||
textDecoration: "none",
|
||||
cursor: "pointer",
|
||||
}}>Live Use Case <Icons.ArrowUpRight size={12} /></a>
|
||||
}}>{t.liveUseCase} <Icons.ArrowUpRight size={12} /></a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -329,9 +328,12 @@ function mergeServices(local, apiData) {
|
||||
});
|
||||
}
|
||||
|
||||
const Projects = () => {
|
||||
const PROJECTS_NUM_WORDS_BN = ['শূন্য','এক','দুই','তিন','চার','পাঁচ','ছয়','সাত','আট','নয়'];
|
||||
|
||||
const Projects = ({ lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const [services, setServices] = React.useState(D.services);
|
||||
const bn = lang === "bn";
|
||||
|
||||
React.useEffect(() => {
|
||||
const CACHE_KEY = 'aura_svc_v3';
|
||||
@@ -361,10 +363,14 @@ const Projects = () => {
|
||||
<section id="work" style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="What we build"
|
||||
eyebrow={bn ? "আমরা যা বানাই" : "What we build"}
|
||||
num={`03 / 06`}
|
||||
title={<>{['Zero','One','Two','Three','Four','Five','Six','Seven','Eight','Nine'][services.length] || services.length} service{services.length !== 1 ? 's' : ''}. One team. All <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>production-grade</span>.</>}
|
||||
sub="From landing pages to AI agent runtimes — we take your idea from spec to live deployment."
|
||||
title={bn
|
||||
? <>{PROJECTS_NUM_WORDS_BN[services.length] || services.length}টা সার্ভিস। একটাই টিম। সব <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>প্রোডাকশন-গ্রেড</span>।</>
|
||||
: <>{['Zero','One','Two','Three','Four','Five','Six','Seven','Eight','Nine'][services.length] || services.length} service{services.length !== 1 ? 's' : ''}. One team. All <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>production-grade</span>.</>}
|
||||
sub={bn
|
||||
? "ল্যান্ডিং পেজ থেকে এআই এজেন্ট রানটাইম পর্যন্ত — আমরা আপনার আইডিয়া spec থেকে লাইভ ডিপ্লয়মেন্টে নিয়ে যাই।"
|
||||
: "From landing pages to AI agent runtimes — we take your idea from spec to live deployment."}
|
||||
/>
|
||||
|
||||
<div style={{
|
||||
@@ -372,7 +378,7 @@ const Projects = () => {
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
gap: 16,
|
||||
}} className="proj-grid">
|
||||
{services.map(p => <ProjectCard key={p.id} p={p} />)}
|
||||
{services.map(p => <ProjectCard key={p.id} p={p} lang={lang} />)}
|
||||
</div>
|
||||
|
||||
<style>{`
|
||||
|
||||
+94
-36
@@ -28,15 +28,48 @@ const SectionHeader = ({ eyebrow, title, sub, num }) => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const About = () => {
|
||||
const ABOUT_TXT = {
|
||||
en: {
|
||||
eyebrow: "About",
|
||||
title: <>I architect the systems that act — not the demos that <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>impress</span>.</>,
|
||||
glance: "At a glance",
|
||||
startConvo: "Start a conversation",
|
||||
rows: [
|
||||
["Discipline", "Agentic systems · Full-stack"],
|
||||
["Stack range", "TS · Python · Solidity"],
|
||||
["Working with", "Founders · CTOs · Platform leads"],
|
||||
["Engagement", "Embedded · Lead architect"],
|
||||
["Location", "Location"],
|
||||
],
|
||||
years: "shipping",
|
||||
},
|
||||
bn: {
|
||||
eyebrow: "পরিচিতি",
|
||||
title: <>আমি এমন সিস্টেম বানাই যা কাজ করে — যে ডেমো শুধু <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>মুগ্ধ করে</span> তা না।</>,
|
||||
glance: "এক নজরে",
|
||||
startConvo: "কথোপকথন শুরু করুন",
|
||||
rows: [
|
||||
["ডিসিপ্লিন", "এজেন্টিক সিস্টেম · ফুল-স্ট্যাক"],
|
||||
["স্ট্যাক রেঞ্জ", "TS · Python · Solidity"],
|
||||
["কাজ করি", "ফাউন্ডার · CTO · প্ল্যাটফর্ম লিড"],
|
||||
["এনগেজমেন্ট", "এমবেডেড · লিড আর্কিটেক্ট"],
|
||||
["লোকেশন", "Location"],
|
||||
],
|
||||
years: "শিপিং",
|
||||
},
|
||||
};
|
||||
|
||||
const About = ({ lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const bn = lang === "bn";
|
||||
const t = ABOUT_TXT[lang] || ABOUT_TXT.en;
|
||||
return (
|
||||
<section id="about" style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="About"
|
||||
eyebrow={t.eyebrow}
|
||||
num="01 / 06"
|
||||
title={<>I architect the systems that act — not the demos that <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>impress</span>.</>}
|
||||
title={t.title}
|
||||
/>
|
||||
|
||||
<div style={{
|
||||
@@ -51,7 +84,7 @@ const About = () => {
|
||||
lineHeight: 1.65,
|
||||
color: "var(--text-dim)",
|
||||
margin: 0,
|
||||
}}>{D.about.pitch}</p>
|
||||
}}>{bn ? D.about.pitchBn : D.about.pitch}</p>
|
||||
|
||||
<ul style={{
|
||||
marginTop: 32,
|
||||
@@ -60,7 +93,7 @@ const About = () => {
|
||||
display: "grid",
|
||||
gap: 14,
|
||||
}}>
|
||||
{D.about.bullets.map((b, i) => (
|
||||
{(bn ? D.about.bulletsBn : D.about.bullets).map((b, i) => (
|
||||
<li key={i} style={{
|
||||
display: "flex",
|
||||
gap: 14,
|
||||
@@ -82,16 +115,23 @@ const About = () => {
|
||||
|
||||
{/* Side card: at a glance */}
|
||||
<div className="panel" style={{ padding: 28 }}>
|
||||
<div className="eyebrow" style={{ marginBottom: 20 }}>At a glance</div>
|
||||
<div className="eyebrow" style={{ marginBottom: 20 }}>{t.glance}</div>
|
||||
<div style={{ display: "grid", gap: 16 }}>
|
||||
{[
|
||||
{(bn ? [
|
||||
["ডিসিপ্লিন", "এজেন্টিক সিস্টেম · ফুল-স্ট্যাক"],
|
||||
["বছর", `${D.brand.yearsExp}+ শিপিং`],
|
||||
["স্ট্যাক রেঞ্জ", "TS · Python · Solidity"],
|
||||
["কাজ করি", "ফাউন্ডার · CTO · প্ল্যাটফর্ম লিড"],
|
||||
["এনগেজমেন্ট", "এমবেডেড · লিড আর্কিটেক্ট"],
|
||||
["লোকেশন", D.brand.location],
|
||||
] : [
|
||||
["Discipline", "Agentic systems · Full-stack"],
|
||||
["Years", `${D.brand.yearsExp}+ shipping`],
|
||||
["Stack range", "TS · Python · Solidity"],
|
||||
["Working with", "Founders · CTOs · Platform leads"],
|
||||
["Engagement", "Embedded · Lead architect"],
|
||||
["Location", D.brand.location],
|
||||
].map(([k, v]) => (
|
||||
]).map(([k, v]) => (
|
||||
<div key={k} style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "110px 1fr",
|
||||
@@ -113,7 +153,7 @@ const About = () => {
|
||||
fontSize: 13,
|
||||
color: "var(--accent)",
|
||||
}}>
|
||||
Start a conversation <Icons.ArrowUpRight size={13} />
|
||||
{t.startConvo} <Icons.ArrowUpRight size={13} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -128,8 +168,17 @@ const About = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const Skills = () => {
|
||||
const CAT_BN = {
|
||||
"Frontend": "ফ্রন্টএন্ড",
|
||||
"Backend": "ব্যাকএন্ড",
|
||||
"AI / Agents": "এআই / এজেন্ট",
|
||||
"Web3": "ওয়েব৩",
|
||||
"DevOps": "ডেভঅপস",
|
||||
};
|
||||
|
||||
const Skills = ({ lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const bn = lang === "bn";
|
||||
const cats = Object.keys(D.stack);
|
||||
const [active, setActive] = React.useState(cats[0]);
|
||||
const items = D.stack[active];
|
||||
@@ -146,10 +195,10 @@ const Skills = () => {
|
||||
<section id="stack" style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="Stack"
|
||||
eyebrow={bn ? "স্ট্যাক" : "Stack"}
|
||||
num="02 / 06"
|
||||
title="Tools I reach for, weighted by reps."
|
||||
sub="Numbers are honest signal — not a vanity bar. They reflect production hours, not tutorials watched."
|
||||
title={bn ? "যেসব টুল ব্যবহার করি, অভিজ্ঞতা অনুযায়ী।" : "Tools I reach for, weighted by reps."}
|
||||
sub={bn ? "সংখ্যাগুলো সৎ সিগন্যাল — কোনো vanity bar না। এগুলো প্রোডাকশন সময় প্রতিফলিত করে, tutorial দেখা না।" : "Numbers are honest signal — not a vanity bar. They reflect production hours, not tutorials watched."}
|
||||
/>
|
||||
|
||||
{/* Category tabs */}
|
||||
@@ -181,7 +230,7 @@ const Skills = () => {
|
||||
fontWeight: 500,
|
||||
transition: "all 0.15s",
|
||||
}}>
|
||||
<I size={13} /> {c}
|
||||
<I size={13} /> {bn ? CAT_BN[c] || c : c}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
@@ -247,16 +296,19 @@ const TESTIMONIAL_COLORS = {
|
||||
violet: { bg: "rgba(124,92,255,0.08)", border: "rgba(124,92,255,0.22)", text: "#a78bfa" },
|
||||
};
|
||||
|
||||
const Testimonials = () => {
|
||||
const Testimonials = ({ lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const bn = lang === "bn";
|
||||
return (
|
||||
<section style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="Client Results"
|
||||
eyebrow={bn ? "ক্লায়েন্ট ফলাফল" : "Client Results"}
|
||||
num="05 / 06"
|
||||
title={<>What clients say after we <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>ship</span></>}
|
||||
sub="Real projects. Real metrics. No stock-photo testimonials."
|
||||
title={bn
|
||||
? <>শিপ করার পর ক্লায়েন্টরা যা <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>বলে</span></>
|
||||
: <>What clients say after we <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>ship</span></>}
|
||||
sub={bn ? "আসল প্রজেক্ট। আসল মেট্রিক্স। কোনো stock-photo testimonial না।" : "Real projects. Real metrics. No stock-photo testimonials."}
|
||||
/>
|
||||
<div style={{
|
||||
display: "grid",
|
||||
@@ -283,7 +335,7 @@ const Testimonials = () => {
|
||||
<p style={{
|
||||
margin: "0 0 24px", fontSize: 15.5,
|
||||
lineHeight: 1.65, color: "var(--text)",
|
||||
}}>{t.text}</p>
|
||||
}}>{bn && t.textBn ? t.textBn : t.text}</p>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 12 }}>
|
||||
<div style={{
|
||||
width: 40, height: 40, borderRadius: "50%",
|
||||
@@ -331,7 +383,8 @@ const PRODUCT_COLORS = {
|
||||
amber: { bg: "rgba(251,191,36,0.08)", border: "rgba(251,191,36,0.22)", text: "#fde68a" },
|
||||
};
|
||||
|
||||
const OwnProductCard = ({ product }) => {
|
||||
const OwnProductCard = ({ product, lang = "en" }) => {
|
||||
const bn = lang === "bn";
|
||||
const c = PRODUCT_COLORS[product.color] || PRODUCT_COLORS.violet;
|
||||
return (
|
||||
<div className="reveal" style={{
|
||||
@@ -364,7 +417,7 @@ const OwnProductCard = ({ product }) => {
|
||||
boxShadow: "0 0 6px rgba(34,197,94,0.9)", display: "inline-block",
|
||||
animation: "glamour-pulse 2s ease-in-out infinite",
|
||||
}} />
|
||||
LIVE
|
||||
{bn ? "লাইভ" : "LIVE"}
|
||||
</span>
|
||||
{product.badge && (
|
||||
<span style={{
|
||||
@@ -378,7 +431,7 @@ const OwnProductCard = ({ product }) => {
|
||||
padding: "3px 9px", borderRadius: 999,
|
||||
background: "var(--bg-elev)", border: "1px solid var(--line)",
|
||||
marginLeft: "auto",
|
||||
}}>Built by Aura</span>
|
||||
}}>{bn ? "Aura-র তৈরি" : "Built by Aura"}</span>
|
||||
</div>
|
||||
|
||||
{/* Brand name */}
|
||||
@@ -396,19 +449,19 @@ const OwnProductCard = ({ product }) => {
|
||||
margin: 0, fontSize: 11.5, color: "var(--text-faint)",
|
||||
fontFamily: "var(--font-mono)", letterSpacing: "0.1em",
|
||||
textTransform: "uppercase",
|
||||
}}>{product.tagline}</p>
|
||||
}}>{bn && product.taglineBn ? product.taglineBn : product.tagline}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Card body */}
|
||||
<div style={{ padding: "28px 36px 32px", display: "flex", flexDirection: "column", gap: 20, flex: 1 }}>
|
||||
<p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.65, color: "var(--text-dim)" }}>
|
||||
{product.description}
|
||||
{bn && product.descriptionBn ? product.descriptionBn : product.description}
|
||||
</p>
|
||||
|
||||
{/* Top 3 features */}
|
||||
<div style={{ display: "grid", gap: 8 }}>
|
||||
{product.features.slice(0, 3).map((f, i) => (
|
||||
{(bn && product.featuresBn ? product.featuresBn : product.features).slice(0, 3).map((f, i) => (
|
||||
<div key={i} style={{ display: "flex", gap: 10, fontSize: 13, color: "var(--text)" }}>
|
||||
<span style={{ color: c.text, flexShrink: 0, fontSize: 11, marginTop: 2 }}>✓</span>
|
||||
{f}
|
||||
@@ -416,7 +469,7 @@ const OwnProductCard = ({ product }) => {
|
||||
))}
|
||||
{product.features.length > 3 && (
|
||||
<div style={{ fontSize: 12, color: "var(--text-faint)", fontFamily: "var(--font-mono)", paddingLeft: 21 }}>
|
||||
+{product.features.length - 3} more capabilities
|
||||
{bn ? `+${product.features.length - 3}টা আরও ক্ষমতা` : `+${product.features.length - 3} more capabilities`}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -451,7 +504,7 @@ const OwnProductCard = ({ product }) => {
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
|
||||
<polyline points="15,3 21,3 21,9"/><line x1="10" y1="14" x2="21" y2="3"/>
|
||||
</svg>
|
||||
Visit →
|
||||
{bn ? "দেখুন →" : "Visit →"}
|
||||
</a>
|
||||
<a href="#/services/web-app-dev" style={{
|
||||
display: "inline-flex", alignItems: "center", gap: 7,
|
||||
@@ -462,17 +515,18 @@ const OwnProductCard = ({ product }) => {
|
||||
}}
|
||||
onMouseEnter={e => e.currentTarget.style.background = c.bg}
|
||||
onMouseLeave={e => e.currentTarget.style.background = "transparent"}
|
||||
>Build Mine →</a>
|
||||
>{bn ? "আমারটা বানান →" : "Build Mine →"}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const FlagshipProduct = () => {
|
||||
const FlagshipProduct = ({ lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const products = D.ownProducts || [];
|
||||
if (!products.length) return null;
|
||||
const bn = lang === "bn";
|
||||
|
||||
const rose = { bg: "rgba(244,63,94,0.08)", border: "rgba(244,63,94,0.22)", text: "#fda4af" };
|
||||
const violet = { bg: "rgba(124,92,255,0.08)", border: "rgba(124,92,255,0.22)", text: "#a78bfa" };
|
||||
@@ -481,10 +535,14 @@ const FlagshipProduct = () => {
|
||||
<section style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="Our Own Products"
|
||||
eyebrow={bn ? "আমাদের নিজস্ব প্রোডাক্ট" : "Our Own Products"}
|
||||
num="03.5 / 06"
|
||||
title={<>We don't just build for clients — we build for <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>ourselves.</span></>}
|
||||
sub="These are Aura's own live products — real businesses we built, run, and grow. Visit them. That's exactly what we ship for you."
|
||||
title={bn
|
||||
? <>আমরা শুধু ক্লায়েন্টদের জন্য বানাই না — নিজেদের জন্যও <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>বানাই।</span></>
|
||||
: <>We don't just build for clients — we build for <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>ourselves.</span></>}
|
||||
sub={bn
|
||||
? "এগুলো Aura-র নিজস্ব লাইভ প্রোডাক্ট — আসল ব্যবসা যা আমরা বানিয়েছি, চালাই, বড় করছি। ঘুরে দেখুন। এটাই আমরা আপনার জন্য শিপ করি।"
|
||||
: "These are Aura's own live products — real businesses we built, run, and grow. Visit them. That's exactly what we ship for you."}
|
||||
/>
|
||||
|
||||
{/* Products grid */}
|
||||
@@ -493,7 +551,7 @@ const FlagshipProduct = () => {
|
||||
gridTemplateColumns: `repeat(${Math.min(products.length, 2)}, 1fr)`,
|
||||
gap: 20,
|
||||
}}>
|
||||
{products.map(p => <OwnProductCard key={p.id} product={p} />)}
|
||||
{products.map(p => <OwnProductCard key={p.id} product={p} lang={lang} />)}
|
||||
</div>
|
||||
|
||||
{/* Bottom nudge */}
|
||||
@@ -506,13 +564,13 @@ const FlagshipProduct = () => {
|
||||
}}>
|
||||
<div>
|
||||
<span style={{ fontSize: 15, fontWeight: 500, color: "var(--text)" }}>
|
||||
Want Aura to build your product?
|
||||
{bn ? "Aura-কে দিয়ে আপনার প্রোডাক্ট বানাতে চান?" : "Want Aura to build your product?"}
|
||||
</span>
|
||||
<span style={{
|
||||
display: "block", fontSize: 13, color: "var(--text-faint)",
|
||||
marginTop: 3, fontFamily: "var(--font-mono)",
|
||||
}}>
|
||||
E-commerce · AI marketplace · SaaS — from $499 · Delivered in 2–4 weeks
|
||||
{bn ? "ই-কমার্স · এআই মার্কেটপ্লেস · SaaS — $৪৯৯ থেকে শুরু · ২–৪ সপ্তাহে ডেলিভারি" : "E-commerce · AI marketplace · SaaS — from $499 · Delivered in 2–4 weeks"}
|
||||
</span>
|
||||
</div>
|
||||
<a href="#/contact" style={{
|
||||
@@ -520,7 +578,7 @@ const FlagshipProduct = () => {
|
||||
background: "var(--text)", color: "var(--bg)",
|
||||
borderRadius: 9, fontSize: 13.5, fontWeight: 500,
|
||||
textDecoration: "none", whiteSpace: "nowrap", flexShrink: 0,
|
||||
}}>Start a Project →</a>
|
||||
}}>{bn ? "প্রজেক্ট শুরু করুন →" : "Start a Project →"}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+12
-10
@@ -1,14 +1,15 @@
|
||||
// Timeline + Contact + Footer
|
||||
|
||||
const Timeline = () => {
|
||||
const Timeline = ({ lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const bn = lang === "bn";
|
||||
return (
|
||||
<section id="timeline" style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="Trajectory"
|
||||
eyebrow={bn ? "যাত্রাপথ" : "Trajectory"}
|
||||
num="05 / 06"
|
||||
title="Seven years, one through-line: shipping systems that work in production."
|
||||
title={bn ? "সাত বছর, একটাই ধারা: প্রোডাকশনে কাজ করা সিস্টেম শিপ করা।" : "Seven years, one through-line: shipping systems that work in production."}
|
||||
/>
|
||||
|
||||
<div style={{ position: "relative", paddingLeft: 32 }}>
|
||||
@@ -69,7 +70,7 @@ const Timeline = () => {
|
||||
fontSize: 10.5,
|
||||
color: "var(--text-dim)",
|
||||
fontFamily: "var(--font-mono)",
|
||||
}}>{e.kind}</span>
|
||||
}}>{bn ? e.kindBn : e.kind}</span>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style={{
|
||||
@@ -77,7 +78,7 @@ const Timeline = () => {
|
||||
fontSize: 19,
|
||||
fontWeight: 500,
|
||||
letterSpacing: "-0.01em",
|
||||
}}>{e.role}</h3>
|
||||
}}>{bn ? e.roleBn : e.role}</h3>
|
||||
<div style={{
|
||||
marginTop: 4,
|
||||
fontSize: 14,
|
||||
@@ -90,7 +91,7 @@ const Timeline = () => {
|
||||
lineHeight: 1.6,
|
||||
color: "var(--text-dim)",
|
||||
maxWidth: 600,
|
||||
}}>{e.detail}</p>
|
||||
}}>{bn ? e.detailBn : e.detail}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -526,8 +527,9 @@ const ChatbotWidget = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const Footer = () => {
|
||||
const Footer = ({ lang = "en" }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const bn = lang === "bn";
|
||||
return (
|
||||
<footer style={{
|
||||
borderTop: "1px solid var(--line)",
|
||||
@@ -545,10 +547,10 @@ const Footer = () => {
|
||||
<span style={{ fontSize: 13, color: "var(--text-dim)" }}>{D.brand.name} · {D.brand.domain}</span>
|
||||
</div>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 20 }}>
|
||||
<a href="#/privacy" style={{ fontSize: 12.5, color: "var(--text-dim)" }}>Privacy</a>
|
||||
<a href="#/terms" style={{ fontSize: 12.5, color: "var(--text-dim)" }}>Terms</a>
|
||||
<a href="#/privacy" style={{ fontSize: 12.5, color: "var(--text-dim)" }}>{bn ? "প্রাইভেসি" : "Privacy"}</a>
|
||||
<a href="#/terms" style={{ fontSize: 12.5, color: "var(--text-dim)" }}>{bn ? "শর্তাবলী" : "Terms"}</a>
|
||||
<div style={{ fontSize: 12, color: "var(--text-faint)", fontFamily: "var(--font-mono)" }}>
|
||||
© 2026 — Built with intent.
|
||||
{bn ? "© ২০২৬ — যত্ন করে তৈরি।" : "© 2026 — Built with intent."}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user