Telemetry’s visual identity is carried by three self-contained components that render on every page without any props. They sit at the top of the component tree — aboveDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/telemetry/llms.txt
Use this file to discover all available pages before exploring further.
<Outlet> and independent of page content — so they never unmount during navigation and their animations run continuously throughout the session.
AuroraBackground
Location:components/AuroraBackground.js
AuroraBackground paints the full-screen space environment that lives behind all page content. It is position: fixed, covers the entire viewport, and sits at z-index: -1 so it never intercepts pointer events or obscures any UI element.
SVG displacement filter
An inline<svg> (hidden from layout) defines an aurora-filter SVG filter that chains feTurbulence (fractal noise at baseFrequency: 0.01 0.02, 3 octaves) into feDisplacementMap (scale 50). Although the filter is defined here, the blob divs below use Tailwind blur instead of the SVG filter for their primary visual effect.
Animated blobs
Threemotion.div elements — teal, violet, and cyan — form the aurora curtain. They share opacity-30 mix-blend-screen filter blur-[100px] and are positioned to overlap across the screen. Each blob animates its x, y, and scale properties on an independent infinite loop:
Starfield overlays
Twodiv elements carry base64-embedded SVG patterns as background-image. The first scrolls forward with animate-[aurora-flow_100s_linear_infinite]; the second scrolls in reverse at 70s. The aurora-flow keyframes are defined in assets/main.css (compiled Tailwind). Together they create parallax depth between the two starfield layers.
Vignette
A finaldiv renders bg-[radial-gradient(ellipse_at_center,transparent_0%,#04060f_100%)] at opacity-80, darkening the corners so page text always has contrast against the light aurora blobs.
Props: none — AuroraBackground is fully self-contained.
CustomCursor
Location:components/CustomCursor.js
CustomCursor replaces the browser’s default pointer with a two-layer spring-physics cursor. It mounts its own mousemove and mouseover event listeners and tears them down on unmount — no external state or context is required.
State
x and y update on every mousemove via e.clientX / e.clientY. isHovering is set to true by the mouseover handler when the event target satisfies any of these conditions:
tagName === 'a'tagName === 'button'.closest('a')returns a match.closest('button')returns a match.classList.contains('interactive')
Layers
The cursor renders as two concentricmotion.div elements, both position: fixed at top: 0, left: 0, offset to their visual center via the animated x / y values.
| Layer | Classes | Spring config | Hover scale |
|---|---|---|---|
| Inner dot | w-3 h-3 bg-aurora-cyan rounded-full + mix-blend-screen shadow-[0_0_10px_#22d3ee,0_0_20px_#14b8a6] | stiffness 500, damping 28, mass 0.5 | 1.5× |
| Outer ring | w-8 h-8 rounded-full border border-aurora-teal/30 bg-aurora-teal/10 + mix-blend-screen | stiffness 250, damping 35, mass 0.8 | 1.8× |
Making a custom element interactive
Add theinteractive CSS class to any element that is not already an <a> or <button>. The mouseover handler checks for this class via classList.contains("interactive") and will trigger the hover-scale effect:
CustomCursor manages its own event listeners.
Navigation
Location:components/Navigation.js
Navigation is the fixed top header rendered on every page. It is position: fixed, spans the full viewport width, and sits at z-index: 50 — above page content but below the cursor layers.
Structure
The header is a three-column flex row (justify-between items-center):
- Left — logo area: A pulsing
Radioicon (Lucide,w-4 h-4 text-aurora-cyan) inside a small rounded badge with an animatedmotion.divthat scales and fades on an infinite 2-second loop. Beside it, two stacked<span>elements display the wordmark. - Center — nav links: Hidden on mobile (
hidden md:flex). A pill-shaped container (bg-midnight-navy/50 backdrop-blur-md border border-white/10 rounded-full p-1) holds the sevenNavLinkentries from theVparray. - Right — status badge: A pulsing
Activityicon (Lucide,w-3 h-3) beside the text “RECEIVING SIGNAL” inaurora-violet font-mono text-[10px].
Nav items
| Path | Label | ID |
|---|---|---|
/ | HOME | home |
/about | ABOUT | about |
/projects | PROJECTS | projects |
/skills | SKILLS | skills |
/writing | WRITING | writing |
/case-studies | CASE STUDIES | case-studies |
/contact | CONTACT | contact |
Active pill animation
When aNavLink is active, a motion.div with layoutId="nav-pill" renders behind its label. All seven nav items share the same layoutId, so Framer Motion’s shared layout system slides the pill smoothly from one link to another on navigation rather than abruptly swapping it.
Mobile behaviour
Nav links are hidden below themd breakpoint (hidden md:flex). There is no hamburger menu in the current implementation — only the logo and signal status badge are visible on narrow viewports.