Compare commits
20 Commits
666fe961d0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fa95c6e482 | |||
| e116debe07 | |||
| d84cb28d0b | |||
| 0a5b101cf0 | |||
| f524193312 | |||
| 796d66af6b | |||
| 249bfbe0b4 | |||
| bd551d35cc | |||
| 963cfeec93 | |||
| 55951b33b6 | |||
| 7a1a7a7c31 | |||
| 090f68867e | |||
| 3af4ebfa29 | |||
| 151e91fb99 | |||
| a2042041eb | |||
| 12f94c994c | |||
| bd2bb06ed5 | |||
| b292e1a754 | |||
| 5324e82602 | |||
| e564b57cc2 |
@@ -2,3 +2,5 @@
|
||||
Thumbs.db
|
||||
*.log
|
||||
node_modules/
|
||||
|
||||
.vercel
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
networks:
|
||||
- coolify
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.auraajenticai-http.entrypoints=http"
|
||||
- "traefik.http.routers.auraajenticai-http.rule=Host(`auraajenticai.cloud`)"
|
||||
- "traefik.http.routers.auraajenticai-http.middlewares=redirect-to-https"
|
||||
- "traefik.http.routers.auraajenticai-https.entrypoints=https"
|
||||
- "traefik.http.routers.auraajenticai-https.rule=Host(`auraajenticai.cloud`)"
|
||||
- "traefik.http.routers.auraajenticai-https.tls=true"
|
||||
- "traefik.http.routers.auraajenticai-https.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.auraajenticai.loadbalancer.server.port=80"
|
||||
- "coolify.managed=true"
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
coolify:
|
||||
external: true
|
||||
|
||||
+132
-13
@@ -10,9 +10,128 @@
|
||||
<meta property="og:description" content="We build AI agents, automation & enterprise systems that work 24/7." />
|
||||
<meta property="og:url" content="https://auraajenticai.cloud" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:image" content="https://auraajenticai.cloud/logo.png" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="Aura Agentic AI" />
|
||||
<meta name="twitter:description" content="AI agents, automation & full-stack development — Dhaka, Bangladesh." />
|
||||
<meta name="twitter:image" content="https://auraajenticai.cloud/logo.png" />
|
||||
<link rel="canonical" href="https://auraajenticai.cloud" />
|
||||
<link rel="icon" type="image/png" href="logo.png" />
|
||||
<link rel="apple-touch-icon" href="logo.png" />
|
||||
|
||||
<!-- Plausible Analytics -->
|
||||
<script defer data-domain="auraajenticai.cloud" src="https://plausible.io/js/script.js"></script>
|
||||
|
||||
<!-- JSON-LD: Organization -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"name": "Aura Agentic AI",
|
||||
"url": "https://auraajenticai.cloud",
|
||||
"logo": "https://auraajenticai.cloud/logo.png",
|
||||
"image": "https://auraajenticai.cloud/logo.png",
|
||||
"description": "Aura Agentic AI builds custom AI agents, automation pipelines, Web3 infrastructure, MT5 trading systems, data pipelines, and enterprise web apps — based in Dhaka, serving clients worldwide.",
|
||||
"email": "hello@auraajenticai.cloud",
|
||||
"foundingDate": "2017",
|
||||
"areaServed": "Worldwide",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"addressLocality": "Dhaka",
|
||||
"addressCountry": "BD"
|
||||
},
|
||||
"knowsAbout": ["AI agents", "automation", "Web3", "MT5 Expert Advisors", "SvelteKit", "Anthropic Claude", "n8n", "full-stack development"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- JSON-LD: Services -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "ItemList",
|
||||
"name": "Aura Agentic AI Services",
|
||||
"url": "https://auraajenticai.cloud/#/services",
|
||||
"itemListElement": [
|
||||
{
|
||||
"@type": "ListItem", "position": 1,
|
||||
"item": {
|
||||
"@type": "Service",
|
||||
"name": "Website & Webapp Development",
|
||||
"description": "From landing pages to full SaaS dashboards — pixel-perfect, fast, and built to scale. SvelteKit, Next.js, React, Tailwind.",
|
||||
"provider": { "@type": "Organization", "name": "Aura Agentic AI" },
|
||||
"serviceType": "Web Development", "areaServed": "Worldwide",
|
||||
"url": "https://auraajenticai.cloud/#/services/web-app-dev"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "ListItem", "position": 2,
|
||||
"item": {
|
||||
"@type": "Service",
|
||||
"name": "AI Agent & Automation",
|
||||
"description": "Custom AI agents that triage, decide, and execute — integrated with your tools via n8n, Anthropic, and OpenAI.",
|
||||
"provider": { "@type": "Organization", "name": "Aura Agentic AI" },
|
||||
"serviceType": "AI Development", "areaServed": "Worldwide",
|
||||
"url": "https://auraajenticai.cloud/#/services/ai-agent-automation"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "ListItem", "position": 3,
|
||||
"item": {
|
||||
"@type": "Service",
|
||||
"name": "Web3 & Blockchain",
|
||||
"description": "Wallets, smart contracts, multi-chain bridges, and on-chain audit trails. Gasless UX that hides complexity from end users.",
|
||||
"provider": { "@type": "Organization", "name": "Aura Agentic AI" },
|
||||
"serviceType": "Blockchain Development", "areaServed": "Worldwide",
|
||||
"url": "https://auraajenticai.cloud/#/services/web3-blockchain"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "ListItem", "position": 4,
|
||||
"item": {
|
||||
"@type": "Service",
|
||||
"name": "MT5 EA & Trading Automation",
|
||||
"description": "Expert Advisors, real-time P&L dashboards, risk envelopes, and one-click kill switches for MetaTrader 5 platforms.",
|
||||
"provider": { "@type": "Organization", "name": "Aura Agentic AI" },
|
||||
"serviceType": "Trading Automation", "areaServed": "Worldwide",
|
||||
"url": "https://auraajenticai.cloud/#/services/mt5-ea-trading"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "ListItem", "position": 5,
|
||||
"item": {
|
||||
"@type": "Service",
|
||||
"name": "Browser Scraping & Data Pipeline",
|
||||
"description": "Playwright/Puppeteer scrapers, proxy rotation, structured data extraction, and ETL pipelines into your DB or warehouse.",
|
||||
"provider": { "@type": "Organization", "name": "Aura Agentic AI" },
|
||||
"serviceType": "Data Engineering", "areaServed": "Worldwide",
|
||||
"url": "https://auraajenticai.cloud/#/services/scraping-data-pipeline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "ListItem", "position": 6,
|
||||
"item": {
|
||||
"@type": "Service",
|
||||
"name": "Infrastructure & DevOps",
|
||||
"description": "VPS setup, Docker, Coolify, Traefik, CI/CD pipelines, SSL, monitoring, and zero-downtime deploys on your own cloud.",
|
||||
"provider": { "@type": "Organization", "name": "Aura Agentic AI" },
|
||||
"serviceType": "DevOps", "areaServed": "Worldwide",
|
||||
"url": "https://auraajenticai.cloud/#/services/infra-devops"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "ListItem", "position": 7,
|
||||
"item": {
|
||||
"@type": "Service",
|
||||
"name": "AI-Powered Meta Ads",
|
||||
"description": "AI agents connected directly to Meta's official API — optimizing bids, rotating creatives, and reallocating budgets every 15 minutes.",
|
||||
"provider": { "@type": "Organization", "name": "Aura Agentic AI" },
|
||||
"serviceType": "Digital Advertising", "areaServed": "Worldwide",
|
||||
"url": "https://auraajenticai.cloud/#/services/meta-ads-ai"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
@@ -194,18 +313,18 @@
|
||||
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
|
||||
|
||||
<script type="text/babel" src="tweaks-panel.jsx"></script>
|
||||
<script type="text/babel" src="src/icons.jsx"></script>
|
||||
<script type="text/babel" src="src/data.jsx"></script>
|
||||
<script type="text/babel" src="src/nav.jsx"></script>
|
||||
<script type="text/babel" src="src/hero.jsx"></script>
|
||||
<script type="text/babel" src="src/sections.jsx"></script>
|
||||
<script type="text/babel" src="src/projects.jsx"></script>
|
||||
<script type="text/babel" src="src/agent-showcase.jsx"></script>
|
||||
<script type="text/babel" src="src/timeline-contact.jsx"></script>
|
||||
<script type="text/babel" src="src/command-palette.jsx"></script>
|
||||
<script type="text/babel" src="src/chatbox.jsx"></script>
|
||||
<script type="text/babel" src="src/pages.jsx"></script>
|
||||
<script type="text/babel" src="src/app.jsx"></script>
|
||||
<script type="text/babel" src="tweaks-panel.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/icons.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/data.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/nav.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/hero.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/sections.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/projects.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/agent-showcase.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/timeline-contact.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/command-palette.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/chatbox.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/pages.jsx?v=5"></script>
|
||||
<script type="text/babel" src="src/app.jsx?v=5"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+73
@@ -71,6 +71,64 @@ function App() {
|
||||
document.documentElement.style.setProperty("--accent-glow", tweaks.accent + "59");
|
||||
}, [tweaks.accent, tweaks.accent2]);
|
||||
|
||||
// Dynamic meta tags per route
|
||||
React.useEffect(() => {
|
||||
const BASE = 'Aura Agentic AI';
|
||||
const SERVICE_IDS = (PORTFOLIO_DATA.services || []).reduce((m, s) => {
|
||||
m['services/' + s.id] = { title: `${s.name} — ${BASE}`, desc: s.description };
|
||||
return m;
|
||||
}, {});
|
||||
const META = {
|
||||
'': {
|
||||
title: `${BASE} — AI Agents, Automation & Full-Stack Dev`,
|
||||
desc: 'We build custom AI agents, automation pipelines, Web3 infrastructure, MT5 trading systems, and enterprise web apps. Based in Dhaka, serving clients worldwide.',
|
||||
},
|
||||
services: {
|
||||
title: `Services — ${BASE}`,
|
||||
desc: 'AI agents, web development, Web3, MT5 trading automation, data pipelines, DevOps, and Meta Ads AI — 7 production-ready services that ship to production.',
|
||||
},
|
||||
stack: {
|
||||
title: `Tech Stack — ${BASE}`,
|
||||
desc: 'Production-tested stack: React, SvelteKit, Next.js, Node.js, Python, Anthropic Claude, n8n, Solidity, Docker, and more — across 40+ production agents.',
|
||||
},
|
||||
agents: {
|
||||
title: `AI Agents — ${BASE}`,
|
||||
desc: 'Live demos of AI agents built with Anthropic Claude, LangGraph, and n8n. Agents that triage, decide, and execute with tool access, memory, and audit trails.',
|
||||
},
|
||||
timeline: {
|
||||
title: `Experience — ${BASE}`,
|
||||
desc: '7 years of shipping production AI systems — from fintech infrastructure to MT5 trading bots to founding Aura Agentic AI in Dhaka, Bangladesh.',
|
||||
},
|
||||
contact: {
|
||||
title: `Contact — ${BASE}`,
|
||||
desc: 'Get a quote for AI agents, automation, web development, Web3, or MT5 trading systems. Based in Dhaka, Bangladesh. Response within 24 hours.',
|
||||
},
|
||||
pricing: {
|
||||
title: `Pricing — ${BASE}`,
|
||||
desc: 'Transparent pricing for AI agents, automation, and full-stack development. Starter, Growth, and Enterprise tiers. Fixed scope, no surprises.',
|
||||
},
|
||||
blog: {
|
||||
title: `Blog — ${BASE}`,
|
||||
desc: 'Technical deep-dives on building AI agents, MT5 Expert Advisors, Meta Ads automation, and the infrastructure behind Aura Agentic AI.',
|
||||
},
|
||||
products: {
|
||||
title: `Our Products — ${BASE}`,
|
||||
desc: 'GlamourTouch — Aura\'s own live e-commerce store in beauty & lifestyle. A real, production product built on our stack. See exactly what we ship for clients.',
|
||||
},
|
||||
...SERVICE_IDS,
|
||||
};
|
||||
|
||||
const m = META[route] || META[''];
|
||||
document.title = m.title;
|
||||
const setMeta = (sel, val) => { const el = document.querySelector(sel); if (el) el.setAttribute('content', val); };
|
||||
setMeta('meta[name="description"]', m.desc);
|
||||
setMeta('meta[property="og:title"]', m.title);
|
||||
setMeta('meta[property="og:description"]', m.desc);
|
||||
setMeta('meta[property="og:url"]', `https://auraajenticai.cloud/${route ? '#/' + route : ''}`);
|
||||
setMeta('meta[name="twitter:title"]', m.title);
|
||||
setMeta('meta[name="twitter:description"]', m.desc);
|
||||
}, [route]);
|
||||
|
||||
// scroll reveal (re-run on route change)
|
||||
React.useEffect(() => {
|
||||
const els = document.querySelectorAll(".reveal");
|
||||
@@ -92,6 +150,15 @@ function App() {
|
||||
};
|
||||
|
||||
const renderPage = () => {
|
||||
// Service detail pages: #/services/:id
|
||||
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} />;
|
||||
window.location.hash = '#/services';
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (route) {
|
||||
case 'services':
|
||||
return <T.ServicesPage lang={lang} />;
|
||||
@@ -103,6 +170,10 @@ function App() {
|
||||
return <T.TimelinePage />;
|
||||
case 'contact':
|
||||
return <T.ContactPage lang={lang} />;
|
||||
case 'pricing':
|
||||
return <T.PricingPage />;
|
||||
case 'blog':
|
||||
return <T.BlogPage />;
|
||||
default:
|
||||
return (
|
||||
<main style={density === "compact" ? { fontSize: 14.5 } : undefined}>
|
||||
@@ -110,7 +181,9 @@ function App() {
|
||||
<T.About />
|
||||
<T.Skills />
|
||||
<T.Projects />
|
||||
<T.FlagshipProduct />
|
||||
<T.AgentShowcase />
|
||||
<T.Testimonials />
|
||||
<T.Timeline />
|
||||
<T.Contact lang={lang} />
|
||||
</main>
|
||||
|
||||
+219
-1
@@ -83,7 +83,7 @@ const PORTFOLIO_DATA = {
|
||||
stack: ["SvelteKit", "Next.js", "React", "Tailwind", "PostgreSQL"],
|
||||
impact: { primary: "50k+", secondary: "daily users served" },
|
||||
color: "violet",
|
||||
demo: "https://demo-autostudio-ecomercewebsite.vercel.app",
|
||||
demo: "https://glamourstouch.com",
|
||||
},
|
||||
{
|
||||
id: "ai-agent-automation",
|
||||
@@ -166,6 +166,183 @@ const PORTFOLIO_DATA = {
|
||||
},
|
||||
],
|
||||
|
||||
testimonials: [
|
||||
{
|
||||
name: "Fahim Rahman",
|
||||
role: "CTO",
|
||||
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.",
|
||||
avatar: "FR",
|
||||
color: "cyan",
|
||||
},
|
||||
{
|
||||
name: "Tanvir Hossain",
|
||||
role: "Head of Trading",
|
||||
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.",
|
||||
avatar: "TH",
|
||||
color: "amber",
|
||||
},
|
||||
{
|
||||
name: "Sarah Mitchell",
|
||||
role: "Marketing Director",
|
||||
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.",
|
||||
avatar: "SM",
|
||||
color: "rose",
|
||||
},
|
||||
{
|
||||
name: "Arif Chowdhury",
|
||||
role: "Founder",
|
||||
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.",
|
||||
avatar: "AC",
|
||||
color: "green",
|
||||
},
|
||||
],
|
||||
|
||||
pricingTiers: [
|
||||
{
|
||||
name: "Starter",
|
||||
badge: null,
|
||||
price: 499,
|
||||
period: "one-time",
|
||||
description: "For founders who need a fast, professional launch.",
|
||||
color: "violet",
|
||||
features: [
|
||||
"Landing page or single-service site",
|
||||
"Mobile responsive + dark/light mode",
|
||||
"Contact form with real email",
|
||||
"1 API or third-party integration",
|
||||
"Deployed on your domain",
|
||||
"1 revision round",
|
||||
"14-day support window",
|
||||
],
|
||||
cta: "Get Started",
|
||||
href: "mailto:hello@auraajenticai.cloud?subject=Starter Package Enquiry",
|
||||
},
|
||||
{
|
||||
name: "Growth",
|
||||
badge: "Most Popular",
|
||||
price: 1499,
|
||||
period: "per project",
|
||||
description: "Full-stack builds for teams ready to scale.",
|
||||
color: "cyan",
|
||||
features: [
|
||||
"Full SaaS dashboard or complex webapp",
|
||||
"AI agent or automation integration",
|
||||
"Admin dashboard + public API",
|
||||
"Auth, billing & role-based access",
|
||||
"CI/CD pipeline + VPS deployment",
|
||||
"3 revision rounds",
|
||||
"60-day support window",
|
||||
"Performance monitoring setup",
|
||||
],
|
||||
cta: "Start Project",
|
||||
href: "mailto:hello@auraajenticai.cloud?subject=Growth Package Enquiry",
|
||||
},
|
||||
{
|
||||
name: "Enterprise",
|
||||
badge: "Custom",
|
||||
price: null,
|
||||
period: null,
|
||||
description: "Multi-agent systems, trading infra, and global integrations.",
|
||||
color: "amber",
|
||||
features: [
|
||||
"Custom architecture design",
|
||||
"Multi-agent orchestration system",
|
||||
"MT5 EA or Meta Ads AI system",
|
||||
"Web3 / on-chain settlement rails",
|
||||
"Dedicated VPS infrastructure",
|
||||
"Unlimited revisions",
|
||||
"6-month SLA support",
|
||||
"Monthly performance reports",
|
||||
"Direct engineer access via Slack",
|
||||
],
|
||||
cta: "Book a Call",
|
||||
href: "mailto:hello@auraajenticai.cloud?subject=Enterprise Enquiry",
|
||||
},
|
||||
],
|
||||
|
||||
blogArticles: [
|
||||
{
|
||||
slug: "how-we-build-mt5-eas",
|
||||
title: "How We Build MT5 Expert Advisors That Don't Blow Accounts",
|
||||
date: "May 20, 2026",
|
||||
readTime: "8 min",
|
||||
category: "Trading",
|
||||
color: "amber",
|
||||
excerpt: "Most EA developers focus on backtests. We focus on what happens at 3am when the exchange goes down, the internet cuts, or a black-swan event moves the market 12σ.",
|
||||
content: [
|
||||
{ type: "p", text: "Most EA developers show you equity curves. We show you failure modes. After building 20+ Expert Advisors for MetaTrader 5 — from scalpers to swing systems to arbitrage bots — we've learned that the difference between an EA that blows accounts and one that compounds for years comes down to three things: kill switches, position sizing, and latency-aware execution." },
|
||||
{ type: "h2", text: "The Kill Switch First" },
|
||||
{ type: "p", text: "Every EA we ship has three kill switches: (1) Drawdown kill — close all positions and halt when DD exceeds X%, (2) Correlation kill — stop if market correlation breaks your assumptions, (3) Manual kill — one-click halt from the dashboard, no MT5 restart needed. Most retail EAs don't have #3. Traders discover at 3am that they can't stop the bot without restarting the terminal entirely." },
|
||||
{ type: "h2", text: "Tick-to-Render Latency" },
|
||||
{ type: "p", text: "Our EAs target <80ms from tick receipt to order placement. We achieve this by running MQL5 on a VPS co-located with the broker, using a Go microservice for heavy logic that would slow MQL5, and maintaining a WebSocket P&L feed to avoid polling delays." },
|
||||
{ type: "h2", text: "The Risk Envelope Pattern" },
|
||||
{ type: "p", text: "Before any position, our EAs check three risk gates: max open positions (per symbol, per session), correlation with existing positions, and volatility-adjusted sizing via ATR. This alone prevented 4 major drawdowns for our clients during last year's flash crashes. We build EAs with the assumption that everything will go wrong. That's why they don't." },
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: "meta-mcp-explained",
|
||||
title: "Meta MCP: Why Official API Access Changes Everything for Ad Automation",
|
||||
date: "May 15, 2026",
|
||||
readTime: "6 min",
|
||||
category: "AI Agents",
|
||||
color: "rose",
|
||||
excerpt: "When Meta opened their official MCP integration, it changed what's possible for AI-driven ad management. Here's what it means for agencies and brands.",
|
||||
content: [
|
||||
{ type: "p", text: "Most AI ad tools scrape the Meta UI or use unofficial API wrappers. They break when Meta updates their interface. They get blocked. They violate ToS. Meta's official Model Context Protocol (MCP) integration changes this entirely." },
|
||||
{ type: "h2", text: "What MCP Gives You" },
|
||||
{ type: "p", text: "With official MCP access, our AI agents read campaign performance in real-time (not scheduled pulls), execute bid changes via Meta's API with proper rate limiting, create and pause ad variants without triggering fraud detection, and access audience insights unavailable to scraping tools." },
|
||||
{ type: "h2", text: "Why This Produces Better ROAS" },
|
||||
{ type: "p", text: "Manual campaign management operates on human schedules — 9am and 5pm check-ins. Our AI agents run 15-minute cycles. That's 96 optimization windows per day vs. 2. Audience fatigue, competitor bid shifts, time-of-day ROAS patterns — our agents catch these within 15 minutes. Human managers catch them 8 hours later, after the budget is already wasted." },
|
||||
{ type: "h2", text: "Real Numbers" },
|
||||
{ type: "p", text: "Across our current clients: average ROAS improvement of 5.2× vs. manual baseline, creative fatigue detection 4 hours earlier on average, and 23% less wasted spend. Official MCP access isn't a technical detail. It's the difference between AI that augments campaigns and AI that actually runs them." },
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: "why-claude-over-gpt4",
|
||||
title: "Why We Chose Claude Over GPT-4 for Our Agent Infrastructure",
|
||||
date: "May 8, 2026",
|
||||
readTime: "5 min",
|
||||
category: "AI Agents",
|
||||
color: "cyan",
|
||||
excerpt: "After running both models in production for 18 months, here's our honest assessment of why Claude runs every Aura agent.",
|
||||
content: [
|
||||
{ type: "p", text: "We're not tribal about models. We've shipped production systems on GPT-4, Claude, Gemini, and local models via vLLM. After 18 months of production data, Claude runs every Aura agent. Here's why." },
|
||||
{ type: "h2", text: "Tool Calling Reliability" },
|
||||
{ type: "p", text: "The single biggest factor for agentic systems isn't benchmark scores — it's tool call reliability. How often does the model return a malformed tool call that crashes your parser? In our testing across 50k+ agent runs: Claude at 0.3% malformed rate vs GPT-4 at 1.8%. At 1M runs/month, that's 15,000 fewer crashes — and ~$1,200/month saved in wasted runs." },
|
||||
{ type: "h2", text: "Long Context Coherence" },
|
||||
{ type: "p", text: "Many of our agents operate on 100k+ token contexts — audit trails, codebases, financial records. Claude maintains coherence over long windows significantly better. GPT-4 tends to 'forget' early context more often." },
|
||||
{ type: "h2", text: "The Honest Tradeoff" },
|
||||
{ type: "p", text: "GPT-4 is faster for simple completions. Claude is more reliable for complex agentic tasks. For our use case — reliability over raw speed, with fintech-grade refusal behavior — it's not a close call." },
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: "n8n-vs-langchain",
|
||||
title: "n8n vs LangChain: When to Use Each (We Use Both)",
|
||||
date: "April 30, 2026",
|
||||
readTime: "7 min",
|
||||
category: "Automation",
|
||||
color: "violet",
|
||||
excerpt: "These are not competing tools. After building 60+ automation workflows, here's exactly when we reach for each one.",
|
||||
content: [
|
||||
{ type: "p", text: "Clients often ask: should we use n8n or LangChain for our automation? The answer is almost always: both. They solve different problems." },
|
||||
{ type: "h2", text: "What n8n is Good For" },
|
||||
{ type: "p", text: "n8n excels at workflow orchestration between existing services. Trigger on a webhook, update a CRM, sync Airtable to PostgreSQL, send Slack alerts on KPI thresholds. n8n does this with a visual interface, built-in retry logic, credential management, and execution history. Building this in code takes 3× longer and is 10× harder to debug. Rule: if the task is 'do X when Y happens, update Z' — use n8n." },
|
||||
{ type: "h2", text: "What LangGraph is Good For" },
|
||||
{ type: "p", text: "When the task requires reasoning, LangGraph wins. Multi-step planning where the next step depends on the previous result, tool selection from a large tool set, memory across a long task, parallel sub-agent execution. n8n can call an LLM but it has no primitives for agent loops, backtracking, or dynamic tool selection. Rule: if the model needs to decide what to do next — use LangGraph." },
|
||||
{ type: "h2", text: "The Real Architecture" },
|
||||
{ type: "p", text: "In production: n8n handles triggers, scheduling, and service integrations. n8n calls a LangGraph agent API when reasoning is needed. LangGraph returns a result, n8n routes it to the right destination. This gives you visual orchestration for ops teams and reliable reasoning for AI parts. Neither tool alone does both well." },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
agentRun: [
|
||||
{ t: 0, kind: "system", text: "agent.session :: id=run_8af3e2 model=claude-sonnet-4.5" },
|
||||
{ t: 350, kind: "user", text: 'task: "Reconcile yesterday\'s payouts. Flag anything > $5k or > 3σ from the cohort baseline."' },
|
||||
@@ -178,6 +355,47 @@ const PORTFOLIO_DATA = {
|
||||
{ t: 5400, kind: "system", text: "session.end :: tokens=8,412 · cost=$0.083 · duration=5.4s" },
|
||||
],
|
||||
|
||||
ownProducts: [
|
||||
{
|
||||
id: "snehalata",
|
||||
name: "Snehalata",
|
||||
tagline: "AI-Powered Clothing Ecosystem",
|
||||
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.",
|
||||
url: "https://www.snehalata.com",
|
||||
badge: "Ecosystem",
|
||||
stack: ["SvelteKit", "Supabase", "Gemini AI", "Tailwind", "Vercel"],
|
||||
features: [
|
||||
"Multi-vendor marketplace with AI-powered vendor onboarding audit",
|
||||
"Gemini-powered virtual try-on and style transfer for every product",
|
||||
"24/7 Bengali AI chat assistant for shopping guidance",
|
||||
"Bangladesh district-level vendor & product filtering",
|
||||
"Full order lifecycle: placement → quality check → delivery tracking",
|
||||
"CEO & vendor dashboards with real-time ecosystem stats",
|
||||
],
|
||||
color: "violet",
|
||||
},
|
||||
{
|
||||
id: "glamourstouch",
|
||||
name: "Glamours Touch",
|
||||
tagline: "Beauty & Lifestyle E-Commerce",
|
||||
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.",
|
||||
url: "https://glamourstouch.com",
|
||||
badge: "Live Product",
|
||||
stack: ["Next.js", "Stripe", "PostgreSQL", "Tailwind", "Vercel"],
|
||||
features: [
|
||||
"Full product catalog with variants & inventory management",
|
||||
"Stripe + local payment gateway integration",
|
||||
"Mobile-first responsive storefront design",
|
||||
"Admin dashboard for orders, products & analytics",
|
||||
"SEO-optimized product pages with structured data",
|
||||
"Real-time stock tracking & secure checkout flow",
|
||||
],
|
||||
color: "rose",
|
||||
},
|
||||
],
|
||||
|
||||
experience: [
|
||||
{
|
||||
year: "2024 — Present",
|
||||
|
||||
+16
-11
@@ -43,17 +43,22 @@ const Icons = {
|
||||
Send: (p) => <Icon {...p}><path d="m22 2-7 20-4-9-9-4 20-7z" /></Icon>,
|
||||
Globe: (p) => <Icon {...p}><circle cx="12" cy="12" r="10" /><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></Icon>,
|
||||
Terminal: (p) => <Icon {...p}><path d="m4 17 6-6-6-6M12 19h8" /></Icon>,
|
||||
Logo: ({ size = 28 }) => (
|
||||
<svg width={size} height={size} viewBox="0 0 32 32" fill="none">
|
||||
<defs>
|
||||
<linearGradient id="logoG" x1="0" y1="0" x2="32" y2="32" gradientUnits="userSpaceOnUse">
|
||||
<stop stopColor="var(--accent)" />
|
||||
<stop offset="1" stopColor="var(--accent-2)" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="2" y="2" width="28" height="28" rx="8" fill="none" stroke="url(#logoG)" strokeWidth="1.5" />
|
||||
<path d="M10 22 L16 8 L22 22 M12.5 17 H19.5" stroke="url(#logoG)" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
</svg>
|
||||
Logo: ({ size = 28, full = false }) => (
|
||||
<img
|
||||
src="logo.png"
|
||||
width={full ? size * 4 : size}
|
||||
height={size}
|
||||
alt="Aura Agentic AI"
|
||||
style={{
|
||||
objectFit: "contain",
|
||||
objectPosition: "center",
|
||||
borderRadius: full ? 0 : 4,
|
||||
mixBlendMode: "screen",
|
||||
display: "block",
|
||||
flexShrink: 0,
|
||||
}}
|
||||
onError={e => { e.currentTarget.style.display = "none"; }}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
+4
-28
@@ -1,9 +1,8 @@
|
||||
// Top nav — minimal, sticky, blurred — mobile-responsive
|
||||
const DASHBOARD = 'https://aura.auraajenticai.cloud'
|
||||
const NAV_FALLBACK = [
|
||||
const NAV_LINKS = [
|
||||
{ id: "services", label: "Services", url: "#/services" },
|
||||
{ id: "stack", label: "Stack", url: "#/stack" },
|
||||
{ id: "agents", label: "Agents", url: "#/agents" },
|
||||
{ id: "pricing", label: "Pricing", url: "#/pricing" },
|
||||
{ id: "blog", label: "Blog", url: "#/blog" },
|
||||
{ id: "timeline", label: "Timeline", url: "#/timeline" },
|
||||
{ id: "contact", label: "Contact", url: "#/contact" },
|
||||
]
|
||||
@@ -11,7 +10,7 @@ const NAV_FALLBACK = [
|
||||
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }) => {
|
||||
const [scrolled, setScrolled] = React.useState(false);
|
||||
const [menuOpen, setMenuOpen] = React.useState(false);
|
||||
const [links, setLinks] = React.useState(NAV_FALLBACK);
|
||||
const links = NAV_LINKS;
|
||||
|
||||
React.useEffect(() => {
|
||||
const onScroll = () => setScrolled(window.scrollY > 12);
|
||||
@@ -19,29 +18,6 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang, route }
|
||||
return () => window.removeEventListener("scroll", onScroll);
|
||||
}, []);
|
||||
|
||||
// Fetch nav links from Control Center API (stale-while-revalidate)
|
||||
React.useEffect(() => {
|
||||
const CACHE_KEY = 'aura_nav_links'
|
||||
const CACHE_TTL = 5 * 60 * 1000 // 5 min
|
||||
const cached = sessionStorage.getItem(CACHE_KEY)
|
||||
if (cached) {
|
||||
try {
|
||||
const { data, ts } = JSON.parse(cached)
|
||||
if (Date.now() - ts < CACHE_TTL) { setLinks(data.length ? data : NAV_FALLBACK); return }
|
||||
} catch {}
|
||||
}
|
||||
fetch(`${DASHBOARD}/api/public/links?page=home`, { signal: AbortSignal.timeout(3000) })
|
||||
.then(r => r.ok ? r.json() : null)
|
||||
.then(data => {
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
const mapped = data.map(l => ({ id: l.id, label: l.label, url: l.url }))
|
||||
setLinks(mapped)
|
||||
sessionStorage.setItem(CACHE_KEY, JSON.stringify({ data: mapped, ts: Date.now() }))
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav style={{
|
||||
|
||||
+643
-2
@@ -35,9 +35,36 @@ const PageHero = ({ eyebrow, title, sub, children }) => (
|
||||
|
||||
// ─── SERVICES PAGE ────────────────────────────────────────────────────────────
|
||||
|
||||
const DASHBOARD_API = 'https://aura.auraajenticai.cloud';
|
||||
|
||||
const ServicesPage = ({ lang }) => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const [active, setActive] = React.useState(null);
|
||||
const [svcLinks, setSvcLinks] = React.useState({});
|
||||
|
||||
// Fetch demo/repo overrides from Dashboard (stale-while-revalidate)
|
||||
React.useEffect(() => {
|
||||
const CACHE_KEY = 'aura_svc_links_v2';
|
||||
const CACHE_TTL = 10 * 60 * 1000;
|
||||
try {
|
||||
const cached = sessionStorage.getItem(CACHE_KEY);
|
||||
if (cached) {
|
||||
const { data, ts } = JSON.parse(cached);
|
||||
if (Date.now() - ts < CACHE_TTL) { setSvcLinks(data); return; }
|
||||
}
|
||||
} catch {}
|
||||
fetch(`${DASHBOARD_API}/api/public/services`, { signal: AbortSignal.timeout(3000) })
|
||||
.then(r => r.ok ? r.json() : null)
|
||||
.then(data => {
|
||||
if (Array.isArray(data)) {
|
||||
const map = {};
|
||||
data.forEach(s => { if (s.id) map[s.id] = { demo: s.demo, repo: s.repo }; });
|
||||
setSvcLinks(map);
|
||||
sessionStorage.setItem(CACHE_KEY, JSON.stringify({ data: map, ts: Date.now() }));
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main>
|
||||
@@ -53,6 +80,8 @@ const ServicesPage = ({ lang }) => {
|
||||
{D.services.map((svc, i) => {
|
||||
const c = COLOR_MAP[svc.color] || COLOR_MAP.violet;
|
||||
const isOpen = active === svc.id;
|
||||
const demo = (svcLinks[svc.id]?.demo) || svc.demo;
|
||||
const repo = (svcLinks[svc.id]?.repo) || svc.repo;
|
||||
const isNew = !!svc.badge;
|
||||
return (
|
||||
<div
|
||||
@@ -142,8 +171,57 @@ const ServicesPage = ({ lang }) => {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Demo / Repo links */}
|
||||
{(demo || repo) && (
|
||||
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
|
||||
{demo && (
|
||||
<a
|
||||
href="mailto:hello@auraajenticai.cloud?subject=Enquiry: {svc.name}"
|
||||
href={demo}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{
|
||||
display: "inline-flex", alignItems: "center", gap: 6,
|
||||
padding: "8px 16px",
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
borderRadius: 8, fontSize: 13, fontWeight: 500,
|
||||
color: c.text, textDecoration: "none",
|
||||
fontFamily: "var(--font-mono)",
|
||||
}}
|
||||
>
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<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>
|
||||
Live Demo
|
||||
</a>
|
||||
)}
|
||||
{repo && (
|
||||
<a
|
||||
href={repo}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{
|
||||
display: "inline-flex", alignItems: "center", gap: 6,
|
||||
padding: "8px 16px",
|
||||
background: "var(--bg-elev)", border: "1px solid var(--line)",
|
||||
borderRadius: 8, fontSize: 13, fontWeight: 500,
|
||||
color: "var(--text-dim)", textDecoration: "none",
|
||||
fontFamily: "var(--font-mono)",
|
||||
}}
|
||||
>
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z"/>
|
||||
</svg>
|
||||
View Repo
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<a
|
||||
href={`mailto:hello@auraajenticai.cloud?subject=Enquiry: ${svc.name}`}
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{
|
||||
alignSelf: "flex-start",
|
||||
@@ -309,8 +387,21 @@ const ContactPage = ({ lang }) => {
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
try {
|
||||
const res = await fetch(`${DASHBOARD_API}/api/public/contact`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(form),
|
||||
signal: AbortSignal.timeout(8000),
|
||||
});
|
||||
if (res.ok) {
|
||||
setSent(true);
|
||||
} else {
|
||||
alert('Something went wrong. Please email us directly at hello@auraajenticai.cloud');
|
||||
}
|
||||
} catch {
|
||||
alert('Could not send message. Please email us at hello@auraajenticai.cloud');
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
@@ -434,8 +525,558 @@ const ContactPage = ({ lang }) => {
|
||||
);
|
||||
};
|
||||
|
||||
// ─── PRICING PAGE ─────────────────────────────────────────────────────────────
|
||||
|
||||
const PRICING_COLORS = {
|
||||
violet: { bg: "rgba(124,92,255,0.08)", border: "rgba(124,92,255,0.22)", text: "#a78bfa" },
|
||||
cyan: { bg: "rgba(0,212,255,0.07)", border: "rgba(0,212,255,0.20)", text: "#67e8f9" },
|
||||
amber: { bg: "rgba(251,191,36,0.08)", border: "rgba(251,191,36,0.22)", text: "#fde68a" },
|
||||
};
|
||||
|
||||
const PricingPage = () => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
return (
|
||||
<main>
|
||||
<PageHero
|
||||
eyebrow="Pricing"
|
||||
title={<>Transparent pricing. <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>No surprises.</span></>}
|
||||
sub="Fixed-scope projects. No retainers for decks. Every tier ends with production code on your domain."
|
||||
/>
|
||||
<section style={{ padding: "80px 0 120px" }}>
|
||||
<div className="container">
|
||||
<div style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(3, 1fr)",
|
||||
gap: 24, alignItems: "start",
|
||||
}} className="pricing-grid">
|
||||
{D.pricingTiers.map((tier, i) => {
|
||||
const c = PRICING_COLORS[tier.color] || PRICING_COLORS.violet;
|
||||
const isPopular = tier.badge === "Most Popular";
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className="reveal"
|
||||
style={{
|
||||
background: isPopular ? c.bg : "var(--bg-card)",
|
||||
border: `1px solid ${isPopular ? c.border : "var(--line)"}`,
|
||||
borderRadius: "var(--radius)",
|
||||
padding: "32px",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
{tier.badge && (
|
||||
<div style={{
|
||||
position: "absolute", top: -12, left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
background: isPopular ? c.text : "var(--bg-elev)",
|
||||
color: isPopular ? "var(--bg)" : "var(--text-faint)",
|
||||
fontSize: 10.5, fontWeight: 600,
|
||||
padding: "3px 12px", borderRadius: 999,
|
||||
fontFamily: "var(--font-mono)",
|
||||
border: `1px solid ${c.border}`,
|
||||
whiteSpace: "nowrap",
|
||||
}}>{tier.badge}</div>
|
||||
)}
|
||||
|
||||
<div style={{ marginBottom: 24 }}>
|
||||
<h3 style={{ margin: "0 0 6px", fontSize: 20, fontWeight: 600 }}>{tier.name}</h3>
|
||||
<p style={{ margin: 0, fontSize: 13.5, color: "var(--text-dim)", lineHeight: 1.5 }}>{tier.description}</p>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 28 }}>
|
||||
{tier.price ? (
|
||||
<div style={{ display: "flex", alignItems: "baseline", gap: 4 }}>
|
||||
<span style={{ fontSize: 13, color: "var(--text-faint)" }}>USD</span>
|
||||
<span style={{ fontSize: 40, fontWeight: 700, letterSpacing: "-0.03em", color: c.text }}>${tier.price.toLocaleString()}</span>
|
||||
<span style={{ fontSize: 13, color: "var(--text-faint)", fontFamily: "var(--font-mono)" }}>{tier.period}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ fontSize: 28, fontWeight: 700, color: c.text }}>Custom Quote</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ul style={{ margin: "0 0 28px", padding: 0, listStyle: "none", display: "grid", gap: 10 }}>
|
||||
{tier.features.map((f, fi) => (
|
||||
<li key={fi} style={{ display: "flex", gap: 10, fontSize: 13.5, color: "var(--text-dim)", lineHeight: 1.45 }}>
|
||||
<span style={{ color: c.text, flexShrink: 0, marginTop: 1, fontWeight: 700 }}>✓</span>
|
||||
{f}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<a
|
||||
href={tier.href}
|
||||
style={{
|
||||
display: "block", textAlign: "center",
|
||||
padding: "12px 24px",
|
||||
background: isPopular ? c.text : "var(--bg-elev)",
|
||||
color: isPopular ? "var(--bg)" : "var(--text)",
|
||||
border: `1px solid ${isPopular ? c.text : "var(--line)"}`,
|
||||
borderRadius: 10, fontSize: 14, fontWeight: 500,
|
||||
textDecoration: "none",
|
||||
transition: "opacity 0.15s",
|
||||
}}
|
||||
onMouseEnter={e => e.currentTarget.style.opacity = "0.85"}
|
||||
onMouseLeave={e => e.currentTarget.style.opacity = "1"}
|
||||
>{tier.cta} →</a>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
marginTop: 64, padding: "32px 40px",
|
||||
background: "var(--bg-card)", border: "1px solid var(--line)",
|
||||
borderRadius: "var(--radius)",
|
||||
display: "grid", gridTemplateColumns: "1fr auto",
|
||||
gap: 24, alignItems: "center",
|
||||
}} className="pricing-cta-row">
|
||||
<div>
|
||||
<h3 style={{ margin: "0 0 6px", fontSize: 18, fontWeight: 500 }}>Not sure which tier fits your project?</h3>
|
||||
<p style={{ margin: 0, fontSize: 14, color: "var(--text-dim)" }}>Email us a brief description — we'll scope it and get back within 24 hours.</p>
|
||||
</div>
|
||||
<a
|
||||
href="mailto:hello@auraajenticai.cloud?subject=Project Scoping"
|
||||
style={{
|
||||
padding: "12px 24px", background: "var(--text)", color: "var(--bg)",
|
||||
borderRadius: 10, fontSize: 14, fontWeight: 500,
|
||||
textDecoration: "none", whiteSpace: "nowrap",
|
||||
}}
|
||||
>Get a Quote →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<style>{`
|
||||
@media (max-width: 900px) {
|
||||
.pricing-grid { grid-template-columns: 1fr !important; max-width: 480px; }
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.pricing-cta-row { grid-template-columns: 1fr !important; }
|
||||
}
|
||||
`}</style>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
// ─── BLOG PAGE ────────────────────────────────────────────────────────────────
|
||||
|
||||
const BLOG_COLORS = {
|
||||
amber: { bg: "rgba(251,191,36,0.08)", border: "rgba(251,191,36,0.22)", text: "#fde68a" },
|
||||
rose: { bg: "rgba(244,63,94,0.08)", border: "rgba(244,63,94,0.22)", text: "#fda4af" },
|
||||
cyan: { bg: "rgba(0,212,255,0.07)", border: "rgba(0,212,255,0.20)", text: "#67e8f9" },
|
||||
violet: { bg: "rgba(124,92,255,0.08)", border: "rgba(124,92,255,0.22)", text: "#a78bfa" },
|
||||
};
|
||||
|
||||
const BlogPage = () => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const [active, setActive] = React.useState(null);
|
||||
const [articles, setArticles] = React.useState(D.blogArticles || []);
|
||||
|
||||
React.useEffect(() => {
|
||||
const CACHE_KEY = 'aura_blog_v1';
|
||||
const CACHE_TTL = 10 * 60 * 1000;
|
||||
try {
|
||||
const cached = sessionStorage.getItem(CACHE_KEY);
|
||||
if (cached) {
|
||||
const { data, ts } = JSON.parse(cached);
|
||||
if (Date.now() - ts < CACHE_TTL && data.length) { setArticles(data); return; }
|
||||
}
|
||||
} catch {}
|
||||
fetch(`${DASHBOARD_API}/api/public/blog`, { signal: AbortSignal.timeout(3000) })
|
||||
.then(r => r.ok ? r.json() : null)
|
||||
.then(data => {
|
||||
if (Array.isArray(data) && data.length) {
|
||||
setArticles(data);
|
||||
sessionStorage.setItem(CACHE_KEY, JSON.stringify({ data, ts: Date.now() }));
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
const article = active ? articles.find(a => a.slug === active) : null;
|
||||
|
||||
if (article) {
|
||||
const c = BLOG_COLORS[article.color] || BLOG_COLORS.violet;
|
||||
return (
|
||||
<main>
|
||||
<section style={{ padding: "140px 0 80px" }}>
|
||||
<div className="container" style={{ maxWidth: 720 }}>
|
||||
<button
|
||||
onClick={() => setActive(null)}
|
||||
style={{
|
||||
display: "inline-flex", alignItems: "center", gap: 6,
|
||||
fontSize: 12.5, color: "var(--text-faint)", background: "none",
|
||||
border: "none", cursor: "pointer", marginBottom: 40,
|
||||
fontFamily: "var(--font-mono)", padding: 0,
|
||||
}}
|
||||
>← All Articles</button>
|
||||
|
||||
<div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 20 }}>
|
||||
<span style={{
|
||||
fontSize: 11, padding: "3px 10px", borderRadius: 999,
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
color: c.text, fontFamily: "var(--font-mono)",
|
||||
}}>{article.category}</span>
|
||||
<span style={{ fontSize: 12, color: "var(--text-faint)", fontFamily: "var(--font-mono)" }}>
|
||||
{article.date} · {article.readTime} read
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h1 style={{
|
||||
fontSize: "clamp(28px, 4vw, 48px)", fontWeight: 500,
|
||||
letterSpacing: "-0.02em", lineHeight: 1.1, margin: "0 0 48px",
|
||||
}}>{article.title}</h1>
|
||||
|
||||
<div style={{ display: "grid", gap: 20 }}>
|
||||
{article.content.map((block, i) => {
|
||||
if (block.type === "h2") return (
|
||||
<h2 key={i} style={{
|
||||
fontSize: 20, fontWeight: 600, margin: "16px 0 0",
|
||||
letterSpacing: "-0.01em",
|
||||
}}>{block.text}</h2>
|
||||
);
|
||||
return (
|
||||
<p key={i} style={{
|
||||
margin: 0, fontSize: 16, lineHeight: 1.75,
|
||||
color: "var(--text-dim)",
|
||||
}}>{block.text}</p>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
marginTop: 64, padding: "28px 32px",
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
borderRadius: "var(--radius)",
|
||||
}}>
|
||||
<p style={{ margin: "0 0 16px", fontSize: 15, fontWeight: 500 }}>
|
||||
Want to build something like this?
|
||||
</p>
|
||||
<a
|
||||
href={`mailto:hello@auraajenticai.cloud?subject=Enquiry from blog: ${article.title}`}
|
||||
style={{
|
||||
display: "inline-flex", padding: "10px 22px",
|
||||
background: "var(--text)", color: "var(--bg)",
|
||||
borderRadius: 9, fontSize: 13.5, fontWeight: 500,
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>Get in Touch →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
<PageHero
|
||||
eyebrow="Blog"
|
||||
title={<>How we build — <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>openly</span></>}
|
||||
sub="Technical deep-dives on AI agents, trading systems, and the infrastructure behind Aura."
|
||||
/>
|
||||
<section style={{ padding: "80px 0 120px" }}>
|
||||
<div className="container">
|
||||
<div style={{ display: "grid", gap: 20 }}>
|
||||
{articles.map((post, i) => {
|
||||
const c = BLOG_COLORS[post.color] || BLOG_COLORS.violet;
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className="reveal"
|
||||
onClick={() => setActive(post.slug)}
|
||||
style={{
|
||||
background: "var(--bg-card)", border: "1px solid var(--line)",
|
||||
borderRadius: "var(--radius)", padding: "28px 32px",
|
||||
cursor: "pointer", transition: "border-color 0.15s, background 0.15s",
|
||||
display: "grid", gridTemplateColumns: "1fr auto", gap: 24, alignItems: "center",
|
||||
}}
|
||||
onMouseEnter={e => { e.currentTarget.style.borderColor = c.border; e.currentTarget.style.background = c.bg; }}
|
||||
onMouseLeave={e => { e.currentTarget.style.borderColor = "var(--line)"; e.currentTarget.style.background = "var(--bg-card)"; }}
|
||||
>
|
||||
<div>
|
||||
<div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 12 }}>
|
||||
<span style={{
|
||||
fontSize: 10.5, padding: "2px 9px", borderRadius: 999,
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
color: c.text, fontFamily: "var(--font-mono)",
|
||||
}}>{post.category}</span>
|
||||
<span style={{ fontSize: 11.5, color: "var(--text-faint)", fontFamily: "var(--font-mono)" }}>
|
||||
{post.date} · {post.readTime} read
|
||||
</span>
|
||||
</div>
|
||||
<h3 style={{ margin: "0 0 10px", fontSize: 18, fontWeight: 500, letterSpacing: "-0.01em" }}>
|
||||
{post.title}
|
||||
</h3>
|
||||
<p style={{ margin: 0, fontSize: 14, color: "var(--text-dim)", lineHeight: 1.55 }}>
|
||||
{post.excerpt}
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ fontSize: 20, color: "var(--text-faint)", flexShrink: 0 }}>→</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
// ─── SERVICE DETAIL PAGE ──────────────────────────────────────────────────────
|
||||
|
||||
const SVC_EXTRA = {
|
||||
'web-app-dev': {
|
||||
useCases: [
|
||||
{ icon: '🛒', title: 'E-commerce & Marketplace', body: 'Product catalogs, cart flows, payment integrations, and seller dashboards — all built to handle real traffic from day one.' },
|
||||
{ icon: '📊', title: 'SaaS Dashboards', body: 'Multi-tenant apps with role-based access, live data, Stripe billing, and the kind of UX that keeps customers from churning.' },
|
||||
{ icon: '🚀', title: 'Landing Pages that Convert', body: 'Fast, opinionated landing pages with A/B-ready structures — we\'ve seen >5% conversion on cold paid traffic.' },
|
||||
],
|
||||
process: ['Scope & wireframe in Figma (3–5 days)', 'Build core flows, DB schema, auth (2–4 weeks)', 'QA, performance audit, deploy to production'],
|
||||
},
|
||||
'ai-agent-automation': {
|
||||
useCases: [
|
||||
{ icon: '💬', title: 'Customer Support Triage', body: 'Agents that classify, route, and draft responses for support tickets — cutting first-response time from hours to seconds.' },
|
||||
{ icon: '📈', title: 'Internal Reporting & Analysis', body: 'Agents that pull data from your tools, summarize it, and push scheduled reports to Slack or email — no analyst required.' },
|
||||
{ icon: '🎯', title: 'Lead Qualification & CRM Automation', body: 'AI that scores inbound leads, enriches profiles, and books meetings without a human touching the pipeline.' },
|
||||
],
|
||||
process: ['Define the agent\'s scope and tool integrations (1–3 days)', 'Build, prompt-engineer, and eval the agent (1–3 weeks)', 'Deploy with monitoring, retry logic, and a kill switch'],
|
||||
},
|
||||
'web3-blockchain': {
|
||||
useCases: [
|
||||
{ icon: '🔐', title: 'DAO & Multi-sig Interfaces', body: 'Governance UIs, proposal voting, and treasury management — making on-chain decisions feel as simple as a web form.' },
|
||||
{ icon: '🖼️', title: 'NFT Minting & Marketplace', body: 'ERC-721/1155 contracts, lazy minting, royalty enforcement, and storefront UIs that don\'t look like it\'s 2021.' },
|
||||
{ icon: '🌉', title: 'Cross-chain Bridges & Gasless UX', body: 'Bridge infrastructure with abstract-away gas complexity — users just click "confirm" without touching ETH.' },
|
||||
],
|
||||
process: ['Contract design & security review (3–5 days)', 'Smart contract deployment + frontend integration (2–4 weeks)', 'Audit, testnet, mainnet launch'],
|
||||
},
|
||||
'mt5-ea-trading': {
|
||||
useCases: [
|
||||
{ icon: '📉', title: 'Automated Trading Strategies', body: 'Trend-following, mean-reversion, and multi-symbol EAs with hard risk limits, drawdown stops, and real-time alerts.' },
|
||||
{ icon: '🏦', title: 'Prop Firm Dashboards', body: 'Live P&L tracking, account-level risk envelopes, one-click kill switches, and challenge-pass analytics for prop trading firms.' },
|
||||
{ icon: '📋', title: 'Copy Trading Infrastructure', body: 'Master-slave signal distribution across hundreds of follower accounts with sub-100ms latency and full trade history.' },
|
||||
],
|
||||
process: ['Strategy specification & backtest design (2–5 days)', 'MQL5 development, forward test on demo (1–3 weeks)', 'Live deployment with monitoring and kill switches'],
|
||||
},
|
||||
'scraping-data-pipeline': {
|
||||
useCases: [
|
||||
{ icon: '🏷️', title: 'Competitor Price Monitoring', body: 'Real-time price intelligence across thousands of SKUs — normalized, deduplicated, and delivered to your dashboard or DB.' },
|
||||
{ icon: '🏘️', title: 'Real Estate & Listing Aggregation', body: 'Multi-source property data collected, structured, and refreshed on schedule — feeding analytics or ML models.' },
|
||||
{ icon: '💹', title: 'Financial Data ETL', body: 'Earnings reports, regulatory filings, and market data extracted from public sources and piped into your warehouse.' },
|
||||
],
|
||||
process: ['Site analysis & proxy strategy (1–2 days)', 'Scraper build with error handling & rotation (1–2 weeks)', 'ETL pipeline, scheduling, and delivery to your DB'],
|
||||
},
|
||||
'infra-devops': {
|
||||
useCases: [
|
||||
{ icon: '💸', title: 'Cut Cloud Bills by 60%+', body: 'Move from AWS/GCP managed services to self-hosted Coolify on a bare-metal VPS — same reliability, fraction of the cost.' },
|
||||
{ icon: '🔄', title: 'Zero-downtime CI/CD Pipelines', body: 'GitHub Actions → Docker → Traefik with blue/green deploys, automatic SSL, and rollback on health-check failure.' },
|
||||
{ icon: '🔭', title: 'Observability for AI Workloads', body: 'Structured logging, Prometheus metrics, and alerting for long-running agent tasks — know before your users do.' },
|
||||
],
|
||||
process: ['Audit current infra and cost (1 day)', 'Provision, configure, migrate (3–7 days)', 'CI/CD setup, monitoring, runbook handoff'],
|
||||
},
|
||||
'meta-ads-ai': {
|
||||
useCases: [
|
||||
{ icon: '🛍️', title: 'E-commerce Scaling ($10k+/mo spend)', body: 'AI that manages bid adjustments, budget reallocation, and creative rotation across campaigns — every 15 minutes, not twice a day.' },
|
||||
{ icon: '🏢', title: 'Agencies with Multiple Client Accounts', body: 'One AI system managing dozens of accounts simultaneously, surfacing anomalies and generating client-ready reports automatically.' },
|
||||
{ icon: '📣', title: 'Product Launches & Rapid Testing', body: '100+ ad variants generated and tested by AI in the first 48 hours — finding your winning creative before your budget runs out.' },
|
||||
],
|
||||
process: ['Connect Meta Ads API + brief the AI on goals (1 day)', 'Deploy optimization agent, set guardrails & budget caps (2–3 days)', 'Monitor KPIs, iterate on creative strategy weekly'],
|
||||
},
|
||||
};
|
||||
|
||||
const ServiceDetailPage = ({ svc }) => {
|
||||
const extra = SVC_EXTRA[svc.id] || {};
|
||||
const c = COLOR_MAP[svc.color] || COLOR_MAP.violet;
|
||||
const demo = svc.demo;
|
||||
const repo = svc.repo;
|
||||
|
||||
return (
|
||||
<main>
|
||||
<PageHero
|
||||
eyebrow={svc.kind}
|
||||
title={svc.name}
|
||||
sub={svc.description}
|
||||
>
|
||||
<div style={{ display: 'flex', gap: 12, marginTop: 32, flexWrap: 'wrap' }}>
|
||||
{demo && (
|
||||
<a href={demo} target="_blank" rel="noopener noreferrer" style={{
|
||||
display: 'inline-flex', alignItems: 'center', gap: 6,
|
||||
padding: '10px 20px', borderRadius: 9,
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
color: c.text, fontSize: 13.5, fontWeight: 500,
|
||||
textDecoration: 'none', fontFamily: 'var(--font-mono)',
|
||||
}}>
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<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>
|
||||
Live Demo
|
||||
</a>
|
||||
)}
|
||||
<a
|
||||
href={`mailto:hello@auraajenticai.cloud?subject=Enquiry: ${svc.name}`}
|
||||
style={{
|
||||
display: 'inline-flex', alignItems: 'center', gap: 6,
|
||||
padding: '10px 20px', borderRadius: 9,
|
||||
background: 'var(--text)', color: 'var(--bg)',
|
||||
fontSize: 13.5, fontWeight: 500, textDecoration: 'none',
|
||||
}}
|
||||
>Get a Quote →</a>
|
||||
</div>
|
||||
</PageHero>
|
||||
|
||||
{/* Impact metric + stack */}
|
||||
<section style={{ padding: '64px 0', borderBottom: '1px solid var(--line)' }}>
|
||||
<div className="container">
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 48, alignItems: 'start' }} className="svc-detail-top">
|
||||
<div>
|
||||
<div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-faint)', marginBottom: 12, textTransform: 'uppercase', letterSpacing: '0.1em' }}>Key metric</div>
|
||||
<div style={{ fontSize: 52, fontWeight: 700, color: c.text, lineHeight: 1 }}>{svc.impact.primary}</div>
|
||||
<div style={{ fontSize: 14, color: 'var(--text-dim)', marginTop: 8 }}>{svc.impact.secondary}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-faint)', marginBottom: 12, textTransform: 'uppercase', letterSpacing: '0.1em' }}>Stack</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
|
||||
{svc.stack.map(s => (
|
||||
<span key={s} style={{
|
||||
fontSize: 12.5, padding: '5px 12px', borderRadius: 7,
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
color: c.text, fontFamily: 'var(--font-mono)',
|
||||
}}>{s}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Highlights */}
|
||||
{svc.highlights && (
|
||||
<section style={{ padding: '72px 0', borderBottom: '1px solid var(--line)' }}>
|
||||
<div className="container">
|
||||
<div className="eyebrow" style={{ marginBottom: 32 }}>What's included</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 16 }}>
|
||||
{svc.highlights.map((h, i) => (
|
||||
<div key={i} className="reveal" style={{
|
||||
padding: '20px 24px', borderRadius: 'var(--radius)',
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
display: 'flex', gap: 12, alignItems: 'flex-start',
|
||||
}}>
|
||||
<span style={{ color: c.text, fontWeight: 700, flexShrink: 0, marginTop: 1 }}>✓</span>
|
||||
<span style={{ fontSize: 14.5, lineHeight: 1.5 }}>{h}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* Use cases */}
|
||||
{extra.useCases && (
|
||||
<section style={{ padding: '72px 0', borderBottom: '1px solid var(--line)' }}>
|
||||
<div className="container">
|
||||
<div className="eyebrow" style={{ marginBottom: 12 }}>Use cases</div>
|
||||
<h2 style={{ fontSize: 'clamp(24px, 3.5vw, 40px)', fontWeight: 500, letterSpacing: '-0.02em', margin: '0 0 48px' }}>
|
||||
Who hires us for this
|
||||
</h2>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 24 }}>
|
||||
{extra.useCases.map((uc, i) => (
|
||||
<div key={i} className="reveal" style={{
|
||||
padding: '28px 28px', borderRadius: 'var(--radius)',
|
||||
background: 'var(--bg-card)', border: '1px solid var(--line)',
|
||||
}}>
|
||||
<div style={{ fontSize: 28, marginBottom: 14 }}>{uc.icon}</div>
|
||||
<h3 style={{ margin: '0 0 10px', fontSize: 16, fontWeight: 600 }}>{uc.title}</h3>
|
||||
<p style={{ margin: 0, fontSize: 14, lineHeight: 1.65, color: 'var(--text-dim)' }}>{uc.body}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* Process */}
|
||||
{extra.process && (
|
||||
<section style={{ padding: '72px 0', borderBottom: '1px solid var(--line)' }}>
|
||||
<div className="container">
|
||||
<div className="eyebrow" style={{ marginBottom: 12 }}>Process</div>
|
||||
<h2 style={{ fontSize: 'clamp(24px, 3.5vw, 40px)', fontWeight: 500, letterSpacing: '-0.02em', margin: '0 0 48px' }}>
|
||||
How we work
|
||||
</h2>
|
||||
<div style={{ display: 'grid', gap: 0, maxWidth: 640 }}>
|
||||
{extra.process.map((step, i) => (
|
||||
<div key={i} className="reveal" style={{
|
||||
display: 'flex', gap: 24, paddingBottom: 32,
|
||||
borderLeft: i < extra.process.length - 1 ? `1px solid ${c.border}` : 'none',
|
||||
paddingLeft: 32, marginLeft: 16, position: 'relative',
|
||||
}}>
|
||||
<div style={{
|
||||
position: 'absolute', left: -8, top: 4,
|
||||
width: 15, height: 15, borderRadius: '50%',
|
||||
background: c.bg, border: `2px solid ${c.text}`,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
fontSize: 9, fontWeight: 700, color: c.text,
|
||||
fontFamily: 'var(--font-mono)',
|
||||
}}>{i + 1}</div>
|
||||
<p style={{ margin: 0, fontSize: 15, lineHeight: 1.6, color: 'var(--text-dim)' }}>{step}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* CTA */}
|
||||
<section style={{ padding: '80px 0 120px' }}>
|
||||
<div className="container">
|
||||
<div style={{
|
||||
padding: '48px 56px', borderRadius: 'var(--radius)',
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
display: 'grid', gridTemplateColumns: '1fr auto',
|
||||
gap: 32, alignItems: 'center',
|
||||
}} className="svc-cta-row">
|
||||
<div>
|
||||
<h2 style={{ margin: '0 0 10px', fontSize: 'clamp(20px, 3vw, 30px)', fontWeight: 500, letterSpacing: '-0.01em' }}>
|
||||
Ready to ship {svc.name}?
|
||||
</h2>
|
||||
<p style={{ margin: 0, fontSize: 15, color: 'var(--text-dim)' }}>
|
||||
Describe your project — we'll respond within 24 hours with a scoped proposal.
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
|
||||
<a
|
||||
href={`mailto:hello@auraajenticai.cloud?subject=Project: ${svc.name}`}
|
||||
style={{
|
||||
padding: '12px 28px', background: 'var(--text)', color: 'var(--bg)',
|
||||
borderRadius: 10, fontSize: 14, fontWeight: 500,
|
||||
textDecoration: 'none', whiteSpace: 'nowrap',
|
||||
}}
|
||||
>Start a Project →</a>
|
||||
<a href="#/services" style={{
|
||||
padding: '12px 20px',
|
||||
background: 'transparent', border: `1px solid ${c.border}`,
|
||||
color: c.text, borderRadius: 10, fontSize: 14,
|
||||
textDecoration: 'none', whiteSpace: 'nowrap',
|
||||
}}>All Services</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>{`
|
||||
@media (max-width: 720px) {
|
||||
.svc-detail-top { grid-template-columns: 1fr !important; }
|
||||
.svc-cta-row { grid-template-columns: 1fr !important; }
|
||||
}
|
||||
`}</style>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
window.ServicesPage = ServicesPage;
|
||||
window.StackPage = StackPage;
|
||||
window.AgentsPage = AgentsPage;
|
||||
window.TimelinePage = TimelinePage;
|
||||
window.ContactPage = ContactPage;
|
||||
window.PricingPage = PricingPage;
|
||||
window.BlogPage = BlogPage;
|
||||
window.ServiceDetailPage = ServiceDetailPage;
|
||||
|
||||
+10
-17
@@ -313,25 +313,18 @@ const ProjectVisual = ({ id, tint, hover }) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
// Merge Dashboard API data (demo/git links, active state) into local static data
|
||||
// Merge Dashboard API data (demo/repo links) into local static data
|
||||
// Public API returns: { id, name, demo, repo, position }
|
||||
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 => {
|
||||
apiData.forEach(s => { byId[s.id] = s; });
|
||||
return local.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,
|
||||
},
|
||||
demo: api.demo || s.demo || null,
|
||||
gitRepo: api.repo || null,
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -341,8 +334,8 @@ const Projects = () => {
|
||||
const [services, setServices] = React.useState(D.services);
|
||||
|
||||
React.useEffect(() => {
|
||||
const CACHE_KEY = 'aura_services_v2';
|
||||
const CACHE_TTL = 60 * 1000;
|
||||
const CACHE_KEY = 'aura_svc_v3';
|
||||
const CACHE_TTL = 5 * 60 * 1000;
|
||||
const cached = sessionStorage.getItem(CACHE_KEY);
|
||||
if (cached) {
|
||||
try {
|
||||
@@ -369,8 +362,8 @@ const Projects = () => {
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="What we build"
|
||||
num="03 / 06"
|
||||
title={<>Six services. One team. All <span style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontWeight: 400 }}>production-grade</span>.</>}
|
||||
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."
|
||||
/>
|
||||
|
||||
|
||||
@@ -237,6 +237,308 @@ const Skills = () => {
|
||||
);
|
||||
};
|
||||
|
||||
// ─── TESTIMONIALS ─────────────────────────────────────────────────────────────
|
||||
|
||||
const TESTIMONIAL_COLORS = {
|
||||
cyan: { bg: "rgba(0,212,255,0.07)", border: "rgba(0,212,255,0.20)", text: "#67e8f9" },
|
||||
amber: { bg: "rgba(251,191,36,0.08)", border: "rgba(251,191,36,0.22)", text: "#fde68a" },
|
||||
rose: { bg: "rgba(244,63,94,0.08)", border: "rgba(244,63,94,0.22)", text: "#fda4af" },
|
||||
green: { bg: "rgba(34,197,94,0.07)", border: "rgba(34,197,94,0.20)", text: "#86efac" },
|
||||
violet: { bg: "rgba(124,92,255,0.08)", border: "rgba(124,92,255,0.22)", text: "#a78bfa" },
|
||||
};
|
||||
|
||||
const Testimonials = () => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
return (
|
||||
<section style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="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."
|
||||
/>
|
||||
<div style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
gap: 20,
|
||||
}} className="testimonials-grid">
|
||||
{D.testimonials.map((t, i) => {
|
||||
const c = TESTIMONIAL_COLORS[t.color] || TESTIMONIAL_COLORS.cyan;
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className="reveal panel"
|
||||
style={{
|
||||
padding: "28px 32px",
|
||||
border: `1px solid ${c.border}`,
|
||||
background: c.bg,
|
||||
borderRadius: "var(--radius)",
|
||||
}}
|
||||
>
|
||||
<div style={{
|
||||
fontSize: 32, lineHeight: 1, color: c.text,
|
||||
marginBottom: 16, fontFamily: "var(--font-serif)",
|
||||
}}>"</div>
|
||||
<p style={{
|
||||
margin: "0 0 24px", fontSize: 15.5,
|
||||
lineHeight: 1.65, color: "var(--text)",
|
||||
}}>{t.text}</p>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 12 }}>
|
||||
<div style={{
|
||||
width: 40, height: 40, borderRadius: "50%",
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
display: "grid", placeItems: "center",
|
||||
fontSize: 12, fontWeight: 600, color: c.text,
|
||||
fontFamily: "var(--font-mono)", flexShrink: 0,
|
||||
}}>{t.avatar}</div>
|
||||
<div>
|
||||
<div style={{ fontSize: 14, fontWeight: 500 }}>{t.name}</div>
|
||||
<div style={{ fontSize: 12, color: "var(--text-faint)", fontFamily: "var(--font-mono)" }}>
|
||||
{t.role} · {t.company}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginLeft: "auto" }}>
|
||||
<span style={{
|
||||
fontSize: 10.5, padding: "3px 9px", borderRadius: 999,
|
||||
background: "var(--bg-elev)", border: "1px solid var(--line)",
|
||||
color: "var(--text-faint)", fontFamily: "var(--font-mono)",
|
||||
whiteSpace: "nowrap",
|
||||
}}>{t.service}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<style>{`
|
||||
@media (max-width: 720px) {
|
||||
.testimonials-grid { grid-template-columns: 1fr !important; }
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
// ─── FLAGSHIP PRODUCTS ───────────────────────────────────────────────────────
|
||||
|
||||
const PRODUCT_COLORS = {
|
||||
rose: { bg: "rgba(244,63,94,0.08)", border: "rgba(244,63,94,0.22)", text: "#fda4af" },
|
||||
violet: { bg: "rgba(124,92,255,0.08)", border: "rgba(124,92,255,0.22)", text: "#a78bfa" },
|
||||
cyan: { bg: "rgba(0,212,255,0.07)", border: "rgba(0,212,255,0.20)", text: "#67e8f9" },
|
||||
green: { bg: "rgba(34,197,94,0.07)", border: "rgba(34,197,94,0.20)", text: "#86efac" },
|
||||
amber: { bg: "rgba(251,191,36,0.08)", border: "rgba(251,191,36,0.22)", text: "#fde68a" },
|
||||
};
|
||||
|
||||
const OwnProductCard = ({ product }) => {
|
||||
const c = PRODUCT_COLORS[product.color] || PRODUCT_COLORS.violet;
|
||||
return (
|
||||
<div className="reveal" style={{
|
||||
borderRadius: "var(--radius)", border: `1px solid ${c.border}`,
|
||||
background: "var(--bg-card)", overflow: "hidden",
|
||||
display: "flex", flexDirection: "column",
|
||||
}}>
|
||||
{/* Card header */}
|
||||
<div style={{
|
||||
background: `linear-gradient(145deg, ${c.bg.replace('0.08', '0.13')} 0%, rgba(0,0,0,0) 100%)`,
|
||||
padding: "36px 36px 28px", borderBottom: `1px solid ${c.border}`,
|
||||
position: "relative", overflow: "hidden",
|
||||
}}>
|
||||
<div style={{
|
||||
position: "absolute", top: -50, right: -50, width: 180, height: 180,
|
||||
borderRadius: "50%", pointerEvents: "none",
|
||||
background: `radial-gradient(circle, ${c.bg.replace('0.08', '0.18')} 0%, transparent 65%)`,
|
||||
}} />
|
||||
|
||||
{/* Badges */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 20, position: "relative" }}>
|
||||
<span style={{
|
||||
display: "inline-flex", alignItems: "center", gap: 5,
|
||||
background: "rgba(34,197,94,0.10)", border: "1px solid rgba(34,197,94,0.28)",
|
||||
borderRadius: 999, padding: "3px 10px 3px 7px",
|
||||
fontSize: 10, fontFamily: "var(--font-mono)", color: "#4ade80", fontWeight: 600,
|
||||
}}>
|
||||
<span style={{
|
||||
width: 5, height: 5, borderRadius: "50%", background: "#22c55e",
|
||||
boxShadow: "0 0 6px rgba(34,197,94,0.9)", display: "inline-block",
|
||||
animation: "glamour-pulse 2s ease-in-out infinite",
|
||||
}} />
|
||||
LIVE
|
||||
</span>
|
||||
{product.badge && (
|
||||
<span style={{
|
||||
fontSize: 10, fontFamily: "var(--font-mono)", color: c.text,
|
||||
padding: "3px 9px", borderRadius: 999,
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
}}>{product.badge}</span>
|
||||
)}
|
||||
<span style={{
|
||||
fontSize: 10, color: "var(--text-faint)", fontFamily: "var(--font-mono)",
|
||||
padding: "3px 9px", borderRadius: 999,
|
||||
background: "var(--bg-elev)", border: "1px solid var(--line)",
|
||||
marginLeft: "auto",
|
||||
}}>Built by Aura</span>
|
||||
</div>
|
||||
|
||||
{/* Brand name */}
|
||||
<div style={{ position: "relative" }}>
|
||||
<h3 style={{
|
||||
margin: "0 0 6px",
|
||||
fontSize: "clamp(22px, 2.5vw, 32px)",
|
||||
fontWeight: 700, fontFamily: "var(--font-serif)", fontStyle: "italic",
|
||||
letterSpacing: "-0.01em",
|
||||
background: `linear-gradient(135deg, ${c.text} 0%, #fff 80%)`,
|
||||
WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent",
|
||||
backgroundClip: "text",
|
||||
}}>{product.name}</h3>
|
||||
<p style={{
|
||||
margin: 0, fontSize: 11.5, color: "var(--text-faint)",
|
||||
fontFamily: "var(--font-mono)", letterSpacing: "0.1em",
|
||||
textTransform: "uppercase",
|
||||
}}>{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}
|
||||
</p>
|
||||
|
||||
{/* Top 3 features */}
|
||||
<div style={{ display: "grid", gap: 8 }}>
|
||||
{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}
|
||||
</div>
|
||||
))}
|
||||
{product.features.length > 3 && (
|
||||
<div style={{ fontSize: 12, color: "var(--text-faint)", fontFamily: "var(--font-mono)", paddingLeft: 21 }}>
|
||||
+{product.features.length - 3} more capabilities
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Stack */}
|
||||
<div style={{ display: "flex", flexWrap: "wrap", gap: 5 }}>
|
||||
{product.stack.map(s => (
|
||||
<span key={s} style={{
|
||||
fontSize: 11, padding: "3px 9px", borderRadius: 5,
|
||||
background: c.bg, border: `1px solid ${c.border}`,
|
||||
color: c.text, fontFamily: "var(--font-mono)",
|
||||
}}>{s}</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* CTAs */}
|
||||
<div style={{ display: "flex", gap: 10, marginTop: "auto", paddingTop: 4 }}>
|
||||
<a
|
||||
href={product.url} target="_blank" rel="noopener noreferrer"
|
||||
style={{
|
||||
display: "inline-flex", alignItems: "center", gap: 7,
|
||||
padding: "10px 20px",
|
||||
background: `linear-gradient(135deg, ${c.bg.replace('0.08','0.6')}, ${c.bg.replace('0.08','0.4')})`,
|
||||
color: "#fff", borderRadius: 9, fontSize: 13, fontWeight: 600,
|
||||
textDecoration: "none", border: `1px solid ${c.border}`,
|
||||
transition: "opacity 0.15s",
|
||||
}}
|
||||
onMouseEnter={e => e.currentTarget.style.opacity = "0.82"}
|
||||
onMouseLeave={e => e.currentTarget.style.opacity = "1"}
|
||||
>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<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 →
|
||||
</a>
|
||||
<a href="#/services/web-app-dev" style={{
|
||||
display: "inline-flex", alignItems: "center", gap: 7,
|
||||
padding: "10px 16px",
|
||||
background: "transparent", border: `1px solid ${c.border}`,
|
||||
color: c.text, borderRadius: 9, fontSize: 13,
|
||||
textDecoration: "none", transition: "background 0.15s",
|
||||
}}
|
||||
onMouseEnter={e => e.currentTarget.style.background = c.bg}
|
||||
onMouseLeave={e => e.currentTarget.style.background = "transparent"}
|
||||
>Build Mine →</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const FlagshipProduct = () => {
|
||||
const D = PORTFOLIO_DATA;
|
||||
const products = D.ownProducts || [];
|
||||
if (!products.length) return null;
|
||||
|
||||
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" };
|
||||
|
||||
return (
|
||||
<section style={{ padding: "120px 0", borderTop: "1px solid var(--line)" }}>
|
||||
<div className="container">
|
||||
<SectionHeader
|
||||
eyebrow="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."
|
||||
/>
|
||||
|
||||
{/* Products grid */}
|
||||
<div className="own-products-grid" style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: `repeat(${Math.min(products.length, 2)}, 1fr)`,
|
||||
gap: 20,
|
||||
}}>
|
||||
{products.map(p => <OwnProductCard key={p.id} product={p} />)}
|
||||
</div>
|
||||
|
||||
{/* Bottom nudge */}
|
||||
<div className="reveal" style={{
|
||||
marginTop: 20, padding: "22px 32px",
|
||||
background: "var(--bg-card)", border: "1px solid var(--line)",
|
||||
borderRadius: "var(--radius)",
|
||||
display: "flex", alignItems: "center", justifyContent: "space-between",
|
||||
flexWrap: "wrap", gap: 16,
|
||||
}}>
|
||||
<div>
|
||||
<span style={{ fontSize: 15, fontWeight: 500, color: "var(--text)" }}>
|
||||
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
|
||||
</span>
|
||||
</div>
|
||||
<a href="#/contact" style={{
|
||||
padding: "11px 24px",
|
||||
background: "var(--text)", color: "var(--bg)",
|
||||
borderRadius: 9, fontSize: 13.5, fontWeight: 500,
|
||||
textDecoration: "none", whiteSpace: "nowrap", flexShrink: 0,
|
||||
}}>Start a Project →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>{`
|
||||
@keyframes glamour-pulse {
|
||||
0%, 100% { opacity: 1; box-shadow: 0 0 7px rgba(34,197,94,0.9); }
|
||||
50% { opacity: 0.55; box-shadow: 0 0 2px rgba(34,197,94,0.3); }
|
||||
}
|
||||
@media (max-width: 860px) {
|
||||
.own-products-grid { grid-template-columns: 1fr !important; }
|
||||
}
|
||||
`}</style>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
window.About = About;
|
||||
window.Skills = Skills;
|
||||
window.SectionHeader = SectionHeader;
|
||||
window.Testimonials = Testimonials;
|
||||
window.FlagshipProduct = FlagshipProduct;
|
||||
|
||||
Reference in New Issue
Block a user