A dark hero for a developer tool or SaaS product. The top row puts a large headline on the left and the pitch with two buttons on the right. Below it sits a wide app window drawn entirely in markup: a title bar, a sidebar, three stat tiles, a response-time chart in inline SVG and a list of monitors with status dots. One blurred violet gradient sits behind the window to lift it off the background. On phones the text stacks, the sidebar is hidden and the window keeps its tiles, chart and list at a readable size.
const stats = [
{ label: "Uptime", value: "99.98%" },
{ label: "Response", value: "182 ms" },
{ label: "Incidents", value: "0" },
];
const monitors = [
{ name: "Checkout API", region: "Frankfurt", ms: "164 ms", ok: true },
{ name: "Marketing site", region: "Virginia", ms: "98 ms", ok: true },
{ name: "Webhook worker", region: "Sydney", ms: "412 ms", ok: false },
];
const nav = ["Overview", "Monitors", "Incidents", "Status page", "On-call"];
export default function DarkHeroWithGlowAndProductWindow() {
const ring = "focus:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-950";
return (
<section className="relative overflow-hidden bg-slate-950 px-6 pb-16 pt-16 text-white sm:pb-24 sm:pt-24">
<div aria-hidden="true" className="pointer-events-none absolute left-1/2 top-48 h-96 w-full max-w-4xl -translate-x-1/2 rounded-full bg-gradient-to-r from-violet-600 via-fuchsia-500 to-indigo-500 opacity-30 blur-3xl" />
<div className="relative mx-auto max-w-6xl">
<div className="grid gap-8 lg:grid-cols-12 lg:items-end">
<div className="lg:col-span-7">
<p className="flex items-center gap-2 text-sm font-medium text-violet-300">
<span className="relative flex h-2 w-2"><span className="absolute inline-flex h-full w-full animate-ping motion-reduce:animate-none rounded-full bg-emerald-400 opacity-60" /><span className="relative inline-flex h-2 w-2 rounded-full bg-emerald-400" /></span>
Checking 1.2 million endpoints right now
</p>
<h1 className="mt-5 text-4xl font-semibold tracking-tight sm:text-6xl">Know it is down before your customers do.</h1>
</div>
<div className="lg:col-span-5 lg:pb-2">
<p className="text-lg leading-relaxed text-slate-300">
Beacon checks your sites and APIs every 30 seconds from 14 regions and calls the right person the moment something breaks.
</p>
<div className="mt-7 flex flex-col gap-3 sm:flex-row">
<a href="#" className={`inline-flex items-center justify-center rounded-xl bg-white px-6 py-3 text-sm font-semibold text-slate-950 transition hover:bg-violet-100 ${ring}`}>Start monitoring free</a>
<a href="#" className={`inline-flex items-center justify-center gap-2 rounded-xl border border-white/20 px-6 py-3 text-sm font-semibold text-white transition hover:bg-white/10 ${ring}`}>
Read the docs
<svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" className="h-4 w-4"><path fillRule="evenodd" d="M3 10a.75.75 0 0 1 .75-.75h10.64l-3.2-3.2a.75.75 0 1 1 1.06-1.06l4.5 4.5a.75.75 0 0 1 0 1.06l-4.5 4.5a.75.75 0 1 1-1.06-1.06l3.2-3.2H3.75A.75.75 0 0 1 3 10Z" clipRule="evenodd" /></svg>
</a>
</div>
</div>
</div>
<div aria-hidden="true" className="mt-14 overflow-hidden rounded-2xl border border-white/10 bg-slate-900 shadow-2xl shadow-violet-950 sm:mt-16">
<div className="flex items-center gap-4 border-b border-white/10 px-4 py-3">
<div className="flex gap-1.5"><span className="h-3 w-3 rounded-full bg-slate-700" /><span className="h-3 w-3 rounded-full bg-slate-700" /><span className="h-3 w-3 rounded-full bg-slate-700" /></div>
<div className="mx-auto w-full max-w-xs truncate rounded-md bg-slate-800 px-3 py-1 text-center text-xs text-slate-400">beacon.app / acme-store / overview</div>
<div className="hidden h-6 w-6 rounded-full bg-violet-500 text-center text-xs font-semibold leading-6 sm:block">JM</div>
</div>
<div className="flex">
<div className="hidden w-48 flex-none border-r border-white/10 p-4 md:block">
<ul className="space-y-1 text-sm">
{nav.map((n, i) => (
<li key={n} className={`rounded-lg px-3 py-2 ${i === 0 ? "bg-white/10 font-medium text-white" : "text-slate-400"}`}>{n}</li>
))}
</ul>
</div>
<div className="min-w-0 flex-1 p-4 sm:p-6">
<div className="flex items-center justify-between gap-3">
<p className="text-base font-semibold">Overview</p>
<span className="inline-flex items-center gap-1.5 rounded-full bg-emerald-400/10 px-2.5 py-1 text-xs font-medium text-emerald-300"><span className="h-1.5 w-1.5 rounded-full bg-emerald-400" />All systems normal</span>
</div>
<div className="mt-5 grid grid-cols-3 gap-2 sm:gap-4">
{stats.map((s) => (
<div key={s.label} className="rounded-xl border border-white/10 bg-slate-950/60 p-3 sm:p-4">
<p className="truncate text-xs text-slate-400">{s.label}</p>
<p className="mt-1.5 text-base font-semibold tabular-nums sm:text-2xl">{s.value}</p>
</div>
))}
</div>
<div className="mt-4 rounded-xl border border-white/10 bg-slate-950/60 p-4">
<div className="flex items-center justify-between text-xs text-slate-400"><span>Response time, last 24 hours</span><span className="hidden sm:inline">p95 across all regions</span></div>
<svg viewBox="0 0 600 140" preserveAspectRatio="none" className="mt-3 h-28 w-full sm:h-36">
<defs>
<linearGradient id="beacon-area" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#8b5cf6" stopOpacity=".45" /><stop offset="1" stopColor="#8b5cf6" stopOpacity="0" /></linearGradient>
</defs>
<g stroke="#ffffff" strokeOpacity=".07"><path d="M0 35H600M0 70H600M0 105H600" /></g>
<path d="M0 96 C40 90 60 100 100 88 S160 70 200 82 S260 104 300 92 S350 40 380 34 S420 84 460 80 S540 66 600 72 V140 H0 Z" fill="url(#beacon-area)" />
<path d="M0 96 C40 90 60 100 100 88 S160 70 200 82 S260 104 300 92 S350 40 380 34 S420 84 460 80 S540 66 600 72" fill="none" stroke="#a78bfa" strokeWidth="2.5" vectorEffect="non-scaling-stroke" />
</svg>
</div>
<ul className="mt-4 divide-y divide-white/10 rounded-xl border border-white/10 bg-slate-950/60 text-sm">
{monitors.map((m) => (
<li key={m.name} className="flex items-center gap-3 px-4 py-3">
<span className={`h-2 w-2 flex-none rounded-full ${m.ok ? "bg-emerald-400" : "bg-amber-400"}`} />
<span className="min-w-0 flex-1 truncate font-medium">{m.name}</span>
<span className="hidden text-slate-400 sm:inline">{m.region}</span>
<span className="w-16 text-right tabular-nums text-slate-300">{m.ms}</span>
<span className={`hidden w-16 rounded-full px-2 py-0.5 text-center text-xs font-medium sm:inline-block ${m.ok ? "bg-emerald-400/10 text-emerald-300" : "bg-amber-400/10 text-amber-300"}`}>{m.ok ? "Healthy" : "Slow"}</span>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
</section>
);
}
Install with one command: npx shadcn@latest add https://we.inc/r/dark-hero-with-glow-and-product-window.json
Place an absolutely positioned element behind your content, give it a gradient or solid colour, a low opacity and a large blur such as `blur-3xl`. Put `overflow-hidden` on the section so the blur does not cause sideways scrolling.
A single static blurred element is cheap. Problems come from animating blurred layers or stacking many of them. This hero uses one, and it does not move.
Not if contrast is kept high. Use white for headings and a light grey such as `slate-300` for paragraphs, and keep line length short. Avoid thin font weights on dark backgrounds.
A drawn mock loads instantly, scales to any screen and never goes out of date in small ways. A real screenshot is more convincing once your interface is polished. Many teams start with the mock and swap later.
Yes. Remove the bottom padding from the section and the bottom corners from the window (`rounded-t-2xl` instead of `rounded-2xl`), and it will look like it continues below the fold.
Related: Split Hero with Email Capture, Centered Hero with Two Buttons and Logo Row, App Landing Hero with Phone Mockup, Pricing Table with Monthly and Yearly Toggle.
More hero sections or all free UI components. Start for free to have a full site built around it.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.