feat: PNG logo, og:image/favicon, dashboard-driven demo/repo links
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,9 +10,13 @@
|
||||
<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="icon" type="image/png" href="logo.png" />
|
||||
<link rel="apple-touch-icon" href="logo.png" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
|
||||
+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"; }}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
+34
-5
@@ -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';
|
||||
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
|
||||
@@ -144,11 +173,11 @@ const ServicesPage = ({ lang }) => {
|
||||
</div>
|
||||
|
||||
{/* Demo / Repo links */}
|
||||
{(svc.demo || svc.repo) && (
|
||||
{(demo || repo) && (
|
||||
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
|
||||
{svc.demo && (
|
||||
{demo && (
|
||||
<a
|
||||
href={svc.demo}
|
||||
href={demo}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={e => e.stopPropagation()}
|
||||
@@ -167,9 +196,9 @@ const ServicesPage = ({ lang }) => {
|
||||
Live Demo
|
||||
</a>
|
||||
)}
|
||||
{svc.repo && (
|
||||
{repo && (
|
||||
<a
|
||||
href={svc.repo}
|
||||
href={repo}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={e => e.stopPropagation()}
|
||||
|
||||
Reference in New Issue
Block a user