Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/sys-core/llms.txt

Use this file to discover all available pages before exploring further.

FrequencyGauge displays a single skill’s proficiency as an animated SVG circular progress arc paired with a radio-frequency label. The arc fills from empty to its target percentage over 1.5 seconds using a Framer Motion strokeDashoffset animation, and the frequency string beneath the skill name (for example, 144.2 MHz for React/Next.js) ties the display into the site’s radio-communications metaphor. Each gauge is self-contained and driven by three props: a numeric level, a human-readable label, and a frequency string read from data/skills.js.

Visual Role

The frequency metaphor maps each skill to a place on the radio spectrum:
  • UHF range (~144–145 MHz) — Front-end and interface skills (NAVIGATION group): React/Next.js at 144.2 MHz, TypeScript at 144.5 MHz, Tailwind CSS at 145.1 MHz, Framer Motion at 145.8 MHz.
  • VHF range (~432–433 MHz) — Back-end and data-processing skills (PROPULSION group): Node.js at 432.1 MHz, PostgreSQL at 432.5 MHz, Redis at 433.0 MHz, GraphQL at 433.8 MHz.
  • GHz range (~1.2–1.5 GHz) — Tooling and infrastructure skills (LIFE SUPPORT group): Git/CI-CD at 1.2 GHz, Docker at 1.3 GHz, AWS/Vercel at 1.4 GHz, Jest/Vitest at 1.5 GHz.
  • High-GHz range (~5 GHz) — Soft skills and design (COMMS group): UI/UX Design at 5.0 GHz, Tech Writing at 5.2 GHz, Mentorship at 5.4 GHz, Agile/Scrum at 5.8 GHz.
The circular arc is rendered in #06b6d4 (cyan-signal) with a drop-shadow-[0_0_8px_rgba(6,182,212,0.5)] glow, against a faint rgba(6, 182, 212, 0.1) track ring. The percentage integer is displayed in bold at the centre of the arc.

Usage

Render a FrequencyGauge for each skill entry in a skill group. The level, label, and frequency values come directly from data/skills.js.
import FrequencyGauge from "../../components/cosmic/FrequencyGauge.js";

// Single gauge
export default function SkillGauge() {
  return (
    <FrequencyGauge
      level={95}
      label="React / Next.js"
      frequency="144.2 MHz"
    />
  );
}
// Rendering all gauges for a skill group from data
import FrequencyGauge from "../../components/cosmic/FrequencyGauge.js";
import { s as skillGroups } from "../../data/skills.js";

export default function SkillsGrid() {
  const navGroup = skillGroups.find((g) => g.id === "nav");

  return (
    <div className="grid grid-cols-2 gap-8 md:grid-cols-4">
      {navGroup.skills.map((skill) => (
        <FrequencyGauge
          key={skill.name}
          level={skill.level}
          label={skill.name}
          frequency={skill.frequency}
        />
      ))}
    </div>
  );
}

Props

level
number
required
Skill proficiency as an integer from 0 to 100. This value drives both the SVG arc fill (as a percentage of the full circumference) and the numeric display at the arc’s centre. A level of 95 fills 95 % of the arc.
label
string
required
The skill name displayed below the arc, for example "React / Next.js" or "PostgreSQL". Rendered in text-sm font-bold text-off-white tracking-wide.
frequency
string
required
The radio-frequency string associated with this skill, for example "144.2 MHz" or "1.2 GHz". Sourced from the frequency field on each skill entry in data/skills.js. Displayed below the label in text-xs font-mono text-cyan-signal/70.

Skills Data Shape

The data/skills.js file exports an array of skill-group objects. Each group maps to a spacecraft subsystem and contains an array of individual skill entries:
// data/skills.js — full data shape
[
  {
    id: "nav",
    name: "NAVIGATION",
    description: "Front-end & Interface Systems",
    skills: [
      { name: "React / Next.js", level: 95, frequency: "144.2 MHz" },
      { name: "TypeScript",      level: 90, frequency: "144.5 MHz" },
      { name: "Tailwind CSS",    level: 85, frequency: "145.1 MHz" },
      { name: "Framer Motion",   level: 80, frequency: "145.8 MHz" },
    ],
  },
  {
    id: "prop",
    name: "PROPULSION",
    description: "Back-end & Data Processing",
    skills: [
      { name: "Node.js",    level: 85, frequency: "432.1 MHz" },
      { name: "PostgreSQL", level: 80, frequency: "432.5 MHz" },
      { name: "Redis",      level: 75, frequency: "433.0 MHz" },
      { name: "GraphQL",    level: 70, frequency: "433.8 MHz" },
    ],
  },
  {
    id: "life",
    name: "LIFE SUPPORT",
    description: "Tooling & Infrastructure",
    skills: [
      { name: "Git / CI/CD",  level: 90, frequency: "1.2 GHz" },
      { name: "Docker",       level: 75, frequency: "1.3 GHz" },
      { name: "AWS / Vercel", level: 80, frequency: "1.4 GHz" },
      { name: "Jest / Vitest",level: 85, frequency: "1.5 GHz" },
    ],
  },
  {
    id: "comms",
    name: "COMMS",
    description: "Soft Skills & Design",
    skills: [
      { name: "UI/UX Design", level: 85, frequency: "5.0 GHz" },
      { name: "Tech Writing", level: 90, frequency: "5.2 GHz" },
      { name: "Mentorship",   level: 80, frequency: "5.4 GHz" },
      { name: "Agile/Scrum",  level: 85, frequency: "5.8 GHz" },
    ],
  },
]

Implementation Notes

SVG arc geometry

The arc is a 96 × 96 px SVG circle (radius r = 40) centred at (48, 48). The full circumference is 2π × 40 ≈ 251.3 px. Two overlapping <circle> elements are drawn:
  1. A static track ring in rgba(6, 182, 212, 0.1) at strokeWidth: 4.
  2. A Framer Motion <motion.circle> in #06b6d4 at strokeWidth: 4 whose strokeDasharray is set to the full circumference and whose strokeDashoffset animates from the full circumference (empty) down to circumference × (1 - level/100) (partially filled).
The SVG is rotated -90° so the arc starts at 12 o’clock rather than 3 o’clock.

Framer Motion entrance animation

A useState flag (animated) starts as false and is set to true after a 100 ms setTimeout in a useEffect. The Framer Motion animate prop then transitions strokeDashoffset from the full circumference to the target value over 1.5 s with an easeOut curve and a 0.2 s delay. This ensures the animation only plays once on mount and not on every re-render.
FrequencyGauge depends on Framer Motion (framer-motion) via the ../../assets/proxy.js import alias. Ensure Framer Motion is installed in the project before rendering this component outside the standard build.
Group FrequencyGauge instances inside a HudFrame titled with the skill-group name (e.g., "NAVIGATION" or "PROPULSION") to mirror the spacecraft-subsystem panel metaphor established throughout the Skills section.

Build docs developers (and LLMs) love