// Projects — SaaS-card grid with featured first const colorMap = { violet: { bg: "rgba(124, 92, 255, 0.08)", border: "rgba(124, 92, 255, 0.25)", text: "#a18bff" }, cyan: { bg: "rgba(0, 212, 255, 0.08)", border: "rgba(0, 212, 255, 0.25)", text: "#5ee0ff" }, green: { bg: "rgba(74, 222, 128, 0.08)", border: "rgba(74, 222, 128, 0.25)", text: "#7ee8a3" }, amber: { bg: "rgba(251, 191, 36, 0.08)", border: "rgba(251, 191, 36, 0.25)", text: "#fcd34d" }, }; const ProjectCard = ({ p }) => { const tint = colorMap[p.color] || colorMap.violet; const [hover, setHover] = React.useState(false); return (
setHover(true)} onMouseLeave={() => setHover(false)} style={{ position: "relative", gridColumn: "span 1", background: "var(--bg-card)", border: "1px solid var(--line)", borderRadius: 16, overflow: "hidden", cursor: "pointer", transition: "all 0.25s ease", transform: hover ? "translateY(-2px)" : "none", boxShadow: hover ? `0 24px 60px -20px ${tint.border}` : "none", }}> {/* hover sheen */}
{/* Decorative top — small visual specific to service type */}
{p.kind}
{p.kind}

{p.name}

{p.nameBn && (
{p.nameBn}
)}

{p.description}

{/* Stack badges */}
{p.stack.map(s => ( {s} ))}
{/* Footer: impact + actions */}
{p.impact.primary}
{p.impact.secondary}
{p.gitRepo ? ( ) : ( )} {p.demo && ( Demo )}
); }; // Tiny SVG visual per service — gives each card a distinct "product preview" const ProjectVisual = ({ id, tint, hover }) => { if (id === "ai-agent-automation") { return ( {/* nodes */} {[ [120, 60], [220, 110], [320, 70], [420, 130], [500, 90], [180, 160], [280, 180], [380, 50], [460, 180], ].map(([x, y], i) => ( ))} {/* connectors */} ); } if (id === "scraping-data-pipeline") { // bar chart const bars = [40, 64, 52, 78, 92, 70, 110, 95, 130, 118, 142]; return ( {bars.map((h, i) => ( ))} ); } if (id === "web3-blockchain") { // chain dots const chains = ["ETH","ARB","OP","BASE","SOL","ZK","POL","BNB","AVAX","CELO","XLM","TRX"]; return (
{chains.map((c, i) => (
{c}
))}
); } if (id === "mt5-ea-trading") { // line chart return ( {[60,180,300,420,540].map((x, i) => ( ))} ); } if (id === "web-app-dev") { // schema → grid morph return ( {/* schema box */} {[20, 40, 60, 80].map(y => )} {[20, 40, 60, 80].map(y => )} {/* arrow */} {/* dashboard grid */} ); } if (id === "infra-devops") { // chat bubbles return (
How do I rotate my API key?
Settings → API → Rotate. New key live in <5s.
); } return null; }; // Merge Dashboard API data (demo/git links, active state) into local static data function mergeServices(local, apiData) { const byId = {}; apiData.forEach(s => { byId[s.serviceId] = s; }); return local .filter(s => !byId[s.id] || byId[s.id].isActive !== false) .map(s => { const api = byId[s.id]; if (!api) return s; return { ...s, demo: api.demoUrl || s.demo || null, gitRepo: api.gitRepo || null, name: api.name || s.name, nameBn: api.nameBn || s.nameBn, impact: { primary: api.impactPrimary || s.impact.primary, secondary: api.impactSecondary || s.impact.secondary, }, }; }); } const Projects = () => { const D = PORTFOLIO_DATA; const [services, setServices] = React.useState(D.services); React.useEffect(() => { const CACHE_KEY = 'aura_services_v2'; const CACHE_TTL = 60 * 1000; const cached = sessionStorage.getItem(CACHE_KEY); if (cached) { try { const { data, ts } = JSON.parse(cached); if (Date.now() - ts < CACHE_TTL && data.length > 0) { setServices(mergeServices(D.services, data)); return; } } catch {} } fetch('https://aura.auraajenticai.cloud/api/public/services', { signal: AbortSignal.timeout(3000) }) .then(r => r.ok ? r.json() : null) .then(data => { if (Array.isArray(data) && data.length > 0) { sessionStorage.setItem(CACHE_KEY, JSON.stringify({ data, ts: Date.now() })); setServices(mergeServices(D.services, data)); } }) .catch(() => {}); }, []); return (
Six services. One team. All production-grade.} sub="From landing pages to AI agent runtimes — we take your idea from spec to live deployment." />
{services.map(p => )}
); }; window.Projects = Projects;