diff --git a/apps/web/app/(dashboard)/layout.tsx b/apps/web/app/(dashboard)/layout.tsx
index da4002d..8afb423 100644
--- a/apps/web/app/(dashboard)/layout.tsx
+++ b/apps/web/app/(dashboard)/layout.tsx
@@ -1,6 +1,7 @@
import { CookieBanner } from '@/components/cookie-banner';
import { Logo } from '@/components/logo';
import { MobileActionBar } from '@/components/mobile-action-bar';
+import { PulseLink } from '@/components/pulse';
import { UserMenu } from '@/components/user-menu';
import { FileClock, LayoutGrid, Package, Server, Settings } from 'lucide-react';
import Link from 'next/link';
@@ -33,12 +34,12 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
-
+ New server
-
+
diff --git a/apps/web/app/(marketing)/page.tsx b/apps/web/app/(marketing)/page.tsx
index 734a5de..6438d07 100644
--- a/apps/web/app/(marketing)/page.tsx
+++ b/apps/web/app/(marketing)/page.tsx
@@ -1,6 +1,7 @@
import { HeroStepRotator } from '@/components/hero-step-rotator';
import { JsonLd } from '@/components/json-ld';
import { ParticleHero } from '@/components/particle-hero';
+import { PulseLink } from '@/components/pulse';
import { ScrollCue } from '@/components/scroll-cue';
import { StaticCodeBlock } from '@/components/static-code-block';
import { FAQ, faqJsonLd } from '@/lib/seo';
@@ -92,14 +93,20 @@ export default function Landing() {
three artifacts (prompt → build.log → claude config) with a
mouse-reactive 3D tilt and a step indicator. Shorter overall
so the video section below is teased above the fold. */}
-
+
{/* WebGL particle field — capability-detected client component.
Sits behind the hero content at z-0 with pointer-events:none
so the CTAs above remain fully interactive. The canvas listens
for pointermove on window itself, so the ring still tracks
- the cursor through the content above. */}
+ the cursor through the content above. With the hero now
+ filling the full first-viewport (minus the 48px sticky nav),
+ the field has cinematic-scale room and the indigo radial
+ glow + dot mask read as the dominant background motif. */}
-
+
v0.1 — updated 2026-05-20
@@ -116,18 +123,18 @@ export default function Landing() {
for Claude, Cursor and ChatGPT.
-
Start building free
-
-
+
Read the docs
-
+
diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css
index 01f4dfc..ecec493 100644
--- a/apps/web/app/globals.css
+++ b/apps/web/app/globals.css
@@ -168,3 +168,29 @@
transform: translateY(0);
}
}
+
+/* Click-pulse for primary actions (see components/pulse.tsx).
+ Scales a small indigo dot from 1x to 80x over 650ms — on a 2px base
+ that's ~160px max radius, comfortably larger than any button on the
+ site. The translate(-50%, -50%) keeps the dot anchored to the click
+ point as it grows. Reduced-motion users get an instant fade-out so
+ the click action still proceeds without the bloom. */
+@keyframes glow-pulse {
+ 0% {
+ transform: translate(-50%, -50%) scale(1);
+ opacity: 0.85;
+ }
+ 100% {
+ transform: translate(-50%, -50%) scale(80);
+ opacity: 0;
+ }
+}
+@media (prefers-reduced-motion: reduce) {
+ @keyframes glow-pulse {
+ 0%,
+ 100% {
+ transform: translate(-50%, -50%) scale(1);
+ opacity: 0;
+ }
+ }
+}
diff --git a/apps/web/components/marketing-auth-buttons.tsx b/apps/web/components/marketing-auth-buttons.tsx
index a126603..6394d53 100644
--- a/apps/web/components/marketing-auth-buttons.tsx
+++ b/apps/web/components/marketing-auth-buttons.tsx
@@ -1,7 +1,7 @@
'use client';
+import { PulseLink } from '@/components/pulse';
import { apiFetch } from '@/lib/api';
-import Link from 'next/link';
import { useEffect, useState } from 'react';
/**
@@ -26,11 +26,11 @@ export function MarketingAuthButtons() {
const showDashboard = authed === true;
return (
-
{showDashboard ? 'Dashboard' : 'Login'}
-
+
);
}
diff --git a/apps/web/components/pulse.tsx b/apps/web/components/pulse.tsx
new file mode 100644
index 0000000..6511b35
--- /dev/null
+++ b/apps/web/components/pulse.tsx
@@ -0,0 +1,121 @@
+'use client';
+
+import Link from 'next/link';
+import {
+ type ComponentProps,
+ type MouseEvent as ReactMouseEvent,
+ useRef,
+ useState,
+} from 'react';
+
+interface Pulse {
+ id: number;
+ x: number; // percentage 0-100
+ y: number;
+}
+
+/**
+ * Shared indigo glow-pulse-on-click effect used by hero CTAs and other
+ * primary actions across the site. Same visual language as the hero
+ * load-in glow — a small bright dot detonates from the click point and
+ * scales out fast, fading to transparent.
+ *
+ * Two variants exposed:
+ * - wraps next/link
+ * - wraps a native