Skip to content

feat: landing page interactive components#984

Merged
Aureliolo merged 16 commits intomainfrom
feat/landing-page-interactive
Apr 2, 2026
Merged

feat: landing page interactive components#984
Aureliolo merged 16 commits intomainfrom
feat/landing-page-interactive

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Add 5 interactive components to the Astro landing page: animated particle network (Canvas hero), scroll-synced split panel (4-step walkthrough with IntersectionObserver + sticky SVG visualization), expandable architecture accordion, scrollable use case cards (horizontal snap on mobile), and interactive dashboard preview (React island with 4 mini pages auto-cycling)
  • Replace thin Core Pillars section with rich Feature Showcase (4 hero cards + 6 compact cards) showcasing orchestration, governance, agent identity, memory, providers, cost transparency, templates, and more
  • Enrich landing page content throughout: punchier hero subtext, expanded proof strip (4 to 6 items), detailed security section copy, 6 use cases (up from 4) with feature callouts
  • Install @astrojs/react for React islands architecture -- React only loads when dashboard preview scrolls into view (client:visible), keeping above-the-fold JS at ~2KB

Content accuracy

  • "How It Works" section shows the real user flow: setup wizard template selection, REST API company creation, agent collaboration, dashboard observation
  • No fictional CLI commands -- the CLI manages containers, orgs are created via wizard/API
  • Template scale accurately represented: 9 built-in templates from Solo Builder (2 agents) to Enterprise (30+ agents, 9 departments)
  • SVG org chart shows 10 agents across 5 departments with progressive reveal per step (empty depts -> agents -> communication -> metrics)
  • Dashboard preview metrics reflect realistic agency-scale org (12 agents, 47 tasks, EUR 18.92)

Test plan

  • npm --prefix site run build passes with zero errors
  • Visual smoke test: npm --prefix site run dev at localhost
    • Particle network visible behind hero, smooth animation, stops with reduced motion
    • Scroll sync: SVG builds progressively (empty depts -> agents -> comms -> metrics), vertical step nav clickable
    • Feature showcase: all 10 cards render, links work, focus-visible rings match card theme
    • Architecture: accordion expands/collapses, one-at-a-time, keyboard accessible, inert when collapsed
    • Use cases: horizontal scroll on mobile with fade hints, 3-col grid on desktop, snap works
    • Dashboard preview: tabs switch, auto-cycles every 6s, pauses on hover, prev/next arrows work, text readable at full width
  • Responsive check at 375px / 768px / 1024px / 1440px
  • Accessibility: keyboard navigation, aria attributes, prefers-reduced-motion

Review coverage

Skipping agent review (site-only changes, no backend/dashboard/CLI code). Build verified.

Closes #294

Copilot AI review requested due to automatic review settings April 1, 2026 20:01
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Walkthrough

Adds the React integration to the Astro site config and updates site/package.json. Introduces new interactive components: ParticleNetwork, ScrollSyncPanel, ExpandableArchitecture, FeatureShowcase, UseCaseCards, and a DashboardPreview React island with accompanying CSS plus four mini React islands (AgentDetailMini, BudgetMini, OrgChartMini, TaskBoardMini). Updates Base.astro font loading and refactors the index page to replace several static sections with these components and to render the dashboard preview as a client:visible island.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 40.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: landing page interactive components' is clear, concise, and directly summarizes the main change: adding five interactive components to the landing page.
Description check ✅ Passed The description is comprehensive and relates directly to the changeset. It covers the five new interactive components, enhanced content, and technical details including React islands architecture and performance considerations.
Linked Issues check ✅ Passed All five components from issue #294 are implemented: animated particle network, scroll-synced split panel, expandable architecture diagram, scrollable use-case cards, and interactive dashboard preview with React islands. Technical requirements (Astro islands, @astrojs/react, IntersectionObserver, Canvas) are all met.
Out of Scope Changes check ✅ Passed All changes are within scope: font updates (Geist), component additions, Astro/React integration, and landing page content enrichment align with issue #294 requirements. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Dependency Review

The following issues were found:

  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ✅ 0 package(s) with unknown licenses.
  • ⚠️ 4 packages with OpenSSF Scorecard issues.

View full job summary

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several new interactive components to the Astro landing page, including an expandable architecture grid, a particle network background, a scroll-synced split panel, and a dashboard preview using React islands. While the new features enhance the site's interactivity, several components rely on hardcoded DOM IDs and global script selectors, which will cause functional issues if multiple instances are used on the same page or during client-side navigation. Additionally, there is a potential runtime error in the particle network's resize logic due to unsafe element access.

Comment on lines +142 to +232
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
{architecture.map((arch) => (
<div class="relative">
<button
id={`btn-${arch.id}`}
data-arch-toggle
aria-expanded="false"
aria-controls={`panel-${arch.id}`}
class="w-full bg-[#1a1f2e] rounded-xl p-6 border border-white/10 hover:border-violet-500/30 transition-colors text-left group cursor-pointer"
>
<div class="flex items-center justify-between">
<div>
<p class="font-semibold text-violet-400">{arch.title}</p>
<p class="text-xs text-gray-400 mt-1">{arch.summary}</p>
</div>
<svg
class="w-4 h-4 text-gray-500 transition-transform duration-300 group-aria-expanded:rotate-180 shrink-0 ml-2"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
</svg>
</div>
</button>
</div>
))}
</div>

<!-- Expandable panels (positioned below the grid) -->
{architecture.map((arch) => (
<div
id={`panel-${arch.id}`}
role="region"
aria-labelledby={`btn-${arch.id}`}
aria-hidden="true"
inert
class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-in-out"
>
<div class="overflow-hidden">
<div class="pt-4 grid sm:grid-cols-2 lg:grid-cols-3 gap-3">
{arch.submodules.map((sub) => (
<a
href={sub.href}
class="block bg-[#1a1f2e]/60 rounded-lg p-4 border border-white/5 hover:border-violet-500/20 transition-colors no-underline text-white"
>
<p class="text-sm font-medium text-violet-400 mb-1">{sub.name}</p>
<p class="text-xs text-gray-400">{sub.description}</p>
</a>
))}
</div>
</div>
</div>
))}

<script>
const buttons = document.querySelectorAll<HTMLButtonElement>("[data-arch-toggle]");
buttons.forEach((btn) => {
btn.addEventListener("click", () => {
const targetId = btn.getAttribute("aria-controls");
if (!targetId) return;
const target = document.getElementById(targetId);
const isExpanded = btn.getAttribute("aria-expanded") === "true";

// Collapse all
buttons.forEach((b) => {
b.setAttribute("aria-expanded", "false");
const panelId = b.getAttribute("aria-controls");
if (panelId) {
const panel = document.getElementById(panelId);
if (panel) {
panel.setAttribute("aria-hidden", "true");
panel.setAttribute("inert", "");
panel.classList.remove("grid-rows-[1fr]");
panel.classList.add("grid-rows-[0fr]");
}
}
});

// Expand clicked (if it was collapsed)
if (!isExpanded && target) {
btn.setAttribute("aria-expanded", "true");
target.removeAttribute("aria-hidden");
target.removeAttribute("inert");
target.classList.remove("grid-rows-[0fr]");
target.classList.add("grid-rows-[1fr]");
}
});
});
</script>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The component uses hardcoded, generic IDs (e.g., btn-config, panel-engine) and global script selectors (document.querySelectorAll("[data-arch-toggle]")). This prevents multiple instances of the component from working independently on the same page and risks ID collisions with other elements. Clicking a button in one instance will collapse panels in all other instances. Consider generating unique IDs per instance and scoping the script to a wrapper element using btn.closest or a custom element.

Comment on lines +61 to +62
function resize(): void {
const rect = canvas.parentElement!.getBoundingClientRect();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The resize function is called within a setTimeout (line 206) and uses a non-null assertion (!) on canvas.parentElement. If the component is unmounted or the page is navigated away before the timeout fires, canvas.parentElement will be null, leading to a runtime crash. Add a safety check for the parent element.

    function resize(): void {
      if (!canvas.parentElement) return;
      const rect = canvas.parentElement.getBoundingClientRect();

Comment on lines +138 to +457
<div class="bg-[#0F1219] rounded-xl border border-white/10 p-6 min-h-[420px] flex items-center justify-center">
<svg
id="sync-viz"
viewBox="0 0 420 380"
class="w-full max-w-[420px]"
aria-hidden="true"
>
<!-- Step label -->
<text id="viz-label" x="210" y="18" text-anchor="middle" fill="#94a3b8" font-size="11" font-family="'JetBrains Mono', monospace" class="transition-all duration-500">
Pick a Template
</text>

<!-- Department groups -->
<rect id="dept-exec" x="140" y="30" width="140" height="55" rx="6" fill="none" stroke="#a78bfa" stroke-opacity="0.12" stroke-width="1" class="transition-all duration-700" opacity="0" />
<text class="dept-label transition-all duration-700" x="148" y="44" fill="#a78bfa" font-size="7" font-family="Inter, sans-serif" opacity="0">Executive</text>

<rect id="dept-eng" x="10" y="115" width="195" height="120" rx="6" fill="none" stroke="#a78bfa" stroke-opacity="0.12" stroke-width="1" class="transition-all duration-700" opacity="0" />
<text class="dept-label transition-all duration-700" x="18" y="129" fill="#a78bfa" font-size="7" font-family="Inter, sans-serif" opacity="0">Engineering</text>

<rect id="dept-product" x="215" y="115" width="95" height="120" rx="6" fill="none" stroke="#2dd4bf" stroke-opacity="0.12" stroke-width="1" class="transition-all duration-700" opacity="0" />
<text class="dept-label transition-all duration-700" x="223" y="129" fill="#2dd4bf" font-size="7" font-family="Inter, sans-serif" opacity="0">Product</text>

<rect id="dept-design" x="320" y="115" width="90" height="120" rx="6" fill="none" stroke="#2dd4bf" stroke-opacity="0.12" stroke-width="1" class="transition-all duration-700" opacity="0" />
<text class="dept-label transition-all duration-700" x="328" y="129" fill="#2dd4bf" font-size="7" font-family="Inter, sans-serif" opacity="0">Design</text>

<rect id="dept-qa" x="120" y="255" width="180" height="55" rx="6" fill="none" stroke="#f59e0b" stroke-opacity="0.12" stroke-width="1" class="transition-all duration-700" opacity="0" />
<text class="dept-label transition-all duration-700" x="128" y="269" fill="#f59e0b" font-size="7" font-family="Inter, sans-serif" opacity="0">QA</text>

<!-- Agent nodes -->
<!-- CEO -->
<g id="node-ceo" class="transition-all duration-700" opacity="0">
<rect x="165" y="48" width="90" height="30" rx="6" fill="#1a1f2e" stroke="#a78bfa" stroke-width="1.5" />
<text x="210" y="67" text-anchor="middle" fill="#e2e8f0" font-size="10" font-weight="600" font-family="Inter, sans-serif">CEO</text>
<circle id="status-ceo" cx="247" cy="58" r="3.5" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- CTO -->
<g id="node-cto" class="transition-all duration-700" opacity="0">
<rect x="15" y="137" width="85" height="30" rx="6" fill="#1a1f2e" stroke="#a78bfa" stroke-width="1.2" />
<text x="57" y="156" text-anchor="middle" fill="#e2e8f0" font-size="9" font-weight="600" font-family="Inter, sans-serif">CTO</text>
<circle id="status-cto" cx="92" cy="147" r="3" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- Backend Dev 1 -->
<g id="node-be1" class="transition-all duration-700" opacity="0">
<rect x="15" y="175" width="85" height="26" rx="5" fill="#1a1f2e" stroke="#a78bfa" stroke-width="0.8" />
<text x="57" y="192" text-anchor="middle" fill="#e2e8f0" font-size="8" font-family="Inter, sans-serif">Backend Dev</text>
<circle id="status-be1" cx="92" cy="184" r="2.5" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- Backend Dev 2 -->
<g id="node-be2" class="transition-all duration-700" opacity="0">
<rect x="110" y="175" width="85" height="26" rx="5" fill="#1a1f2e" stroke="#a78bfa" stroke-width="0.8" />
<text x="152" y="192" text-anchor="middle" fill="#e2e8f0" font-size="8" font-family="Inter, sans-serif">Backend Dev 2</text>
<circle id="status-be2" cx="187" cy="184" r="2.5" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- Frontend Dev -->
<g id="node-fe" class="transition-all duration-700" opacity="0">
<rect x="60" y="207" width="95" height="26" rx="5" fill="#1a1f2e" stroke="#a78bfa" stroke-width="0.8" />
<text x="107" y="224" text-anchor="middle" fill="#e2e8f0" font-size="8" font-family="Inter, sans-serif">Frontend Dev</text>
<circle id="status-fe" cx="147" cy="216" r="2.5" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- PM -->
<g id="node-pm" class="transition-all duration-700" opacity="0">
<rect x="220" y="145" width="85" height="30" rx="6" fill="#1a1f2e" stroke="#2dd4bf" stroke-width="1" />
<text x="262" y="164" text-anchor="middle" fill="#e2e8f0" font-size="9" font-weight="600" font-family="Inter, sans-serif">PM</text>
<circle id="status-pm" cx="297" cy="155" r="3" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- Scrum Master -->
<g id="node-sm" class="transition-all duration-700" opacity="0">
<rect x="220" y="183" width="85" height="26" rx="5" fill="#1a1f2e" stroke="#2dd4bf" stroke-width="0.8" />
<text x="262" y="200" text-anchor="middle" fill="#e2e8f0" font-size="8" font-family="Inter, sans-serif">Scrum Master</text>
<circle id="status-sm" cx="297" cy="192" r="2.5" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- UX Designer -->
<g id="node-ux" class="transition-all duration-700" opacity="0">
<rect x="325" y="145" width="80" height="30" rx="6" fill="#1a1f2e" stroke="#2dd4bf" stroke-width="1" />
<text x="365" y="164" text-anchor="middle" fill="#e2e8f0" font-size="9" font-weight="600" font-family="Inter, sans-serif">UX Designer</text>
<circle id="status-ux" cx="397" cy="155" r="3" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- UI Designer -->
<g id="node-ui" class="transition-all duration-700" opacity="0">
<rect x="325" y="183" width="80" height="26" rx="5" fill="#1a1f2e" stroke="#2dd4bf" stroke-width="0.8" />
<text x="365" y="200" text-anchor="middle" fill="#e2e8f0" font-size="8" font-family="Inter, sans-serif">UI Designer</text>
<circle id="status-ui" cx="397" cy="192" r="2.5" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- QA Engineer -->
<g id="node-qa" class="transition-all duration-700" opacity="0">
<rect x="155" y="273" width="85" height="30" rx="6" fill="#1a1f2e" stroke="#f59e0b" stroke-width="1" />
<text x="197" y="292" text-anchor="middle" fill="#e2e8f0" font-size="9" font-weight="600" font-family="Inter, sans-serif">QA Engineer</text>
<circle id="status-qa" cx="232" cy="283" r="3" fill="#94a3b8" class="transition-all duration-500" />
</g>

<!-- Hierarchy edges -->
<line id="edge-ceo-cto" x1="210" y1="78" x2="57" y2="137" stroke="#a78bfa" stroke-width="0.8" stroke-opacity="0.25" stroke-dasharray="3 3" class="transition-all duration-700" opacity="0" />
<line id="edge-ceo-pm" x1="210" y1="78" x2="262" y2="145" stroke="#a78bfa" stroke-width="0.8" stroke-opacity="0.25" stroke-dasharray="3 3" class="transition-all duration-700" opacity="0" />
<line id="edge-ceo-ux" x1="210" y1="78" x2="365" y2="145" stroke="#a78bfa" stroke-width="0.8" stroke-opacity="0.25" stroke-dasharray="3 3" class="transition-all duration-700" opacity="0" />
<line id="edge-cto-be1" x1="57" y1="167" x2="57" y2="175" stroke="#a78bfa" stroke-width="0.6" stroke-opacity="0.2" class="transition-all duration-700" opacity="0" />
<line id="edge-cto-be2" x1="57" y1="167" x2="152" y2="175" stroke="#a78bfa" stroke-width="0.6" stroke-opacity="0.2" class="transition-all duration-700" opacity="0" />
<line id="edge-cto-fe" x1="57" y1="167" x2="107" y2="207" stroke="#a78bfa" stroke-width="0.6" stroke-opacity="0.2" class="transition-all duration-700" opacity="0" />

<!-- Communication edges (animated) -->
<line id="edge-comm1" x1="155" y1="188" x2="220" y2="196" stroke="#2dd4bf" stroke-width="1.2" stroke-opacity="0" stroke-dasharray="5 3" class="transition-all duration-700">
<animate attributeName="stroke-dashoffset" from="0" to="-16" dur="1.5s" repeatCount="indefinite" />
</line>
<line id="edge-comm2" x1="305" y1="160" x2="325" y2="160" stroke="#2dd4bf" stroke-width="1.2" stroke-opacity="0" stroke-dasharray="5 3" class="transition-all duration-700">
<animate attributeName="stroke-dashoffset" from="0" to="-16" dur="2s" repeatCount="indefinite" />
</line>

<!-- Task flow (step 2) -->
<line id="edge-task" x1="210" y1="78" x2="57" y2="137" stroke="#a78bfa" stroke-width="1.5" stroke-opacity="0" class="transition-all duration-700">
<animate attributeName="stroke-dashoffset" from="0" to="-12" dur="1s" repeatCount="indefinite" />
</line>

<!-- Metrics panel (step 4) -->
<g id="metrics-group" opacity="0" class="transition-all duration-700">
<rect x="40" y="325" width="340" height="45" rx="6" fill="#1a1f2e" stroke="#2dd4bf" stroke-width="0.5" stroke-opacity="0.3" />
<text x="60" y="344" fill="#a78bfa" font-size="8" font-family="'JetBrains Mono', monospace">12 agents</text>
<text x="140" y="344" fill="#10b981" font-size="8" font-family="'JetBrains Mono', monospace">47 tasks</text>
<text x="210" y="344" fill="#2dd4bf" font-size="8" font-family="'JetBrains Mono', monospace">EUR 18.92</text>
<text x="300" y="344" fill="#f59e0b" font-size="8" font-family="'JetBrains Mono', monospace">14% coord</text>
<rect x="60" y="352" width="70" height="3" rx="1.5" fill="#a78bfa" opacity="0.3" />
<rect x="60" y="352" width="50" height="3" rx="1.5" fill="#a78bfa" />
<rect x="155" y="352" width="70" height="3" rx="1.5" fill="#10b981" opacity="0.3" />
<rect x="155" y="352" width="48" height="3" rx="1.5" fill="#10b981" />
<rect x="250" y="352" width="70" height="3" rx="1.5" fill="#2dd4bf" opacity="0.3" />
<rect x="250" y="352" width="57" height="3" rx="1.5" fill="#2dd4bf" />
</g>
</svg>
</div>
</div>
</div>
</div>
</div>
</section>

<script>
const steps = document.querySelectorAll<HTMLDivElement>(".scroll-step");
const dots = document.querySelectorAll<HTMLButtonElement>(".step-dot");

const labels = [
"Pick a Template",
"Agents Auto-Configured",
"Agents Collaborate",
"Observe Everything",
];

// SVG elements
const vizLabel = document.getElementById("viz-label");
const allNodes = [
"node-ceo", "node-cto", "node-be1", "node-be2", "node-fe",
"node-pm", "node-sm", "node-ux", "node-ui", "node-qa",
].map((id) => document.getElementById(id));
const allDepts = ["dept-exec", "dept-eng", "dept-product", "dept-design", "dept-qa"]
.map((id) => document.getElementById(id));
const deptLabels = document.querySelectorAll<SVGTextElement>(".dept-label");
const allEdges = [
"edge-ceo-cto", "edge-ceo-pm", "edge-ceo-ux",
"edge-cto-be1", "edge-cto-be2", "edge-cto-fe",
].map((id) => document.getElementById(id));
const edgeComm1 = document.getElementById("edge-comm1");
const edgeComm2 = document.getElementById("edge-comm2");
const edgeTask = document.getElementById("edge-task");
const metricsGroup = document.getElementById("metrics-group");

const statusIds = ["status-ceo", "status-cto", "status-be1", "status-be2", "status-fe",
"status-pm", "status-sm", "status-ux", "status-ui", "status-qa"];
const statusEls = statusIds.map((id) => document.getElementById(id));

let currentStep = -1;

function setStep(step: number): void {
if (step === currentStep) return;
currentStep = step;

// Update code step highlighting
steps.forEach((s, i) => {
const inner = s.firstElementChild as HTMLElement;
const codeBox = inner?.querySelector("[data-code-box]") as HTMLElement;
if (i === step) {
inner.classList.remove("opacity-40", "scale-[0.98]");
inner.classList.add("opacity-100", "scale-100");
if (codeBox) {
codeBox.classList.remove("border-l-transparent");
codeBox.classList.add("border-l-violet-500/40");
}
} else {
inner.classList.add("opacity-40", "scale-[0.98]");
inner.classList.remove("opacity-100", "scale-100");
if (codeBox) {
codeBox.classList.add("border-l-transparent");
codeBox.classList.remove("border-l-violet-500/40");
}
}
});

// Update dots
dots.forEach((d, i) => {
if (i === step) {
d.classList.remove("border-white/20", "text-gray-500");
d.classList.add("border-violet-400", "text-violet-400", "bg-violet-400/10");
} else {
d.classList.add("border-white/20", "text-gray-500");
d.classList.remove("border-violet-400", "text-violet-400", "bg-violet-400/10");
}
});

// Update label
if (vizLabel) vizLabel.textContent = labels[step] || "";

const show = (el: Element | null) => el?.setAttribute("opacity", "1");
const hide = (el: Element | null) => el?.setAttribute("opacity", "0");
const setFill = (el: Element | null, color: string) => el?.setAttribute("fill", color);

// Reset all
allNodes.forEach(hide);
allDepts.forEach(hide);
deptLabels.forEach((el) => el.setAttribute("opacity", "0"));
allEdges.forEach(hide);
edgeComm1?.setAttribute("stroke-opacity", "0");
edgeComm2?.setAttribute("stroke-opacity", "0");
edgeTask?.setAttribute("stroke-opacity", "0");
hide(metricsGroup);
statusEls.forEach((el) => setFill(el, "#94a3b8"));

if (step === 0) {
// Step 1: Template selection -- show empty department frames only
allDepts.forEach(show);
deptLabels.forEach((el) => el.setAttribute("opacity", "0.5"));
}

if (step === 1) {
// Step 2: Agents configured -- departments + agents appear + hierarchy edges
allDepts.forEach(show);
deptLabels.forEach((el) => el.setAttribute("opacity", "0.5"));
allNodes.forEach(show);
allEdges.forEach(show);
}

if (step === 2) {
// Step 3: Collaboration -- agents active, communication flowing, tasks delegated
allDepts.forEach(show);
deptLabels.forEach((el) => el.setAttribute("opacity", "0.5"));
allNodes.forEach(show);
allEdges.forEach(show);
edgeTask?.setAttribute("stroke-opacity", "0.5");
edgeTask?.setAttribute("stroke-dasharray", "5 3");
edgeComm1?.setAttribute("stroke-opacity", "0.5");
edgeComm2?.setAttribute("stroke-opacity", "0.5");
setFill(statusEls[0], "#a78bfa"); // CEO directing
setFill(statusEls[1], "#a78bfa"); // CTO directing
setFill(statusEls[2], "#2dd4bf"); // BE1 working
setFill(statusEls[3], "#2dd4bf"); // BE2 working
setFill(statusEls[4], "#2dd4bf"); // FE working
setFill(statusEls[5], "#a78bfa"); // PM directing
setFill(statusEls[7], "#10b981"); // UX done
setFill(statusEls[9], "#f59e0b"); // QA reviewing
}

if (step === 3) {
// Step 4: Observe -- all done, metrics visible
allDepts.forEach(show);
deptLabels.forEach((el) => el.setAttribute("opacity", "0.5"));
allNodes.forEach(show);
allEdges.forEach(show);
show(metricsGroup);
statusEls.forEach((el) => setFill(el, "#10b981"));
}
}

// Dot click navigation
dots.forEach((dot) => {
dot.addEventListener("click", () => {
const stepIdx = parseInt(dot.dataset.dot || "0", 10);
const target = steps[stepIdx];
if (target) {
target.scrollIntoView({ behavior: "smooth", block: "center" });
}
});
});

// Reduced motion: disable SVG SMIL animations
const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)");

function disableSvgAnimations(): void {
document.querySelectorAll<SVGElement>("#sync-viz animate").forEach((el) => {
el.parentNode?.removeChild(el);
});
}

if (prefersReduced.matches) {
disableSvgAnimations();
setStep(0);
} else {
const observer = new IntersectionObserver(
(entries) => {
const active = entries
.filter((e) => e.isIntersecting)
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
if (!active) return;
const step = parseInt((active.target as HTMLElement).dataset.step || "0", 10);
setStep(step);
},
{
rootMargin: "-40% 0px -40% 0px",
threshold: [0, 0.25, 0.5, 0.75, 1],
}
);

steps.forEach((step) => observer.observe(step));
document.addEventListener("astro:before-swap", () => observer.disconnect(), { once: true });
setStep(0);
}
</script>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The component and its internal SVG use numerous hardcoded IDs (e.g., sync-viz, viz-label, node-ceo) which are then accessed via document.getElementById in the script. This pattern breaks component reusability and will cause functional bugs if multiple instances are present on the page (e.g., the script will only animate the first SVG found). Use data- attributes and relative DOM traversal, or generate unique IDs per instance.

Comment on lines +122 to +126
fill="url(#dp-sparkGrad)"
stroke="none"
/>
<defs>
<linearGradient id="dp-sparkGrad" x1="0" y1="0" x2="0" y2="1">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The SVG linearGradient uses a hardcoded ID dp-sparkGrad. In React, hardcoded IDs in SVG definitions can lead to collisions if the component is rendered multiple times or during client-side navigation (like Astro View Transitions), causing rendering artifacts where the wrong gradient is applied. Use the useId hook to generate a unique ID for the gradient definition.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/ExpandableArchitecture.astro`:
- Around line 145-167: The accordion buttons (elements using data-arch-toggle /
id `btn-${arch.id}`) lack Up/Down arrow key navigation per WAI-ARIA; add a
keydown handler on these buttons that listens for ArrowUp/ArrowDown (and
optionally Home/End), prevents default, finds the list of all data-arch-toggle
buttons in the same accordion group, computes the previous/next (wrap around)
index relative to the current `btn-${arch.id}`, and moves focus to that target
button while leaving aria-expanded behavior unchanged; implement this central
handler in the component script (or a small helper function) and attach it to
the button element so keyboard users can navigate headers with arrow keys.

In `@site/src/components/islands/DashboardPreview.tsx`:
- Around line 168-178: The Prev/Next button handlers in DashboardPreview.tsx
still include conditional logic inside onClick (using activeTab and selectTab)
even though the button is disabled via the disabled prop; remove the redundant
conditional by only attaching the onClick when the button is enabled (e.g., set
onClick to a function that calls selectTab(activeTab - 1) / selectTab(activeTab
+ 1) only if not disabled) or attach a no-op when disabled; update both the
previous button (uses activeTab and selectTab) and the corresponding next button
block (the code around lines 200-210) so the handler is not executed/created
when disabled.

In `@site/src/components/islands/mini/BudgetMini.tsx`:
- Around line 125-130: Move the SVG <defs> block that defines the gradient id
"dp-sparkGrad" so it appears before any elements that reference it (e.g., the
<polyline> that uses "url(`#dp-sparkGrad`)"). Locate the <defs> in BudgetMini (the
block with linearGradient id="dp-sparkGrad") and cut/paste it to the top of the
SVG element (immediately after the opening <svg> tag) to follow conventional
ordering and improve readability.

In `@site/src/components/ParticleNetwork.astro`:
- Around line 61-75: The resize() function uses a non-null assertion on
canvas.parentElement! which can throw if the DOM changes; update resize() to
guard against a missing parent by retrieving const parent = canvas.parentElement
and if (!parent) return (or fallback to canvas.getBoundingClientRect()/default
dimensions), then use parent.getBoundingClientRect() instead of parentElement!.
Also apply the same defensive check wherever canvas.parentElement! is used
(e.g., the other occurrence referenced in the review) so the code safely handles
a missing parent without throwing.

In `@site/src/components/ScrollSyncPanel.astro`:
- Around line 425-456: The code currently removes SVG <animate> elements
permanently when the MediaQueryList prefersReduced.matches is true; add a
listener on the prefersReduced MediaQueryList
(prefersReduced.addEventListener('change' / prefersReduced.onchange)) to handle
dynamic preference changes: when event.matches is true call
disableSvgAnimations(), and when false re-enable animations by re-initializing
the visualization (the same logic that originally injects the SVG <animate>
elements) or as a minimal fallback trigger a component reload (e.g., re-run the
setup that creates the SVG animations or force a page/component refresh). Update
the block around prefersReduced, disableSvgAnimations, and the
IntersectionObserver setup so enabling/disabling motion toggles animations and
step behavior reliably without requiring a full manual page reload.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fc664c4e-1572-420a-acc4-68c431b07079

📥 Commits

Reviewing files that changed from the base of the PR and between a854dcc and 6c2cbe0.

⛔ Files ignored due to path filters (1)
  • site/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • CLAUDE.md
  • site/astro.config.mjs
  • site/package.json
  • site/src/components/ExpandableArchitecture.astro
  • site/src/components/FeatureShowcase.astro
  • site/src/components/ParticleNetwork.astro
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/DashboardPreview.css
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/layouts/Base.astro
  • site/src/pages/index.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Agent
  • GitHub Check: Analyze (python)
  • GitHub Check: Dependency Review
🧰 Additional context used
🧠 Learnings (44)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/package.json : Web dashboard Node.js 22+, TypeScript 6.0+, dependencies in `web/package.json`

Applied to files:

  • site/package.json
  • CLAUDE.md
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)

Applied to files:

  • site/package.json
  • CLAUDE.md
  • site/astro.config.mjs
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard

Applied to files:

  • site/package.json
  • CLAUDE.md
  • site/astro.config.mjs
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/pages/index.astro
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).

Applied to files:

  • site/package.json
  • CLAUDE.md
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/.storybook/{main,preview}.{ts,tsx} : Storybook 10: Use `defineMain` from `storybook/react-vite/node` and `definePreview` from `storybook/react-vite` in Storybook config files

Applied to files:

  • site/package.json
  • site/astro.config.mjs
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{ts,tsx} : CSS side-effect imports need type declarations; use Vite's `/// <reference types="vite/client" />` directive

Applied to files:

  • site/package.json
  • site/astro.config.mjs
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Web dashboard: see `web/CLAUDE.md` for commands, design system, and component inventory

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/api/**/*.md : Library reference in `docs/api/` (auto-generated via mkdocstrings + Griffe, AST-based)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to {docs/rest-api.md,docs/_generated/api-reference.html} : REST API reference in `docs/rest-api.md` + `docs/_generated/api-reference.html` (generated by `scripts/export_openapi.py`)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to pyproject.toml : Docs group in `pyproject.toml` includes: `zensical`, `mkdocstrings[python]`, `griffe-pydantic`

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to scripts/**/*.py : Scripts in `scripts/` (CI/build utilities and development-time validation hooks) — relaxed ruff rules: `print` and deferred imports allowed

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • CLAUDE.md
  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/pages/index.astro
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
📚 Learning: 2026-04-01T18:29:59.468Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T18:29:59.468Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.

Applied to files:

  • CLAUDE.md
  • site/src/components/islands/DashboardPreview.css
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
  • site/src/components/islands/mini/OrgChartMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Install via `uv sync` (installs all deps including dev group by default)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T18:29:59.468Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T18:29:59.468Z
Learning: Use `uv sync` to install all dependencies (dev + test groups).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T18:29:59.468Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T18:29:59.468Z
Learning: Applies to web/** : Use Node.js 22+ and TypeScript 6.0+ for web dashboard.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to pyproject.toml : Dependencies: all versions use == in pyproject.toml. Groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit). Required: mem0ai (Mem0 memory backend — the default and currently only backend). Install: uv sync installs everything (dev group is default).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `font-sans` or `font-mono` for typography (maps to Geist tokens). NEVER set `fontFamily` directly

Applied to files:

  • site/src/layouts/Base.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>` component

Applied to files:

  • site/src/components/UseCaseCards.astro
  • site/src/pages/index.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/UseCaseCards.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/UseCaseCards.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/DashboardPreview.css
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Create a `.stories.tsx` Storybook file alongside each new shared component with all states (default, hover, loading, error, empty)

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to src/synthorg/templates/**/*.py : Templates: pre-built company templates, personality presets, and builder.

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue. DESIGN_SPEC.md is a pointer file linking to the 7 design pages (index, agents, organization, communication, engine, memory, operations).

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Security: SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/security/**/*.py : Security package (security/): SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Gitleaks scans for secrets via pre-commit hook and weekly CI job

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
🔇 Additional comments (21)
site/src/layouts/Base.astro (1)

52-68: Geist fonts are not available on Google Fonts.

Geist and Geist Mono are Vercel's proprietary fonts and are not hosted on Google Fonts. These requests will fail silently, falling back to Inter/JetBrains Mono. To use Geist, you need to either:

  1. Self-host the fonts (download from vercel/geist-font)
  2. Use @fontsource/geist-sans and @fontsource/geist-mono npm packages

[raise_major_issue, request_verification]

Is the Geist font family available on Google Fonts?
site/src/components/islands/DashboardPreview.css (1)

1-107: Well-structured CSS with proper reduced-motion support.

The stylesheet provides:

  • Consistent CSS custom properties for theming
  • Smooth animations for page transitions, counters, pulse effects, and scrolling
  • Comprehensive prefers-reduced-motion handling that disables all animations

Note: The font stack references Geist fonts (line 15-16) which depend on the font loading fix needed in Base.astro.

site/src/components/UseCaseCards.astro (1)

72-98: Good accessibility and responsive implementation.

The scrollable card region properly includes:

  • role="region" and aria-label for screen readers
  • tabindex="0" enabling keyboard scrolling
  • Snap-scroll behavior on mobile with grid layout on larger screens
  • Dynamic color theming per card
site/src/components/FeatureShowcase.astro (1)

89-127: Proper keyboard accessibility with focus-visible rings.

Both hero and compact feature cards implement:

  • focus-visible:outline-none with focus-visible:ring-2 for keyboard navigation
  • Color-coordinated ring colors matching the card theme
  • Proper ring-offset for visual clarity
site/src/components/islands/mini/OrgChartMini.tsx (1)

26-109: Well-implemented React island with proper reduced-motion handling.

The component:

  • Uses matchMedia to detect and respond to motion preference changes
  • Properly cleans up the event listener on unmount
  • Conditionally disables SVG <animate> when reduced motion is preferred
  • Marks the decorative SVG as aria-hidden="true"
site/src/components/islands/mini/AgentDetailMini.tsx (1)

92-108: Index as key is acceptable here for static display list.

While using array index as a React key is generally discouraged, it's acceptable in this case because:

  • The activities array is static and never reorders
  • It's duplicated purely for the infinite scroll visual effect
  • No items are added/removed/filtered dynamically

The dp-activity-scroll animation respects reduced-motion via DashboardPreview.css.

site/src/components/ScrollSyncPanel.astro (1)

119-133: Good accessibility implementation for step navigation.

The dot buttons include:

  • Proper aria-label attributes describing each step's purpose
  • Keyboard accessibility via native <button> elements
  • Visual hover/focus states via Tailwind classes
site/src/components/ParticleNetwork.astro (2)

158-182: Excellent reduced-motion implementation with dynamic toggling.

Unlike ScrollSyncPanel.astro, this component properly handles runtime changes to motion preferences:

  • Listens for change events on the matchMedia query
  • Stops animation and draws a static frame when reduced-motion is enabled
  • Resumes animation when reduced-motion is disabled
  • Cleans up the listener on view transitions

209-215: Proper cleanup on Astro view transitions.

The astro:before-swap listener correctly cleans up:

  • ResizeObserver disconnection
  • Debounce timer clearance
  • Animation flag reset
  • Motion preference event listener removal

Note: This cleanup only fires if Astro View Transitions are enabled. Per the relevant snippet from ScrollSyncPanel.astro, both components rely on this event. Ensure <ViewTransitions /> is included in the layout, or resources may leak on traditional navigation.

[approve_code_changes, request_verification]

#!/bin/bash
# Verify ViewTransitions is enabled in the layout or pages
rg -n "ViewTransitions" --type astro -g '*.astro'
site/src/components/islands/mini/BudgetMini.tsx (1)

12-18: LGTM! Clean gauge calculation logic.

The gauge value clamping, derived metrics, and SVG arc math are correctly implemented. The half-circle circumference formula (Math.PI * radius) and dash offset calculation properly animate the fill arc based on the tick-driven percentage.

site/astro.config.mjs (1)

4-4: LGTM! React integration correctly configured.

The @astrojs/react import and registration in the integrations array follow Astro v5+ conventions. Using default options is appropriate for the dashboard preview island use case.

Also applies to: 11-11

site/package.json (1)

12-25: LGTM! Dependencies correctly declared.

React runtime dependencies (react, react-dom) and the Astro integration (@astrojs/react) are properly added with appropriate version ranges. TypeScript type definitions are correctly placed in devDependencies.

CLAUDE.md (1)

63-64: LGTM! Documentation accurately reflects code changes.

The updates to the landing page description, package structure, and dependencies section are consistent with the actual implementation and follow the existing documentation style.

Also applies to: 109-110, 236-236

site/src/components/ExpandableArchitecture.astro (1)

198-231: LGTM! Toggle script correctly implements accordion behavior.

The script properly:

  • Collapses all panels before expanding the clicked one (single-expand behavior)
  • Manages aria-expanded, aria-hidden, and inert attributes correctly
  • Uses CSS grid-rows transition for smooth animation
site/src/components/islands/mini/TaskBoardMini.tsx (2)

1-80: LGTM! Clean Kanban mini-board implementation.

The component structure is well-organized with clear separation between the MiniCard subcomponent and the main TaskBoardMini. The highlight logic using tick % 6 creates a subtle animation effect alternating between two cards.


82-130: LGTM! Grid layout and footer are correctly implemented.

The 4-column grid layout works well for the Kanban visualization. Column headers with task counts and optional WIP badges provide useful context.

site/src/components/islands/DashboardPreview.tsx (2)

31-44: LGTM! Timer effects correctly manage cleanup.

Both the auto-cycle (6s) and animation tick (1Hz) effects properly clear their intervals on cleanup. The isPaused dependency correctly restarts/stops the auto-cycle timer.


118-146: Tab navigation follows WAI-ARIA tab pattern correctly.

The tablist/tab roles, aria-selected, and aria-controls are correctly implemented. Each tab button properly references the shared tabpanel, and the active tab is visually distinguished.

site/src/pages/index.astro (3)

4-9: LGTM! Component imports are correctly structured.

All new Astro components and the React island import follow Astro conventions. The DashboardPreview import path correctly references the TSX file in the islands directory.


220-220: Excellent use of client:visible for the React island.

Using client:visible ensures React only loads when the dashboard preview section enters the viewport, keeping above-the-fold JS minimal (~2KB as stated in PR objectives). This is the optimal hydration strategy for a below-fold interactive component.


156-161: LGTM! Security section accurately describes the hybrid SecOps model.

The updated text correctly reflects the rule-engine + LLM fallback architecture with 5 autonomy tiers. The phrasing aligns with the design spec's security model.

Comment on lines +145 to +167
<button
id={`btn-${arch.id}`}
data-arch-toggle
aria-expanded="false"
aria-controls={`panel-${arch.id}`}
class="w-full bg-[#1a1f2e] rounded-xl p-6 border border-white/10 hover:border-violet-500/30 transition-colors text-left group cursor-pointer"
>
<div class="flex items-center justify-between">
<div>
<p class="font-semibold text-violet-400">{arch.title}</p>
<p class="text-xs text-gray-400 mt-1">{arch.summary}</p>
</div>
<svg
class="w-4 h-4 text-gray-500 transition-transform duration-300 group-aria-expanded:rotate-180 shrink-0 ml-2"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
</svg>
</div>
</button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Accordion buttons missing keyboard accessibility for arrow key navigation.

The toggle buttons work correctly for click and basic keyboard (Enter/Space), but the WAI-ARIA accordion pattern recommends arrow key navigation between accordion headers. This is a minor accessibility enhancement rather than a blocker.

If you want full WAI-ARIA accordion compliance, add keydown handlers for Up/Down arrows to move focus between buttons. However, the current implementation is functional and accessible for most users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ExpandableArchitecture.astro` around lines 145 - 167, The
accordion buttons (elements using data-arch-toggle / id `btn-${arch.id}`) lack
Up/Down arrow key navigation per WAI-ARIA; add a keydown handler on these
buttons that listens for ArrowUp/ArrowDown (and optionally Home/End), prevents
default, finds the list of all data-arch-toggle buttons in the same accordion
group, computes the previous/next (wrap around) index relative to the current
`btn-${arch.id}`, and moves focus to that target button while leaving
aria-expanded behavior unchanged; implement this central handler in the
component script (or a small helper function) and attach it to the button
element so keyboard users can navigate headers with arrow keys.

Comment on lines +425 to +456
// Reduced motion: disable SVG SMIL animations
const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)");

function disableSvgAnimations(): void {
document.querySelectorAll<SVGElement>("#sync-viz animate").forEach((el) => {
el.parentNode?.removeChild(el);
});
}

if (prefersReduced.matches) {
disableSvgAnimations();
setStep(0);
} else {
const observer = new IntersectionObserver(
(entries) => {
const active = entries
.filter((e) => e.isIntersecting)
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
if (!active) return;
const step = parseInt((active.target as HTMLElement).dataset.step || "0", 10);
setStep(step);
},
{
rootMargin: "-40% 0px -40% 0px",
threshold: [0, 0.25, 0.5, 0.75, 1],
}
);

steps.forEach((step) => observer.observe(step));
document.addEventListener("astro:before-swap", () => observer.disconnect(), { once: true });
setStep(0);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reduced-motion preference changes are not handled dynamically.

When prefers-reduced-motion is initially true, the SVG <animate> elements are permanently removed from the DOM. If the user later disables reduced-motion (without page reload), animations cannot be restored.

Consider listening for motion preference changes like ParticleNetwork.astro does, or document that a page reload is required. This is a minor edge case since most users don't toggle this setting mid-session.

🔧 Optional: Add dynamic motion preference handling
+ prefersReduced.addEventListener("change", (e) => {
+   if (e.matches) {
+     disableSvgAnimations();
+   }
+   // Note: Can't restore removed <animate> elements without re-rendering SVG
+ });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ScrollSyncPanel.astro` around lines 425 - 456, The code
currently removes SVG <animate> elements permanently when the MediaQueryList
prefersReduced.matches is true; add a listener on the prefersReduced
MediaQueryList (prefersReduced.addEventListener('change' /
prefersReduced.onchange)) to handle dynamic preference changes: when
event.matches is true call disableSvgAnimations(), and when false re-enable
animations by re-initializing the visualization (the same logic that originally
injects the SVG <animate> elements) or as a minimal fallback trigger a component
reload (e.g., re-run the setup that creates the SVG animations or force a
page/component refresh). Update the block around prefersReduced,
disableSvgAnimations, and the IntersectionObserver setup so enabling/disabling
motion toggles animations and step behavior reliably without requiring a full
manual page reload.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades the Astro landing page (site/) with several interactive sections (Canvas hero background, scroll-synced “How it Works”, expandable architecture, scrollable use cases, and a React “dashboard preview” island), and refreshes the content to better reflect the product flow and feature set.

Changes:

  • Added new interactive landing page components (Astro + client scripts + a React island for the dashboard preview).
  • Replaced the “Core Pillars” section with a richer “Feature Showcase” card grid.
  • Added React islands support to the site (Astro integration + React deps) and updated base layout fonts/documentation accordingly.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
site/src/pages/index.astro Wires in the new interactive sections and updated landing copy/layout.
site/src/layouts/Base.astro Updates font loading to include Geist/Geist Mono alongside existing fonts.
site/src/components/UseCaseCards.astro Adds horizontally scrollable/snap use case cards (mobile) with desktop grid layout.
site/src/components/ScrollSyncPanel.astro Implements the scroll-synced 4-step split panel with sticky SVG visualization.
site/src/components/ParticleNetwork.astro Adds the Canvas particle network hero background animation.
site/src/components/islands/DashboardPreview.tsx Adds the React island mock dashboard with tab auto-cycling + controls.
site/src/components/islands/DashboardPreview.css Styling + motion-reduction rules for the dashboard preview.
site/src/components/islands/mini/*.tsx Four mini “pages” used by the dashboard preview island.
site/src/components/FeatureShowcase.astro New feature showcase (hero cards + compact cards) with docs links.
site/src/components/ExpandableArchitecture.astro Expandable architecture accordion component (one-at-a-time panels).
site/package.json Adds @astrojs/react, React 19, and React type deps.
site/package-lock.json Lockfile updates for the new React/Astro React dependencies.
site/astro.config.mjs Enables React integration for Astro islands.
CLAUDE.md Updates repository documentation to reflect React islands in site/.
Files not reviewed (1)
  • site/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

site/package-lock.json:23

  • package.json lists @types/react / @types/react-dom under devDependencies, but package-lock.json currently records them under the root dependencies section. This looks like an out-of-sync lockfile and can cause the types packages to be installed in production installs; please regenerate the lockfile so dependency sections match.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +436 to +456
setStep(0);
} else {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
const step = parseInt((entry.target as HTMLElement).dataset.step || "0", 10);
setStep(step);
}
}
},
{
rootMargin: "-45% 0px -45% 0px",
threshold: 0.5,
}
);

steps.forEach((step) => observer.observe(step));
document.addEventListener("astro:before-swap", () => observer.disconnect(), { once: true });
setStep(0);
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefers-reduced-motion branch disables SMIL but also skips setting up the IntersectionObserver, so the visualization/code highlighting never advances past step 0 for reduced-motion users (dot clicks also won't update state because setStep() is only called once). Consider still wiring the observer and just disabling animations / using non-smooth scrolling when reduced motion is enabled.

Suggested change
setStep(0);
} else {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
const step = parseInt((entry.target as HTMLElement).dataset.step || "0", 10);
setStep(step);
}
}
},
{
rootMargin: "-45% 0px -45% 0px",
threshold: 0.5,
}
);
steps.forEach((step) => observer.observe(step));
document.addEventListener("astro:before-swap", () => observer.disconnect(), { once: true });
setStep(0);
}
}
const observer = new IntersectionObserver(
(entries) => {
const active = entries
.filter((e) => e.isIntersecting)
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
if (!active) return;
const step = parseInt((active.target as HTMLElement).dataset.step || "0", 10);
setStep(step);
},
{
rootMargin: "-40% 0px -40% 0px",
threshold: [0, 0.25, 0.5, 0.75, 1],
}
);
steps.forEach((step) => observer.observe(step));
document.addEventListener("astro:before-swap", () => observer.disconnect(), { once: true });
setStep(0);

Copilot uses AI. Check for mistakes.
title: "100+ LLM Providers",
description:
"11 built-in presets, hot-reload management, quota-aware routing, automatic fallback chains.",
href: "/docs/design/providers/",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compact feature links point to /docs/design/providers/, but there is no corresponding docs/design/providers.md in the repo (provider docs appear to live under docs/api/providers.md and/or docs/design/operations.md#providers). This will likely produce a broken link in the built docs site—please update the href to an existing docs route.

Suggested change
href: "/docs/design/providers/",
href: "/docs/api/providers/",

Copilot uses AI. Check for mistakes.
Comment on lines +72 to +78
href: "/docs/design/budget/",
},
{
title: "Tool Sandboxing",
description:
"Subprocess or Docker isolation per tool category. Explicit network controls. MCP protocol support.",
href: "/docs/design/tools/",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several compact feature links use /docs/design/.../ routes that don't exist in docs/design/ (e.g., budget and tools are under docs/api/* or docs/guides/*, not docs/design/*). Updating these hrefs to existing pages will prevent broken links from the landing page.

Suggested change
href: "/docs/design/budget/",
},
{
title: "Tool Sandboxing",
description:
"Subprocess or Docker isolation per tool category. Explicit network controls. MCP protocol support.",
href: "/docs/design/tools/",
href: "/docs/api/budget/",
},
{
title: "Tool Sandboxing",
description:
"Subprocess or Docker isolation per tool category. Explicit network controls. MCP protocol support.",
href: "/docs/api/tools/",

Copilot uses AI. Check for mistakes.
{
name: "Tool System",
description: "Sandboxed execution (subprocess/Docker), MCP protocol, git SSRF prevention, per-category isolation.",
href: "/docs/design/tools/",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tool System links to /docs/design/tools/, but there is no docs/design/tools.md in the repo (tool docs appear under docs/api/tools.md and docs/guides/mcp-tools.md). This href is likely to 404 in the generated docs site; please point it at an existing route.

Suggested change
href: "/docs/design/tools/",
href: "/docs/api/tools/",

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +120
href: "/docs/design/providers/",
},
{
name: "Smart Routing",
description: "Multi-provider resolution, quota-aware selection, fallback chains, task-type model rules.",
href: "/docs/design/providers/",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LLM Providers / Smart Routing submodules link to /docs/design/providers/, but there is no docs/design/providers.md in the repo (provider docs appear under docs/api/providers.md and docs/design/operations.md#providers). This will likely be a broken link from the landing page—please update the href to a real docs page.

Suggested change
href: "/docs/design/providers/",
},
{
name: "Smart Routing",
description: "Multi-provider resolution, quota-aware selection, fallback chains, task-type model rules.",
href: "/docs/design/providers/",
href: "/docs/api/providers/",
},
{
name: "Smart Routing",
description: "Multi-provider resolution, quota-aware selection, fallback chains, task-type model rules.",
href: "/docs/design/operations/#providers",

Copilot uses AI. Check for mistakes.
{
name: "Observability",
description: "Structured logging, correlation tracking, redaction, log shipping (syslog, HTTP), compressed archival.",
href: "/docs/design/observability/",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Observability links to /docs/design/observability/, but there is no docs/design/observability.md in the repo (observability docs appear under docs/api/observability.md and guides like docs/guides/centralized-logging.md). This href is likely broken; please adjust it to an existing route.

Suggested change
href: "/docs/design/observability/",
href: "/docs/api/observability/",

Copilot uses AI. Check for mistakes.
{
name: "Budget Engine",
description: "Hierarchical cascades, 3-layer cost controls, CFO optimization, trend analysis with Theil-Sen regression.",
href: "/docs/design/budget/",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Budget Engine links to /docs/design/budget/, but there is no docs/design/budget.md in the repo (budget documentation appears under docs/guides/budget.md, docs/api/budget.md, and docs/design/operations.md). This will likely 404; please update the href to an existing docs page.

Suggested change
href: "/docs/design/budget/",
href: "/docs/design/operations/",

Copilot uses AI. Check for mistakes.
Comment on lines +170 to +182
};

function start(): void {
resize();

if (prefersReduced.matches) {
drawStaticFrame();
} else {
animating = true;
lastFrame = performance.now();
requestAnimationFrame(draw);
}

Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The canvas animation runs continuously once started (requestAnimationFrame loop) and isn't paused when the hero scrolls out of view or when the tab becomes hidden. Consider pausing/resuming via document.visibilitychange and/or an IntersectionObserver on the canvas container to reduce CPU/battery usage on long sessions.

Copilot uses AI. Check for mistakes.
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 20:10 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/DashboardPreview.tsx`:
- Around line 168-178: The previous/next buttons can call selectTab with
out-of-range indices leading PageComponent to be undefined; update the selectTab
function to validate and clamp its input (e.g., ensure newIndex is between 0 and
pages.length - 1) before updating state, and use that validated index for
setting activeTab and selecting PageComponent (references: selectTab, activeTab,
PageComponent, and the pages array used to compute PageComponent); this prevents
negative or too-large indices even if the onClick is triggered when the button
appears disabled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 749c83b4-18ec-4108-bfe5-3b780224d45a

📥 Commits

Reviewing files that changed from the base of the PR and between 6c2cbe0 and 8c3c984.

📒 Files selected for processing (5)
  • site/src/components/ParticleNetwork.astro
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
📜 Review details
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard

Applied to files:

  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Create a `.stories.tsx` Storybook file alongside each new shared component with all states (default, hover, loading, error, empty)

Applied to files:

  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T18:29:59.468Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T18:29:59.468Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 20:22 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
site/src/components/ExpandableArchitecture.astro (1)

198-231: ⚠️ Potential issue | 🟡 Minor

Arrow-key header navigation is still missing.

These controls expose accordion semantics via aria-expanded/aria-controls, but Up/Down/Home/End handling is still absent, so keyboard users still can’t move between headers with the expected accordion keys.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ExpandableArchitecture.astro` around lines 198 - 231, The
accordion header buttons selected by
document.querySelectorAll("[data-arch-toggle]") need keyboard navigation: add a
keydown handler on each button (in the same loop where addEventListener("click",
... ) is registered) that checks event.key for "ArrowUp"/"ArrowLeft" and
"ArrowDown"/"ArrowRight"/"Home"/"End" and moves focus to the
previous/next/first/last button respectively (wrapping as appropriate), then
update aria-expanded on the newly focused/activated header and toggle the
associated panel (use the same aria-controls/aria-expanded logic and panel class
toggles already implemented). Ensure default scrolling is prevented
(event.preventDefault()) for arrow/home/end keys and that handlers reference the
existing buttons NodeList and each button’s aria-controls to keep behavior
consistent with the click handler.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/DashboardPreview.tsx`:
- Around line 27-28: The children rely on the shared state variable tick, so
when the visible page changes via pageKey the clock must be reset; update the
logic around pageKey (where setPageKey is called or in a useEffect watching
pageKey inside DashboardPreview) to call setTick(0) (or derive a page-local tick
instead) so each tab mounts with tick === 0; ensure you update all places that
change pageKey or mount the mini view so tick is reset on page switch.
- Around line 109-115: The header pills in DashboardPreview are hardcoded ("7
agents", "12 tasks") and diverge from the mock preview data used elsewhere;
import or reference the same mock dataset used by the mini pages (the module
that exports the preview/mock object) and replace the literal strings in the
DashboardPreview component with the dataset fields (e.g., dataset.agentsCount,
dataset.tasksCount and dataset.estimatedCost formatted as EUR) so the header
values match the mini pages and PR objectives.
- Around line 59-66: The onMouseLeave handler currently always calls
setIsPaused(false) and can resume cycling while keyboard focus remains inside
the DashboardPreview; change the onMouseLeave behavior to only unpause when the
preview does not contain the current focus (use
e.currentTarget.contains(document.activeElement) or equivalent) so it mirrors
the onBlur guard, and keep the existing onBlur logic that checks
e.relatedTarget; update the handlers in DashboardPreview.tsx (the
onMouseEnter/onMouseLeave/onFocus/onBlur block surrounding setIsPaused) so
onMouseLeave verifies focus is outside before calling setIsPaused(false).

In `@site/src/components/ParticleNetwork.astro`:
- Around line 160-169: The onMotionChange handler unconditionally restarts
animation; change it to only resume when the hero is currently visible by
checking the visibility flag or the IntersectionObserver state (e.g., an
existing isVisible or heroVisible boolean set by your observer) before setting
animating = true, updating lastFrame, or calling requestAnimationFrame(draw); if
not visible, leave animating false and do not schedule frames. Apply the same
guard to the similar block around lines 211-225 so reduced-motion toggles never
resume the loop while the hero is off-screen.

In `@site/src/components/ScrollSyncPanel.astro`:
- Around line 245-256: The SVG animations and smooth-scroll behavior are always
present in the initial HTML (e.g., the <line> elements with ids edge-comm1,
edge-comm2, edge-task and the step dot elements), causing motion for
prefers-reduced-motion users on first paint; change the markup to render static
SVG (remove or omit <animate> children and any smooth-scroll attributes/classes
in the initial server-rendered markup) and then, in the client script that
currently toggles animations, detect the media query
(window.matchMedia('(prefers-reduced-motion: no-preference)')) and only then
programmatically insert the SMIL <animate> elements into
edge-comm1/edge-comm2/edge-task (and enable smooth scrolling on step dot
elements) so reduced-motion users never receive animations on first paint.

---

Duplicate comments:
In `@site/src/components/ExpandableArchitecture.astro`:
- Around line 198-231: The accordion header buttons selected by
document.querySelectorAll("[data-arch-toggle]") need keyboard navigation: add a
keydown handler on each button (in the same loop where addEventListener("click",
... ) is registered) that checks event.key for "ArrowUp"/"ArrowLeft" and
"ArrowDown"/"ArrowRight"/"Home"/"End" and moves focus to the
previous/next/first/last button respectively (wrapping as appropriate), then
update aria-expanded on the newly focused/activated header and toggle the
associated panel (use the same aria-controls/aria-expanded logic and panel class
toggles already implemented). Ensure default scrolling is prevented
(event.preventDefault()) for arrow/home/end keys and that handlers reference the
existing buttons NodeList and each button’s aria-controls to keep behavior
consistent with the click handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6e0b592e-f420-477b-882f-57ac7064c5e2

📥 Commits

Reviewing files that changed from the base of the PR and between 8c3c984 and b376c3b.

📒 Files selected for processing (7)
  • site/src/components/ExpandableArchitecture.astro
  • site/src/components/FeatureShowcase.astro
  • site/src/components/ParticleNetwork.astro
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (24)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/design/*.md : Update the relevant `docs/design/` page when approved deviations occur to reflect the new reality

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue. DESIGN_SPEC.md is a pointer file linking to the 7 design pages (index, agents, organization, communication, engine, memory, operations).

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue

Applied to files:

  • site/src/components/FeatureShowcase.astro
📚 Learning: 2026-03-18T08:23:08.912Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T08:23:08.912Z
Learning: When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality.

Applied to files:

  • site/src/components/FeatureShowcase.astro
📚 Learning: 2026-04-01T18:29:59.468Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T18:29:59.468Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue. Do not silently diverge from the design spec -- every deviation needs explicit user approval and must be updated in the relevant design page.

Applied to files:

  • site/src/components/FeatureShowcase.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/ScrollSyncPanel.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/ExpandableArchitecture.astro
  • site/src/components/ScrollSyncPanel.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Export props as a TypeScript interface for new components

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard

Applied to files:

  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Create a `.stories.tsx` Storybook file alongside each new shared component with all states (default, hover, loading, error, empty)

Applied to files:

  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T18:29:59.468Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T18:29:59.468Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • site/src/components/ExpandableArchitecture.astro

Comment on lines +27 to +28
const [tick, setTick] = useState(0);
const [pageKey, setPageKey] = useState(0);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reset tick when the visible page changes.

pageKey remounts the mini view, but the children derive their visible state directly from tick, so each tab still opens mid-sequence instead of from frame 0. Reset the clock on tab changes or pass a page-local tick.

Minimal fix
   useEffect(() => {
     if (isPaused) return;
     const timer = setInterval(() => {
-      setActiveTab((t) => (t + 1) % 4);
+      setActiveTab((t) => (t + 1) % pages.length);
+      setTick(0);
       setPageKey((k) => k + 1);
     }, 6000);
     return () => clearInterval(timer);
   }, [isPaused]);
@@
   const selectTab = useCallback((i: number) => {
     const clamped = Math.max(0, Math.min(i, pages.length - 1));
     setActiveTab(clamped);
+    setTick(0);
     setPageKey((k) => k + 1);
     setIsPaused(true);
   }, []);

Also applies to: 30-38, 46-50, 156-157

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/DashboardPreview.tsx` around lines 27 - 28, The
children rely on the shared state variable tick, so when the visible page
changes via pageKey the clock must be reset; update the logic around pageKey
(where setPageKey is called or in a useEffect watching pageKey inside
DashboardPreview) to call setTick(0) (or derive a page-local tick instead) so
each tab mounts with tick === 0; ensure you update all places that change
pageKey or mount the mini view so tick is reset on page switch.

Comment on lines +109 to +115
<div className="flex items-center gap-2">
<span className="text-xs px-2 py-0.5 rounded" style={{ background: "var(--dp-border)", color: "var(--dp-text-muted)" }}>
7 agents
</span>
<span className="text-xs px-2 py-0.5 rounded" style={{ background: "var(--dp-border)", color: "var(--dp-text-muted)" }}>
12 tasks
</span>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Header metrics drift from the agreed preview data.

The PR objectives call out 12 agents / 47 tasks / EUR 18.92 for this preview, but these pills still show 7 agents / 12 tasks. Pull the header numbers from the same mock dataset as the mini pages so the landing page doesn’t contradict itself.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/DashboardPreview.tsx` around lines 109 - 115, The
header pills in DashboardPreview are hardcoded ("7 agents", "12 tasks") and
diverge from the mock preview data used elsewhere; import or reference the same
mock dataset used by the mini pages (the module that exports the preview/mock
object) and replace the literal strings in the DashboardPreview component with
the dataset fields (e.g., dataset.agentsCount, dataset.tasksCount and
dataset.estimatedCost formatted as EUR) so the header values match the mini
pages and PR objectives.

Comment on lines +245 to +256
<!-- Communication edges (animated) -->
<line id="edge-comm1" x1="155" y1="188" x2="220" y2="196" stroke="#2dd4bf" stroke-width="1.2" stroke-opacity="0" stroke-dasharray="5 3" class="transition-all duration-700">
<animate attributeName="stroke-dashoffset" from="0" to="-16" dur="1.5s" repeatCount="indefinite" />
</line>
<line id="edge-comm2" x1="305" y1="160" x2="325" y2="160" stroke="#2dd4bf" stroke-width="1.2" stroke-opacity="0" stroke-dasharray="5 3" class="transition-all duration-700">
<animate attributeName="stroke-dashoffset" from="0" to="-16" dur="2s" repeatCount="indefinite" />
</line>

<!-- Task flow (step 2) -->
<line id="edge-task" x1="210" y1="78" x2="57" y2="137" stroke="#a78bfa" stroke-width="1.5" stroke-opacity="0" class="transition-all duration-700">
<animate attributeName="stroke-dashoffset" from="0" to="-12" dur="1s" repeatCount="indefinite" />
</line>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reduced-motion users still get motion here.

The SVG <animate> nodes are rendered in the initial HTML and only removed after this script runs, so prefers-reduced-motion users can still see animation on first paint. The step dots also always request smooth scrolling. Start from static SVG markup and only opt into SMIL/smooth scrolling when the media query says motion is allowed.

Also applies to: 415-421, 425-436

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ScrollSyncPanel.astro` around lines 245 - 256, The SVG
animations and smooth-scroll behavior are always present in the initial HTML
(e.g., the <line> elements with ids edge-comm1, edge-comm2, edge-task and the
step dot elements), causing motion for prefers-reduced-motion users on first
paint; change the markup to render static SVG (remove or omit <animate> children
and any smooth-scroll attributes/classes in the initial server-rendered markup)
and then, in the client script that currently toggles animations, detect the
media query (window.matchMedia('(prefers-reduced-motion: no-preference)')) and
only then programmatically insert the SMIL <animate> elements into
edge-comm1/edge-comm2/edge-task (and enable smooth scrolling on step dot
elements) so reduced-motion users never receive animations on first paint.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 20:37 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (3)
site/src/components/islands/DashboardPreview.tsx (3)

27-28: ⚠️ Potential issue | 🟡 Minor

Tick is not reset when switching tabs.

The tick value continues incrementing globally. When a user manually switches tabs, each mini page opens mid-animation rather than from frame 0, which can be disorienting. The past review suggested resetting tick on tab change.

🔧 Suggested fix
   const selectTab = useCallback((i: number) => {
     const clamped = Math.max(0, Math.min(i, pages.length - 1));
     setActiveTab(clamped);
+    setTick(0);
     setPageKey((k) => k + 1);
     setIsPaused(true);
   }, []);

Also reset in the auto-cycle effect:

   useEffect(() => {
     if (isPaused) return;
     const timer = setInterval(() => {
       setActiveTab((t) => (t + 1) % pages.length);
+      setTick(0);
       setPageKey((k) => k + 1);
     }, 6000);
     return () => clearInterval(timer);
   }, [isPaused]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/DashboardPreview.tsx` around lines 27 - 28, The
tick state (tick / setTick) isn’t being reset when the active mini-page changes,
so pages open mid-animation; update the tab-change handler that updates pageKey
(setPageKey) to also call setTick(0), and also ensure the auto-cycle effect (the
useEffect that advances tick and/or cycles pageKey) resets tick to 0 when it
changes pages automatically; locate the functions/hooks manipulating pageKey and
the useEffect that increments tick and add setTick(0) whenever pageKey is
updated (both manual tab switch and in the auto-cycle logic).

113-119: ⚠️ Potential issue | 🟡 Minor

Header metrics still inconsistent with PR objectives.

The header displays "7 agents" and "12 tasks", but the PR objectives specify the dashboard preview should show 12 agents, 47 tasks, EUR 18.92. This creates a visual contradiction on the landing page.

🔧 Suggested fix to align with PR objectives
             <div className="flex items-center gap-2">
               <span className="text-xs px-2 py-0.5 rounded" style={{ background: "var(--dp-border)", color: "var(--dp-text-muted)" }}>
-                7 agents
+                12 agents
               </span>
               <span className="text-xs px-2 py-0.5 rounded" style={{ background: "var(--dp-border)", color: "var(--dp-text-muted)" }}>
-                12 tasks
+                47 tasks
               </span>
             </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/DashboardPreview.tsx` around lines 113 - 119, The
header metrics in DashboardPreview are hardcoded to "7 agents" and "12 tasks"
but should match the PR objectives; update the <div className="flex items-center
gap-2"> block inside the DashboardPreview component to render three metric spans
showing "12 agents", "47 tasks", and "EUR 18.92" (or, better, pull these values
from the component's props/state if metrics are available, e.g., metrics.agents,
metrics.tasks, metrics.revenue) and keep the existing styling (text-xs px-2
py-0.5 rounded with the same inline styles) so the landing page matches the PR
requirements.

34-34: 🧹 Nitpick | 🔵 Trivial

Use pages.length instead of hardcoded 4.

The auto-cycle and next-button logic use hardcoded values (4 and 3) instead of deriving from pages.length. This creates a maintenance burden if pages are added/removed.

🔧 Suggested fix
   useEffect(() => {
     if (isPaused) return;
     const timer = setInterval(() => {
-      setActiveTab((t) => (t + 1) % 4);
+      setActiveTab((t) => (t + 1) % pages.length);
       setPageKey((k) => k + 1);
     }, 6000);
     return () => clearInterval(timer);
   }, [isPaused]);

And at line 207:

-          style={{ color: activeTab < 3 ? "var(--dp-text-secondary)" : "var(--dp-border-bright)" }}
+          style={{ color: activeTab < pages.length - 1 ? "var(--dp-text-secondary)" : "var(--dp-border-bright)" }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/DashboardPreview.tsx` at line 34, The code in
DashboardPreview uses hardcoded tab counts (e.g., setActiveTab((t) => (t + 1) %
4) and a next-button that compares to 3) which breaks when pages change; update
those to derive from the pages array length: replace occurrences of 4 with
pages.length (for cycling modulo) and replace 3 with pages.length - 1 (for
last-index comparisons) — locate these in the DashboardPreview component (e.g.,
the setActiveTab call and the next-button logic) and use pages.length
consistently so tab navigation auto-adjusts when pages are added/removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/mini/BudgetMini.tsx`:
- Around line 115-120: The SVG gradient stops inside the linearGradient (id
referenced by sparkGradId) use a hardcoded hex (`#38bdf8`); update the stop
elements to reference the CSS accent variable instead (e.g., use
stopColor="var(--dp-accent)") so the gradient follows the site's accent color,
and keep the hex as a fallback or document it as intentional fallback if browser
support is a concern; modify the stop elements within the linearGradient in
BudgetMini.tsx (the <stop ... stopColor=... /> nodes) accordingly.

In `@site/src/components/ParticleNetwork.astro`:
- Around line 61-77: The resize() handler currently clears the canvas but
doesn't repaint when reduced-motion (animating === false), leaving a blank hero
after resize; after you update the canvas size and node list in resize(), call
the same frame-drawing routine used by the animation loop (the function that
iterates over nodes and renders to ctx — e.g., the frame/draw/render function
that consumes nodes and ctx) when animating is false so the static frame is
immediately repainted; apply the same change to the analogous block around the
visibility/observer logic (the section at ~213-225) so reduced-motion users see
a rendered frame after resize/orientation changes.
- Around line 13-14: The gradient overlay div is intercepting mouse input and
preventing the canvas pointer handlers (the handlers at lines 194-202) from
receiving events; update the overlay div (the element with classes "absolute
inset-0 bg-gradient-to-b ...") to ignore pointer events by adding
pointer-events-none (or style="pointer-events:none;") so the underlying canvas
and its repulsion handlers can receive pointer events.

---

Duplicate comments:
In `@site/src/components/islands/DashboardPreview.tsx`:
- Around line 27-28: The tick state (tick / setTick) isn’t being reset when the
active mini-page changes, so pages open mid-animation; update the tab-change
handler that updates pageKey (setPageKey) to also call setTick(0), and also
ensure the auto-cycle effect (the useEffect that advances tick and/or cycles
pageKey) resets tick to 0 when it changes pages automatically; locate the
functions/hooks manipulating pageKey and the useEffect that increments tick and
add setTick(0) whenever pageKey is updated (both manual tab switch and in the
auto-cycle logic).
- Around line 113-119: The header metrics in DashboardPreview are hardcoded to
"7 agents" and "12 tasks" but should match the PR objectives; update the <div
className="flex items-center gap-2"> block inside the DashboardPreview component
to render three metric spans showing "12 agents", "47 tasks", and "EUR 18.92"
(or, better, pull these values from the component's props/state if metrics are
available, e.g., metrics.agents, metrics.tasks, metrics.revenue) and keep the
existing styling (text-xs px-2 py-0.5 rounded with the same inline styles) so
the landing page matches the PR requirements.
- Line 34: The code in DashboardPreview uses hardcoded tab counts (e.g.,
setActiveTab((t) => (t + 1) % 4) and a next-button that compares to 3) which
breaks when pages change; update those to derive from the pages array length:
replace occurrences of 4 with pages.length (for cycling modulo) and replace 3
with pages.length - 1 (for last-index comparisons) — locate these in the
DashboardPreview component (e.g., the setActiveTab call and the next-button
logic) and use pages.length consistently so tab navigation auto-adjusts when
pages are added/removed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f202cfbd-9917-4400-a1ef-eb370bd289c0

📥 Commits

Reviewing files that changed from the base of the PR and between b376c3b and c7b4315.

📒 Files selected for processing (6)
  • site/src/components/ParticleNetwork.astro
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/TaskBoardMini.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Create a `.stories.tsx` Storybook file alongside each new shared component with all states (default, hover, loading, error, empty)

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/ScrollSyncPanel.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>` component

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/ScrollSyncPanel.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Export props as a TypeScript interface for new components

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T18:29:59.468Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T18:29:59.468Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones. Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets.

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
🔇 Additional comments (4)
site/src/components/ScrollSyncPanel.astro (1)

1-456: LGTM - Well-structured scroll-sync implementation.

The IntersectionObserver setup with -35% root margin provides good scroll detection, the step visualization logic is clean, and the component properly disconnects the observer on astro:before-swap. The SVG visualization progressively reveals elements across steps effectively.

Note: Past review comments flagged that SVG <animate> elements are rendered in initial HTML (users with prefers-reduced-motion may briefly see animation on first paint) and that dynamic motion preference changes aren't handled. Those concerns remain valid but are already tracked.

site/src/components/islands/mini/TaskBoardMini.tsx (1)

103-136: Column rendering JSX is at the threshold of inline complexity.

The JSX inside .map() at lines 103-136 (~33 lines) is moderately complex. While it's self-contained, consider extracting a Column component if this grows further.

Otherwise, the implementation is solid—useMemo correctly depends on tick, column assignments are deterministic, and theming via CSS variables is consistent.

site/src/components/islands/mini/OrgChartMini.tsx (1)

30-36: Good dynamic motion preference handling.

Unlike the Astro component, this React island correctly listens for changes to prefers-reduced-motion and updates state accordingly. The SMIL <animate> at line 71 is conditionally rendered, so reduced-motion users never receive the animation.

site/src/components/islands/mini/BudgetMini.tsx (1)

1-148: Overall implementation is solid.

Good use of useId() to prevent gradient ID collisions when multiple instances render. The gauge math is correct, metric calculations are consistent, and the component properly uses CSS variables for theming throughout (except the noted gradient stops).

@Aureliolo Aureliolo force-pushed the feat/landing-page-interactive branch from c7b4315 to 53c2be0 Compare April 1, 2026 20:58
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 20:59 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
site/src/components/ScrollSyncPanel.astro (1)

413-422: ⚠️ Potential issue | 🟡 Minor

Smooth scrolling ignores reduced-motion preference.

The dot click handler always uses behavior: "smooth" regardless of the user's motion preferences. Users who have prefers-reduced-motion: reduce enabled should receive instant scrolling instead.

Suggested fix
   dots.forEach((dot) => {
     dot.addEventListener("click", () => {
       const stepIdx = parseInt(dot.dataset.dot || "0", 10);
       const target = steps[stepIdx];
       if (target) {
-        target.scrollIntoView({ behavior: "smooth", block: "center" });
+        const behavior = prefersReduced.matches ? "instant" : "smooth";
+        target.scrollIntoView({ behavior, block: "center" });
       }
     });
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ScrollSyncPanel.astro` around lines 413 - 422, The dot
click handler always uses smooth scrolling; change the behavior to respect the
user's reduced-motion preference by checking
window.matchMedia("(prefers-reduced-motion: reduce)").matches inside the
dots.forEach click listener (where dot.addEventListener and
target.scrollIntoView are used) and set the scrollIntoView options to use "auto"
(or "instant"/"auto") when prefers-reduced-motion is true and "smooth" otherwise
so users with reduced-motion enabled get instant scrolling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/mini/AgentDetailMini.tsx`:
- Line 65: The div in AgentDetailMini.tsx currently applies both the Tailwind
class "font-mono" and an inline style fontFamily: "var(--dp-font-mono)" which is
redundant; edit the JSX for the div (the element with className "text-sm
font-semibold font-mono" and style={{ color: m.color, fontFamily:
"var(--dp-font-mono)" }}) to remove the inline fontFamily property while keeping
the color (m.color) and the "font-mono" class, so the mono font is provided by
the class only.
- Around line 94-106: The usage of index as key in the duplicated activities
render is intentional for the visual infinite-scroll effect; update the map in
AgentDetailMini (the {[...activities, ...activities].map((a, i) => ...)} block
where key={i}) to add a concise comment above or beside the element explaining
that the activities array is static and intentionally duplicated, so using the
index as key is deliberate and not a bug.

---

Duplicate comments:
In `@site/src/components/ScrollSyncPanel.astro`:
- Around line 413-422: The dot click handler always uses smooth scrolling;
change the behavior to respect the user's reduced-motion preference by checking
window.matchMedia("(prefers-reduced-motion: reduce)").matches inside the
dots.forEach click listener (where dot.addEventListener and
target.scrollIntoView are used) and set the scrollIntoView options to use "auto"
(or "instant"/"auto") when prefers-reduced-motion is true and "smooth" otherwise
so users with reduced-motion enabled get instant scrolling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 80c8f189-91c1-48f8-8dc0-c9d707243b30

📥 Commits

Reviewing files that changed from the base of the PR and between c7b4315 and 53c2be0.

⛔ Files ignored due to path filters (1)
  • site/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • CLAUDE.md
  • site/astro.config.mjs
  • site/package.json
  • site/src/components/ExpandableArchitecture.astro
  • site/src/components/FeatureShowcase.astro
  • site/src/components/ParticleNetwork.astro
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/DashboardPreview.css
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/layouts/Base.astro
  • site/src/pages/index.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (51)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Web dashboard: see `web/CLAUDE.md` for commands, design system, and component inventory

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/api/**/*.md : Library reference in `docs/api/` (auto-generated via mkdocstrings + Griffe, AST-based)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to {docs/rest-api.md,docs/_generated/api-reference.html} : REST API reference in `docs/rest-api.md` + `docs/_generated/api-reference.html` (generated by `scripts/export_openapi.py`)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • CLAUDE.md
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to pyproject.toml : Docs group in `pyproject.toml` includes: `zensical`, `mkdocstrings[python]`, `griffe-pydantic`

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to scripts/**/*.py : Scripts in `scripts/` (CI/build utilities and development-time validation hooks) — relaxed ruff rules: `print` and deferred imports allowed

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T20:43:15.699Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T20:43:15.699Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard design system: ALWAYS reuse existing components from web/src/components/ui/ before creating new ones

Applied to files:

  • CLAUDE.md
  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard

Applied to files:

  • CLAUDE.md
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/pages/index.astro
  • site/package.json
  • site/astro.config.mjs
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).

Applied to files:

  • CLAUDE.md
  • site/package.json
📚 Learning: 2026-04-01T20:43:15.699Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T20:43:15.699Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard: NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets

Applied to files:

  • CLAUDE.md
  • site/src/components/islands/DashboardPreview.css
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • CLAUDE.md
  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/ExpandableArchitecture.astro
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/pages/index.astro
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)

Applied to files:

  • CLAUDE.md
  • site/package.json
  • site/astro.config.mjs
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/package.json : Web dashboard Node.js 22+, TypeScript 6.0+, dependencies in `web/package.json`

Applied to files:

  • CLAUDE.md
  • site/package.json
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Install via `uv sync` (installs all deps including dev group by default)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to pyproject.toml : Dependencies: all versions use == in pyproject.toml. Groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit). Required: mem0ai (Mem0 memory backend — the default and currently only backend). Install: uv sync installs everything (dev group is default).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to cli/go.mod : CLI uses Go 1.26+. Dependencies: Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `font-sans` or `font-mono` for typography (maps to Geist tokens). NEVER set `fontFamily` directly

Applied to files:

  • site/src/layouts/Base.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>` component

Applied to files:

  • site/src/components/UseCaseCards.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/design/*.md : Update the relevant `docs/design/` page when approved deviations occur to reflect the new reality

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue. DESIGN_SPEC.md is a pointer file linking to the 7 design pages (index, agents, organization, communication, engine, memory, operations).

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue

Applied to files:

  • site/src/components/FeatureShowcase.astro
📚 Learning: 2026-03-18T08:23:08.912Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T08:23:08.912Z
Learning: When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality.

Applied to files:

  • site/src/components/FeatureShowcase.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Create a `.stories.tsx` Storybook file alongside each new shared component with all states (default, hover, loading, error, empty)

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/DashboardPreview.css
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Export props as a TypeScript interface for new components

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders. NEVER hardcode shadow or border values

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to src/synthorg/templates/**/*.py : Templates: pre-built company templates, personality presets, and builder.

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Security: SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/security/**/*.py : Security package (security/): SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Gitleaks scans for secrets via pre-commit hook and weekly CI job

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/.storybook/{main,preview}.{ts,tsx} : Storybook 10: Use `defineMain` from `storybook/react-vite/node` and `definePreview` from `storybook/react-vite` in Storybook config files

Applied to files:

  • site/package.json
  • site/astro.config.mjs
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{ts,tsx} : CSS side-effect imports need type declarations; use Vite's `/// <reference types="vite/client" />` directive

Applied to files:

  • site/package.json
  • site/astro.config.mjs
🔇 Additional comments (18)
site/src/components/islands/mini/TaskBoardMini.tsx (1)

70-95: LGTM!

The useMemo correctly depends on tick, the column assignment logic is deterministic and clear, and task keys use stable task.id values. The CSS variable usage for theming is consistent with other mini components.

site/src/components/UseCaseCards.astro (1)

72-98: LGTM!

Good accessibility implementation with role="region", aria-label, and tabindex="0" for keyboard navigation. The responsive behavior (horizontal snap on mobile, 3-column grid on desktop) and gradient fade hints match the PR requirements well.

site/astro.config.mjs (1)

4-11: LGTM!

Standard @astrojs/react integration setup. The default configuration is appropriate for the React islands use case in this PR.

CLAUDE.md (3)

63-63: LGTM!

Documentation accurately reflects the new React islands architecture and interactive dashboard preview feature added in this PR.


109-109: LGTM!

Package structure documentation correctly notes React islands for interactive sections.


236-236: LGTM!

Dependencies section correctly documents the landing page stack versions.

site/src/components/FeatureShowcase.astro (1)

89-127: LGTM!

Good accessibility implementation with focus-visible ring styles for keyboard navigation on all interactive elements. The conditional color theming is consistent with other components in this PR.

site/package.json (1)

12-19: Package versions are compatible.

The React integration with @astrojs/react@^5.0.2, react@^19.2.4, and react-dom@^19.2.4 is fully compatible with Astro 6.1.2. The @astrojs/react package explicitly supports React 19.x, and compatibility is ensured through coordinated releases between the Astro framework and its official integrations.

site/src/components/ScrollSyncPanel.astro (1)

245-256: Reduced-motion users still see animation on first paint.

The SVG <animate> elements (lines 247, 250, 255) are rendered in the initial HTML and only removed after the script runs. Users with prefers-reduced-motion: reduce will see animations briefly before the DOM is modified.

To properly respect reduced-motion from first paint, start with static SVG (no <animate> children) and only inject SMIL animations when the media query indicates motion is allowed.

site/src/components/islands/DashboardPreview.tsx (2)

113-120: Header metrics still inconsistent with PR objectives.

The header pills show 7 agents and 12 tasks, but the PR objectives and content accuracy notes specify 12 agents and 47 tasks. This contradicts the dashboard preview mini pages which use the agreed data.

Suggested fix
             <div className="flex items-center gap-2">
               <span className="text-xs px-2 py-0.5 rounded" style={{ background: "var(--dp-border)", color: "var(--dp-text-muted)" }}>
-                7 agents
+                12 agents
               </span>
               <span className="text-xs px-2 py-0.5 rounded" style={{ background: "var(--dp-border)", color: "var(--dp-text-muted)" }}>
-                12 tasks
+                47 tasks
               </span>
             </div>

46-51: tick should reset when switching tabs.

When a user switches tabs (either manually or via auto-cycle), the tick counter continues from its current value. This causes mini pages to start mid-sequence rather than from frame 0, making the animation feel inconsistent.

Suggested fix
   const selectTab = useCallback((i: number) => {
     const clamped = Math.max(0, Math.min(i, pages.length - 1));
     setActiveTab(clamped);
+    setTick(0);
     setPageKey((k) => k + 1);
     setIsPaused(true);
   }, []);

Also update the auto-cycle effect:

   useEffect(() => {
     if (isPaused) return;
     const timer = setInterval(() => {
       setActiveTab((t) => (t + 1) % pages.length);
+      setTick(0);
       setPageKey((k) => k + 1);
     }, 6000);
     return () => clearInterval(timer);
   }, [isPaused]);
site/src/components/islands/DashboardPreview.css (1)

1-107: Well-structured CSS theming with comprehensive accessibility support.

The CSS custom properties approach cleanly centralizes design tokens for this island component. The prefers-reduced-motion media query correctly disables all animations and transitions. The animation definitions are appropriate for their visual purposes.

site/src/components/islands/mini/OrgChartMini.tsx (1)

40-134: LGTM!

The component properly handles reduced-motion preferences with a matchMedia listener and cleanup. The SVG is correctly marked aria-hidden="true", and SMIL <animate> elements are conditionally rendered only when motion is allowed. The tick-based cycling of communication patterns works correctly with the modulo operation.

site/src/components/ExpandableArchitecture.astro (1)

142-232: LGTM!

The accordion implementation correctly uses ARIA attributes (aria-expanded, aria-controls, aria-hidden), the inert attribute for collapsed panels, and CSS grid-row transitions for smooth animations. The toggle logic properly collapses all panels before expanding the clicked one. Basic keyboard accessibility (Enter/Space) works correctly.

site/src/components/islands/mini/BudgetMini.tsx (1)

14-148: LGTM!

The component correctly uses useId() for gradient ID stability across SSR/hydration. Previous issues have been addressed: the gradient <defs> block is now positioned at the top of the SVG, and the gradient stops use var(--dp-accent) instead of hardcoded hex values. The gauge math and forecast color logic are correct.

site/src/components/ParticleNetwork.astro (1)

1-243: LGTM!

Previous review issues have been addressed:

  • The gradient overlay now has pointer-events-none (line 14)
  • The onMotionChange handler checks isVisible before resuming animation (line 171)
  • The resize() function repaints a static frame when not animating (lines 78-81)

The implementation properly handles reduced-motion preferences, off-screen pausing via IntersectionObserver, resize with debouncing, and cleanup on Astro view transitions.

site/src/pages/index.astro (2)

1-12: Component composition looks good.

The landing page now cleanly imports and uses the new interactive components. The DashboardPreview React island correctly uses client:visible for above-the-fold JS optimization.


18-19: ParticleNetwork cleanup listener requires ViewTransitions to fire.

The ParticleNetwork component includes cleanup on astro:before-swap, but this event only fires when Astro's ViewTransitions component is enabled. Currently, Base.astro does not include ViewTransitions, so full page reloads will occur and cleanup happens naturally via browser garbage collection.

If you plan to add ViewTransitions later, the cleanup code is already in place.

<div className="text-xs mb-0.5" style={{ color: "var(--dp-text-muted)" }}>
{m.label}
</div>
<div className="text-sm font-semibold font-mono" style={{ color: m.color, fontFamily: "var(--dp-font-mono)" }}>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Redundant font styling.

Both font-mono class and inline fontFamily: "var(--dp-font-mono)" are applied. One is sufficient.

💡 Remove redundant inline style
-            <div className="text-sm font-semibold font-mono" style={{ color: m.color, fontFamily: "var(--dp-font-mono)" }}>
+            <div className="text-sm font-semibold font-mono" style={{ color: m.color }}>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="text-sm font-semibold font-mono" style={{ color: m.color, fontFamily: "var(--dp-font-mono)" }}>
<div className="text-sm font-semibold font-mono" style={{ color: m.color }}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/mini/AgentDetailMini.tsx` at line 65, The div in
AgentDetailMini.tsx currently applies both the Tailwind class "font-mono" and an
inline style fontFamily: "var(--dp-font-mono)" which is redundant; edit the JSX
for the div (the element with className "text-sm font-semibold font-mono" and
style={{ color: m.color, fontFamily: "var(--dp-font-mono)" }}) to remove the
inline fontFamily property while keeping the color (m.color) and the "font-mono"
class, so the mono font is provided by the class only.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 21:13 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
site/src/components/ScrollSyncPanel.astro (2)

425-436: ⚠️ Potential issue | 🟡 Minor

Reduced-motion preference changes are not handled after load.

Line 425-Line 436 applies reduced-motion only once. If OS preference changes while the page is open, the component state won’t adapt.

Suggested fix
  if (prefersReduced.matches) {
    disableSvgAnimations();
  }
+
+ prefersReduced.addEventListener("change", (e) => {
+   if (e.matches) {
+     disableSvgAnimations();
+   } else {
+     // Re-attach animations if you implement programmatic insertion.
+     // Otherwise, consider re-initializing the viz.
+   }
+ });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ScrollSyncPanel.astro` around lines 425 - 436, The code
currently checks prefersReduced once; register a listener on the MediaQueryList
returned by window.matchMedia("(prefers-reduced-motion: reduce)") to respond to
runtime changes: call disableSvgAnimations() when event.matches is true, and
when event.matches is false restore or re-initialize animations (e.g., re-render
the SVG/animations or reload the component) so the UI adapts; use the existing
prefersReduced variable and add prefersReduced.addEventListener('change',
handler) (or prefersReduced.addListener for older browsers) and implement the
handler to call disableSvgAnimations() on matches and to re-enable animations
when not matches.

245-256: ⚠️ Potential issue | 🟠 Major

Reduced-motion users still get animation on first paint.

At Line 247, Line 250, and Line 255, SMIL animations are rendered in initial HTML, then removed only at Line 434-Line 436. This still exposes motion briefly for users with prefers-reduced-motion: reduce.

Suggested fix
- <line id="edge-comm1" ...>
-   <animate attributeName="stroke-dashoffset" from="0" to="-16" dur="1.5s" repeatCount="indefinite" />
- </line>
+ <line id="edge-comm1" ...></line>

- <line id="edge-comm2" ...>
-   <animate attributeName="stroke-dashoffset" from="0" to="-16" dur="2s" repeatCount="indefinite" />
- </line>
+ <line id="edge-comm2" ...></line>

- <line id="edge-task" ...>
-   <animate attributeName="stroke-dashoffset" from="0" to="-12" dur="1s" repeatCount="indefinite" />
- </line>
+ <line id="edge-task" ...></line>
+ function attachSvgAnimations(): void {
+   if (document.querySelector("#edge-comm1 animate")) return;
+   const specs = [
+     ["edge-comm1", "-16", "1.5s"],
+     ["edge-comm2", "-16", "2s"],
+     ["edge-task", "-12", "1s"],
+   ] as const;
+   for (const [id, to, dur] of specs) {
+     const line = document.getElementById(id);
+     if (!line) continue;
+     const anim = document.createElementNS("http://www.w3.org/2000/svg", "animate");
+     anim.setAttribute("attributeName", "stroke-dashoffset");
+     anim.setAttribute("from", "0");
+     anim.setAttribute("to", to);
+     anim.setAttribute("dur", dur);
+     anim.setAttribute("repeatCount", "indefinite");
+     line.appendChild(anim);
+   }
+ }
+
+ if (!prefersReduced.matches) {
+   attachSvgAnimations();
+ } else {
+   disableSvgAnimations();
+ }

Also applies to: 425-436

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ScrollSyncPanel.astro` around lines 245 - 256, The SMIL
<animate> tags for edge-comm1, edge-comm2 and edge-task are included in the
initial HTML causing brief motion for users with prefers-reduced-motion; remove
the inline <animate> elements from those <line id="edge-comm1">, <line
id="edge-comm2"> and <line id="edge-task"> server-side and instead add them at
runtime only if window.matchMedia('(prefers-reduced-motion: reduce)').matches is
false — implement a small client-side script that checks prefers-reduced-motion,
and when motion is allowed dynamically creates/appends the corresponding
<animate> elements (matching the existing attributes like attributeName, from,
to, dur, repeatCount) to those elements; ensure the server-rendered lines have
no <animate> children so reduced-motion users never see a first-paint animation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/mini/AgentDetailMini.tsx`:
- Around line 35-40: The badge in AgentDetailMini uses a hardcoded background
rgba(16,185,129,0.15); replace that with a CSS variable (e.g.
--dp-success-muted) and use it in the span instead of the literal color, or
alternatively use color-mix() against --dp-success to derive a muted variant;
add the new --dp-success-muted to the component's stylesheet or global theme and
update the span in AgentDetailMini to reference that variable (with a fallback
to the original rgba).

---

Duplicate comments:
In `@site/src/components/ScrollSyncPanel.astro`:
- Around line 425-436: The code currently checks prefersReduced once; register a
listener on the MediaQueryList returned by
window.matchMedia("(prefers-reduced-motion: reduce)") to respond to runtime
changes: call disableSvgAnimations() when event.matches is true, and when
event.matches is false restore or re-initialize animations (e.g., re-render the
SVG/animations or reload the component) so the UI adapts; use the existing
prefersReduced variable and add prefersReduced.addEventListener('change',
handler) (or prefersReduced.addListener for older browsers) and implement the
handler to call disableSvgAnimations() on matches and to re-enable animations
when not matches.
- Around line 245-256: The SMIL <animate> tags for edge-comm1, edge-comm2 and
edge-task are included in the initial HTML causing brief motion for users with
prefers-reduced-motion; remove the inline <animate> elements from those <line
id="edge-comm1">, <line id="edge-comm2"> and <line id="edge-task"> server-side
and instead add them at runtime only if
window.matchMedia('(prefers-reduced-motion: reduce)').matches is false —
implement a small client-side script that checks prefers-reduced-motion, and
when motion is allowed dynamically creates/appends the corresponding <animate>
elements (matching the existing attributes like attributeName, from, to, dur,
repeatCount) to those elements; ensure the server-rendered lines have no
<animate> children so reduced-motion users never see a first-paint animation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a04e7a48-edb3-40de-8551-d543838a7cc4

📥 Commits

Reviewing files that changed from the base of the PR and between 53c2be0 and 997eea5.

📒 Files selected for processing (2)
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/islands/mini/AgentDetailMini.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/ScrollSyncPanel.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `font-sans` or `font-mono` for typography (maps to Geist tokens). NEVER set `fontFamily` directly

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/ScrollSyncPanel.astro
🔇 Additional comments (5)
site/src/components/islands/mini/AgentDetailMini.tsx (5)

1-14: LGTM!

Clean static data structure. Using hardcoded colors in the activities data array is acceptable for this static demo content that drives the visual scroll effect.


16-19: LGTM!

The tick-driven computed values create a smooth animation effect. The EUR formatting aligns with PR requirements.


53-70: LGTM!

The metrics grid is well-structured with stable keys. The font styling issue from previous review has been addressed.


112-119: LGTM!

The footer tagline is clean and uses consistent CSS variable styling.


92-109: The dp-activity-scroll animation already respects prefers-reduced-motion. The media query in DashboardPreview.css (lines 101–102) explicitly sets animation: none for users with that preference. No action needed.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 21:21 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/mini/AgentDetailMini.tsx`:
- Around line 92-93: The activity ticker in AgentDetailMini lacks a pause
control; add a pause path by making the scrolling container (the element with
class "dp-activity-scroll" inside AgentDetailMini) focusable (tabIndex=0) and
introduce a paused state that, when true, applies a CSS rule (e.g., a "paused"
class that sets animation-play-state: paused or stops the JS scrolling timer) to
stop the animation. Wire onMouseEnter/onFocus to set paused=true and
onMouseLeave/onBlur to set paused=false, and add a keyboard handler (onKeyDown)
to toggle pause/resume for Space/Escape so keyboard users can control the
ticker. Ensure the state and handlers are implemented in the AgentDetailMini
component and the CSS class name matches the "dp-activity-scroll" element so the
visual animation actually pauses.
- Around line 17-18: The animated metrics tasksCompleted and costToday currently
grow unbounded with tick; change their calculation in AgentDetailMini
(referencing tasksCompleted, costToday and tick) to produce bounded/cycling
values instead of ever-increasing ones—e.g. compute a small cycle value like
cycle = tick % N (or clamp a derived value) and use that to offset a realistic
base (e.g. tasksCompletedBase + Math.floor(cycle/step) and costTodayBase + cycle
* rate) so tasksCompleted and costToday stay within a fixed preview range and
costToday still uses toFixed(2) on the final numeric result.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: db3ad4ae-4eab-4a5a-afaa-664363bccdd6

📥 Commits

Reviewing files that changed from the base of the PR and between 997eea5 and 58dc14e.

📒 Files selected for processing (1)
  • site/src/components/islands/mini/AgentDetailMini.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `font-sans` or `font-mono` for typography (maps to Geist tokens). NEVER set `fontFamily` directly

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders. NEVER hardcode shadow or border values

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T20:43:15.699Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T20:43:15.699Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard: NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
🔇 Additional comments (2)
site/src/components/islands/mini/AgentDetailMini.tsx (2)

94-96: Good clarification on intentional index key usage.

The inline comment clearly documents why key={i} is safe in this duplicated static list case.


7-14: ⚠️ Potential issue | 🟠 Major

Replace hardcoded activity colors with dashboard tokens.

The activities palette is hardcoded with hex literals, which weakens theme consistency for the dashboard-style preview.

♻️ Suggested tokenized update
 const activities = [
-  { time: "2m ago", action: "Completed task `#12`: Schema validation", color: "#10b981" },
-  { time: "5m ago", action: "Delegated subtask to Engineer", color: "#38bdf8" },
-  { time: "8m ago", action: "Approved PR `#47` (quality: 94%)", color: "#10b981" },
-  { time: "12m ago", action: "Started task `#11`: API design", color: "#a78bfa" },
-  { time: "15m ago", action: "Meeting: sprint planning (chair)", color: "#2dd4bf" },
-  { time: "20m ago", action: "Budget alert: 72% daily used", color: "#f59e0b" },
+  { time: "2m ago", action: "Completed task `#12`: Schema validation", color: "var(--dp-success)" },
+  { time: "5m ago", action: "Delegated subtask to Engineer", color: "var(--dp-accent)" },
+  { time: "8m ago", action: "Approved PR `#47` (quality: 94%)", color: "var(--dp-success)" },
+  { time: "12m ago", action: "Started task `#11`: API design", color: "var(--dp-purple)" },
+  { time: "15m ago", action: "Meeting: sprint planning (chair)", color: "var(--dp-teal)" },
+  { time: "20m ago", action: "Budget alert: 72% daily used", color: "var(--dp-warning)" },
 ];

Also applies to: 97-97

⛔ Skipped due to learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T20:43:15.699Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard: NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders. NEVER hardcode shadow or border values

Comment on lines +92 to +93
<div className="h-[72px] overflow-hidden relative">
<div className="dp-activity-scroll">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add a pause path for the auto-scrolling activity ticker.

The ticker continuously animates but has no explicit pause/stop control in this component, which is an accessibility/readability risk for moving content.

🛠️ Suggested hover + keyboard pause behavior
-        <div className="h-[72px] overflow-hidden relative">
-          <div className="dp-activity-scroll">
+        <div
+          className="h-[72px] overflow-hidden relative group"
+          tabIndex={0}
+          aria-label="Recent activity ticker. Focus or hover to pause scrolling."
+        >
+          <div className="dp-activity-scroll group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused]">

Also applies to: 95-107

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/mini/AgentDetailMini.tsx` around lines 92 - 93,
The activity ticker in AgentDetailMini lacks a pause control; add a pause path
by making the scrolling container (the element with class "dp-activity-scroll"
inside AgentDetailMini) focusable (tabIndex=0) and introduce a paused state
that, when true, applies a CSS rule (e.g., a "paused" class that sets
animation-play-state: paused or stops the JS scrolling timer) to stop the
animation. Wire onMouseEnter/onFocus to set paused=true and onMouseLeave/onBlur
to set paused=false, and add a keyboard handler (onKeyDown) to toggle
pause/resume for Space/Escape so keyboard users can control the ticker. Ensure
the state and handlers are implemented in the AgentDetailMini component and the
CSS class name matches the "dp-activity-scroll" element so the visual animation
actually pauses.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 21:29 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
site/src/components/islands/mini/AgentDetailMini.tsx (1)

93-108: ⚠️ Potential issue | 🟠 Major

Provide a real pause path for the auto-scrolling activity ticker.

Line 94 continuously animates moving content, but this block still lacks an explicit user pause mechanism and will read duplicated items twice to assistive tech. Add keyboard/hover pause behavior and hide the duplicated half from screen readers.

Suggested patch
-        <div className="h-[72px] overflow-hidden relative">
-          <div className="dp-activity-scroll">
+        <div
+          className="h-[72px] overflow-hidden relative group"
+          tabIndex={0}
+          aria-label="Recent activity ticker. Focus or hover to pause."
+        >
+          <div className="dp-activity-scroll group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused]">
             {/* Duplicated array for infinite scroll effect -- index key is intentional (static data) */}
             {[...activities, ...activities].map((a, i) => (
-              <div key={i} className="flex items-start gap-2 px-2 py-1">
+              <div key={i} aria-hidden={i >= activities.length} className="flex items-start gap-2 px-2 py-1">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/mini/AgentDetailMini.tsx` around lines 93 - 108,
The activity ticker in AgentDetailMini.tsx duplicates activities via
[...activities, ...activities] and lacks pause and accessibility handling;
update the container (the div with className "dp-activity-scroll") to support
pause on hover and keyboard focus by toggling a paused state via
onMouseEnter/onMouseLeave and onFocus/onBlur (or by adding/removing a CSS class
that pauses the animation), and mark the duplicated second half produced by the
second spread (the mapped items with index i >= activities.length) with
aria-hidden="true" and remove them from tab order so screen readers do not read
items twice; implement the pause state handling inside the component and apply
aria-hidden to elements where i >= activities.length.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/mini/AgentDetailMini.tsx`:
- Around line 7-14: The activities array in AgentDetailMini.tsx currently
hardcodes hex colors; replace the color hex strings in the activities data with
semantic token keys (e.g., "success", "info", "accent", "warning") and update
the render logic where the dot is drawn (referenced in AgentDetailMini render
around the previous line 98) to resolve those token keys to theme-aware CSS
classes or CSS custom properties (e.g., map token -> tailwind/token class or
var(--color-...)) before applying the style; ensure the mapping is centralized
(a small tokenToClass/tokenToVar helper alongside AgentDetailMini or in a theme
util) so the preview follows the active theme instead of using hardcoded hex
values.

---

Duplicate comments:
In `@site/src/components/islands/mini/AgentDetailMini.tsx`:
- Around line 93-108: The activity ticker in AgentDetailMini.tsx duplicates
activities via [...activities, ...activities] and lacks pause and accessibility
handling; update the container (the div with className "dp-activity-scroll") to
support pause on hover and keyboard focus by toggling a paused state via
onMouseEnter/onMouseLeave and onFocus/onBlur (or by adding/removing a CSS class
that pauses the animation), and mark the duplicated second half produced by the
second spread (the mapped items with index i >= activities.length) with
aria-hidden="true" and remove them from tab order so screen readers do not read
items twice; implement the pause state handling inside the component and apply
aria-hidden to elements where i >= activities.length.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0d0b3c38-d24a-465c-b11f-3f2347fc3e9d

📥 Commits

Reviewing files that changed from the base of the PR and between 58dc14e and 3c406d5.

📒 Files selected for processing (1)
  • site/src/components/islands/mini/AgentDetailMini.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `font-sans` or `font-mono` for typography (maps to Geist tokens). NEVER set `fontFamily` directly

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders. NEVER hardcode shadow or border values

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T20:43:15.699Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T20:43:15.699Z
Learning: Applies to web/src/**/*.{ts,tsx} : Web dashboard: NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions -- use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
🔇 Additional comments (1)
site/src/components/islands/mini/AgentDetailMini.tsx (1)

17-20: Bounded tick-cycle metrics look correct.

tick % 20 with derived tasksCompleted and costToday keeps preview values in a realistic range.

Aureliolo and others added 7 commits April 1, 2026 23:35
Add 5 interactive components to the Astro landing page:
- Animated particle network (Canvas hero background with agent nodes)
- Scroll-synced split panel (4-step code + visualization walkthrough)
- Expandable architecture diagram (accordion with detailed sub-modules)
- Scrollable use case cards (horizontal snap on mobile, 6 detailed cards)
- Interactive dashboard preview (React island with 4 mini pages)

Also enriches landing page content: deeper feature showcase replacing
Core Pillars, expanded proof strip, updated security section copy, and
punchier hero subtext showcasing SynthOrg's differentiators.

Closes #294

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix SVG attributeName casing in OrgChartMini (stroke-dashoffset) and
update CLAUDE.md documentation entries to reflect React islands in the
landing page.

Pre-reviewed by 2 agents, 4 findings addressed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Accessibility: add missing button id for aria-labelledby, add
inert/aria-hidden to collapsed accordion panels, complete ARIA tab
pattern with id/aria-controls/aria-labelledby, add dot nav focus
indicator.

Reduced motion: honor prefers-reduced-motion in ScrollSyncPanel by
disabling SVG SMIL animations and skipping scroll observer.

Robustness: graceful canvas context null handling, replace brittle
Tailwind class selectors with data attributes, stabilize
IntersectionObserver by picking highest ratio entry, add observer and
ResizeObserver cleanup for Astro view transitions, defensive guard
for edge agent lookups.

Correctness: fix lg:flex-shrink (invalid Tailwind v4) to lg:shrink,
replace scrollbar Tailwind utilities with native CSS, close sparkline
polyline to baseline, fix legend text (4 levels not 8), rename SVG
gradient id to avoid collisions.

Code quality: simplify nested setState, use Unicode glyphs instead
of set:html, add stylelint blank line, type priorityColors strictly,
move @types to devDependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- OrgChartMini: conditionally render SMIL animate for reduced motion
- ParticleNetwork: clean up matchMedia listener on view transitions
- UseCaseCards: use semantic h3 for card titles, scope CSS mask to class
- FeatureShowcase: add focus-visible ring on card anchors for keyboard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Content:
- Replace fictional `synthorg run` CLI command with actual setup wizard
  flow (template selection -> API/wizard config -> agent collaboration ->
  dashboard observation)
- Show real template scale: 9 built-in templates from 2 agents (Solo
  Builder) to 30+ agents (Enterprise) across up to 9 departments
- Expand SVG org chart from 3 agents to 10 agents across 5 departments
  (Executive, Engineering, Product, Design, QA)
- Update all metrics to reflect realistic agency-scale org (12 agents,
  47 tasks, EUR 18.92 cost)

UX:
- ScrollSyncPanel: move step dots from horizontal bottom to vertical
  side column with numbered clickable buttons showing scroll direction
- DashboardPreview: fix size stability with fixed-height tabpanel
  (h-[280px]/h-[320px] + overflow-hidden)
- DashboardPreview: replace tiny dot nav with proper bottom bar
  featuring prev/next arrows and labeled page buttons

Code quality (CodeRabbit round 3):
- FeatureShowcase: dynamic focus ring color matching card theme
- FeatureShowcase: correct ring-offset background for compact cards
- UseCaseCards: add -webkit-mask-image prefix for Safari
- ParticleNetwork: extract drawEdges/drawNodes helpers (DRY)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…iation

SVG visualization now progressively builds across steps:
- Step 1 (Pick a Template): empty department frames only
- Step 2 (Configure): agents appear with hierarchy edges
- Step 3 (Collaborate): communication edges, task delegation, status
  colors showing active work
- Step 4 (Observe): all green + metrics panel

Dashboard preview font sizes scaled up throughout:
- Header: text-sm for company name, text-xs for badges/status
- Tabs: text-sm with larger icons (14px)
- Sidebar: 8x8 icons (was 6x6), wider padding
- Content area: h-[360px]/h-[420px] (was 280/320)
- Bottom nav: text-xs page labels (was 9px)

Mini component fonts scaled up:
- OrgChartMini: fontSize 12/10 for name/seniority (was 9/7)
- All minis: text-[8px] -> text-xs, text-[9px] -> text-xs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scroll sync: use threshold 0.5 with -45% rootMargin to prevent
title flicker when scrolling between steps.

OrgChartMini: wider viewBox (500x230), repositioned agents for
landscape layout, constrain SVG with max-h-full so it fits the
container without clipping bottom agents.

Gemini + CodeRabbit review fixes:
- ParticleNetwork: defensive null check for canvas.parentElement
  in resize() and ResizeObserver.observe()
- DashboardPreview: remove redundant conditional in disabled
  button onClick handlers
- BudgetMini: use React useId() for SVG gradient ID (prevents
  collisions), move defs before usage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Aureliolo and others added 7 commits April 1, 2026 23:35
Doc links: fix 8 broken hrefs pointing to nonexistent design pages
(/docs/design/providers/, tools/, budget/, observability/) -- all
now point to /docs/design/operations/ where those topics live.

Scroll sync: fix observer rootMargin from -45% to -35% (was too
restrictive, steps never triggered). Observer now always runs even
with prefers-reduced-motion (only SMIL animations disabled, not
step navigation).

Org chart: remove noisy status dots from agent cards, remove bottom
badge, wider SVG viewBox (500x230) for better landscape fit.

ParticleNetwork: pause canvas when off-screen via IntersectionObserver
(CPU/battery savings). Defensive null check for canvas.parentElement.

DashboardPreview: clamp selectTab index to valid range, clean up
redundant onClick conditionals on disabled buttons.

BudgetMini: useId() for gradient (no ID collisions), move defs
before usage, bump text-[7px] to text-[9px].

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Budget gauge: move percentage text above arc, "budget remaining"
below. Increase viewBox height to prevent overlap.

Org chart: highlight edges connected to active agent (solid cyan
vs dashed faint). Active agent visually connected to its neighbors.

Scroll sync steps: Step 2 (Configure) now shows agents WITHOUT
edges. Step 3 (Collaborate) adds ALL edges + communication + status
colors. Clear visual progression between steps.

TaskBoardMini: tasks now move between columns based on tick. Each
task progresses at a different rate (offset by id). Highlight cycles
through tasks. Cards redistribute across Backlog/Progress/Review/Done.

DashboardPreview: onMouseLeave checks if focus is still inside
before resuming auto-cycle (a11y fix).

ParticleNetwork: shared isVisible flag ensures onMotionChange
never restarts animation while hero is off-screen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
OrgChartMini: realistic communication patterns cycling each tick.
TaskBoardMini: remove card highlighting.
ParticleNetwork: pointer-events-none on overlay, repaint on resize
when reduced-motion active.
BudgetMini: var(--dp-accent) for gradient stops.
DashboardPreview: pages.length instead of hardcoded 4/3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AgentDetailMini: remove redundant font-mono Tailwind class (inline
fontFamily var(--dp-font-mono) already handles it). Add comment
explaining intentional index-as-key for infinite scroll effect.

ScrollSyncPanel: dot click respects prefers-reduced-motion (uses
"auto" scroll instead of "smooth").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AgentDetailMini: replace rgba(16,185,129,0.15) with
color-mix(in srgb, var(--dp-success) 15%, transparent) so the
muted green derives from the theme variable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tasksCompleted now cycles 47-51 (was unbounded growth).
costToday now cycles EUR 12.40-15.25 (was unbounded growth).
Uses tick % 20 to create a natural repeating pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded hex colors in activities array with
var(--dp-success), var(--dp-accent), var(--dp-warning)
so the dots follow the dashboard preview theme.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo force-pushed the feat/landing-page-interactive branch from 3c406d5 to 95b4167 Compare April 1, 2026 21:43
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 1, 2026 21:44 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
site/src/layouts/Base.astro (1)

70-70: 🧹 Nitpick | 🔵 Trivial

Body font-family still hardcodes Inter despite Geist being loaded as the primary font.

The font preload URLs now prioritize Geist, and DashboardPreview.css (line 16-17) defines --dp-font-sans: "Geist", "Inter", ..., but the body class still explicitly uses font-['Inter',sans-serif]. This means the page will render in Inter even though Geist is loaded first.

If Geist is intended as the primary font site-wide:

♻️ Proposed fix
-  <body class="bg-[`#0F1219`] text-white font-['Inter',sans-serif] antialiased">
+  <body class="bg-[`#0F1219`] text-white font-['Geist','Inter',sans-serif] antialiased">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/layouts/Base.astro` at line 70, The body element in Base.astro
currently hardcodes Inter via the class font-['Inter',sans-serif] which
overrides the intended primary Geist font; update the body class to use the CSS
variable defined in DashboardPreview.css (--dp-font-sans) or a neutral utility
(e.g., remove the explicit font utility) so the site-wide font resolves to Geist
first; locate the body element in Base.astro and replace the explicit Inter font
utility with usage of the --dp-font-sans variable (or a generic sans fallback)
so Geist, as preloaded and defined in --dp-font-sans, becomes the primary font
site-wide.
♻️ Duplicate comments (2)
site/src/components/islands/mini/AgentDetailMini.tsx (1)

93-95: ⚠️ Potential issue | 🟠 Major

Pause the activity ticker when users interact with it.

This loop keeps animating even when the surrounding preview is paused, so the panel still has moving content while someone is trying to read it.

🛠️ Minimal pause-on-hover/focus fix
-        <div className="h-[72px] overflow-hidden relative">
-          <div className="dp-activity-scroll">
+        <div
+          className="h-[72px] overflow-hidden relative group"
+          tabIndex={0}
+          aria-label="Recent activity ticker. Hover or focus to pause scrolling."
+        >
+          <div className="dp-activity-scroll group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused]">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/mini/AgentDetailMini.tsx` around lines 93 - 95,
The activity ticker inside AgentDetailMini keeps animating even when the preview
is paused; update the dp-activity-scroll element to pause animations on user
interaction by adding hover/focus handlers: in the AgentDetailMini component add
a local state (e.g., isTickerPaused) and set it true on onMouseEnter/onFocus and
false on onMouseLeave/onBlur, then apply a conditional class or inline style to
the element with className "dp-activity-scroll" that sets animation-play-state:
paused when isTickerPaused is true; this will pause the infinite scroll loop
during hover/focus and resume afterward.
site/src/components/islands/DashboardPreview.tsx (1)

113-119: ⚠️ Potential issue | 🟡 Minor

Pull the header pills from the same mock snapshot.

These literals still say 7 agents / 12 tasks, which no longer matches the preview snapshot described in this PR. Keeping them hardcoded will keep drifting the landing page out of sync with the mini pages.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/DashboardPreview.tsx` around lines 113 - 119, The
two hardcoded header pills in DashboardPreview.tsx ("7 agents" and "12 tasks")
must be replaced with values read from the same mock snapshot used to render the
preview mini-page; locate the DashboardPreview component and the span elements
that render the agents/tasks pills and substitute their literal strings with the
corresponding properties from the preview mock object (the mock snapshot or prop
passed into DashboardPreview—use that identifier in this file) so the pill
counts come from the snapshot data instead of being hardcoded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/ExpandableArchitecture.astro`:
- Around line 173-180: The current panels in ExpandableArchitecture.astro are
rendered as JS-only collapsible regions (div with id `panel-${arch.id}`,
aria-hidden and inert) that rely on a click handler to reveal links; replace
each JS-only panel with a semantic <details> and <summary> structure (use the
mapped identifier `btn-${arch.id}` as the summary id/label and
`panel-${arch.id}` as the details element) so the collapse is usable without JS,
remove `inert`/`aria-hidden` from the server-rendered markup, and update any
associated event handlers or CSS transitions (targeting the details open state)
instead of toggling attributes; alternatively, if you must keep the current
structure, render at least the first panel server-side as open (add the `open`
attribute) so the content is accessible without JS — ensure IDs and
aria-labelledby relationships remain consistent.

In `@site/src/components/islands/DashboardPreview.tsx`:
- Around line 30-44: The animation tick effect currently always advances tick;
change the second useEffect that sets setInterval for setTick so it
early-returns (does not create the interval) when isPaused or when the user's
reduced-motion preference is set (e.g., prefersReducedMotion/ reduceMotion
flag); include those flags in the effect's dependency array and clear the timer
when they change so the shared preview clock stops when isPaused or
reduced-motion is enabled. Ensure you reference the existing symbols: useEffect,
setTick, tick timer, isPaused, and your reduced-motion flag
(prefersReducedMotion) when making the change.

In `@site/src/components/islands/mini/BudgetMini.tsx`:
- Around line 23-26: The arc math uses radius = 52 while the SVG path uses A 50
50, causing incorrect gauge fill; update the calculation to use the actual arc
radius (50) or derive it from the SVG arc params so circumference = Math.PI *
actualRadius and dashOffset = circumference * (1 - gaugeValue / 100) reflect the
real arc; adjust the variables radius, circumference, and dashOffset in
BudgetMini (where radius, circumference, dashOffset, and gaugeValue are defined)
so the visual percentage matches the SVG A 50 50 arc.

---

Outside diff comments:
In `@site/src/layouts/Base.astro`:
- Line 70: The body element in Base.astro currently hardcodes Inter via the
class font-['Inter',sans-serif] which overrides the intended primary Geist font;
update the body class to use the CSS variable defined in DashboardPreview.css
(--dp-font-sans) or a neutral utility (e.g., remove the explicit font utility)
so the site-wide font resolves to Geist first; locate the body element in
Base.astro and replace the explicit Inter font utility with usage of the
--dp-font-sans variable (or a generic sans fallback) so Geist, as preloaded and
defined in --dp-font-sans, becomes the primary font site-wide.

---

Duplicate comments:
In `@site/src/components/islands/DashboardPreview.tsx`:
- Around line 113-119: The two hardcoded header pills in DashboardPreview.tsx
("7 agents" and "12 tasks") must be replaced with values read from the same mock
snapshot used to render the preview mini-page; locate the DashboardPreview
component and the span elements that render the agents/tasks pills and
substitute their literal strings with the corresponding properties from the
preview mock object (the mock snapshot or prop passed into DashboardPreview—use
that identifier in this file) so the pill counts come from the snapshot data
instead of being hardcoded.

In `@site/src/components/islands/mini/AgentDetailMini.tsx`:
- Around line 93-95: The activity ticker inside AgentDetailMini keeps animating
even when the preview is paused; update the dp-activity-scroll element to pause
animations on user interaction by adding hover/focus handlers: in the
AgentDetailMini component add a local state (e.g., isTickerPaused) and set it
true on onMouseEnter/onFocus and false on onMouseLeave/onBlur, then apply a
conditional class or inline style to the element with className
"dp-activity-scroll" that sets animation-play-state: paused when isTickerPaused
is true; this will pause the infinite scroll loop during hover/focus and resume
afterward.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: dce4cc4c-5cba-4922-8a53-d6466116e07f

📥 Commits

Reviewing files that changed from the base of the PR and between 3c406d5 and 95b4167.

⛔ Files ignored due to path filters (1)
  • site/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • CLAUDE.md
  • site/astro.config.mjs
  • site/package.json
  • site/src/components/ExpandableArchitecture.astro
  • site/src/components/FeatureShowcase.astro
  • site/src/components/ParticleNetwork.astro
  • site/src/components/ScrollSyncPanel.astro
  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/DashboardPreview.css
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/layouts/Base.astro
  • site/src/pages/index.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Socket Security: Pull Request Alerts
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (56)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones in the React dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/package.json : Web dashboard Node.js 22+, TypeScript 6.0+, dependencies in `web/package.json`

Applied to files:

  • site/package.json
  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard

Applied to files:

  • site/package.json
  • site/astro.config.mjs
  • CLAUDE.md
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/pages/index.astro
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to web/package.json : Web dashboard Node.js 20+; dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, ESLint, vue-tsc)

Applied to files:

  • site/package.json
  • site/astro.config.mjs
  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).

Applied to files:

  • site/package.json
  • CLAUDE.md
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/.storybook/{main,preview}.{ts,tsx} : Storybook 10: Use `defineMain` from `storybook/react-vite/node` and `definePreview` from `storybook/react-vite` in Storybook config files

Applied to files:

  • site/package.json
  • site/astro.config.mjs
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{ts,tsx} : CSS side-effect imports need type declarations; use Vite's `/// <reference types="vite/client" />` directive

Applied to files:

  • site/package.json
  • site/astro.config.mjs
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `font-sans` or `font-mono` for typography (maps to Geist tokens). NEVER set `fontFamily` directly

Applied to files:

  • site/src/layouts/Base.astro
  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Web dashboard: see `web/CLAUDE.md` for commands, design system, and component inventory

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T21:35:00.759Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to docs/design/**/*.md : Update the relevant `docs/design/` page to reflect approved deviations from the original spec

Applied to files:

  • CLAUDE.md
  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Documentation source in `docs/` (Markdown, built with Zensical). Design spec in `docs/design/` (7 pages: index, agents, organization, communication, engine, memory, operations). Architecture in `docs/architecture/` (overview, tech-stack, decision log). Roadmap in `docs/roadmap/`. Security in `docs/security.md`. Licensing in `docs/licensing.md`. Reference in `docs/reference/`. REST API reference in `docs/rest-api.md`. Library reference in `docs/api/` (auto-generated from docstrings). Custom templates in `docs/overrides/`. Config in `mkdocs.yml`.

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/api/**/*.md : Library reference in `docs/api/` (auto-generated via mkdocstrings + Griffe, AST-based)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to {docs/rest-api.md,docs/_generated/api-reference.html} : REST API reference in `docs/rest-api.md` + `docs/_generated/api-reference.html` (generated by `scripts/export_openapi.py`)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-14T15:43:05.601Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-14T15:43:05.601Z
Learning: Applies to docs/** : Docs source in docs/ (Markdown, built with Zensical); design spec in docs/design/ (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • CLAUDE.md
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to pyproject.toml : Docs group in `pyproject.toml` includes: `zensical`, `mkdocstrings[python]`, `griffe-pydantic`

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/api/**/*.py : API package (api/): Litestar REST + WebSocket with controllers, guards, channels, JWT + API key + WS ticket auth, approval gate integration, coordination endpoint, collaboration endpoint, settings endpoint, provider management endpoint (CRUD + test + presets), backup endpoint, RFC 9457 structured errors, AppState hot-reload slots, service auto-wiring (Phase 1 at construction, Phase 2 on startup), lifecycle helpers

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to scripts/**/*.py : Scripts in `scripts/` (CI/build utilities and development-time validation hooks) — relaxed ruff rules: `print` and deferred imports allowed

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T21:35:00.759Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones in the React dashboard

Applied to files:

  • CLAUDE.md
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/pages/index.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • CLAUDE.md
  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/ExpandableArchitecture.astro
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
  • site/src/components/ScrollSyncPanel.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-15T21:20:09.993Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:20:09.993Z
Learning: Applies to web/src/components/** : Vue components organized by feature (agents/, approvals/, budget/, common/, dashboard/, layout/, messages/, org-chart/, tasks/).

Applied to files:

  • CLAUDE.md
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Install via `uv sync` (installs all deps including dev group by default)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-21T12:54:22.557Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T12:54:22.557Z
Learning: Go 1.26+ required; CLI dependencies in `cli/go.mod` (Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to pyproject.toml : Dependencies: all versions use == in pyproject.toml. Groups: test (pytest + plugins, hypothesis), dev (includes test + ruff, mypy, pre-commit, commitizen, pip-audit). Required: mem0ai (Mem0 memory backend — the default and currently only backend). Install: uv sync installs everything (dev group is default).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-21T14:12:17.848Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-21T14:12:17.848Z
Learning: Applies to cli/go.mod : CLI uses Go 1.26+. Dependencies: Cobra, charmbracelet/huh, charmbracelet/lipgloss, sigstore-go, go-containerregistry, go-tuf

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT build card-with-header layouts from scratch -- use `<SectionCard>` component

Applied to files:

  • site/src/components/UseCaseCards.astro
  • site/src/pages/index.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/UseCaseCards.astro
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T21:35:00.759Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to web/src/**/*.{ts,tsx} : Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions in React components; use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/DashboardPreview.css
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/DashboardPreview.css
  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create metric displays with `text-metric font-bold` -- use `<MetricCard>` component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT create complex (>8 line) JSX inside `.map()` -- extract to a shared component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders. NEVER hardcode shadow or border values

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/mini/OrgChartMini.tsx
  • site/src/components/islands/mini/BudgetMini.tsx
  • site/src/components/ScrollSyncPanel.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use density-aware tokens (`p-card`, `gap-section-gap`, `gap-grid-gap`) or standard Tailwind spacing. NEVER hardcode pixel values for layout spacing

Applied to files:

  • site/src/components/islands/mini/AgentDetailMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to docs/design/*.md : Update the relevant `docs/design/` page when approved deviations occur to reflect the new reality

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
📚 Learning: 2026-03-15T18:38:44.202Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:38:44.202Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue. DESIGN_SPEC.md is a pointer file linking to the 7 design pages (index, agents, organization, communication, engine, memory, operations).

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-16T06:24:56.341Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T06:24:56.341Z
Learning: Applies to docs/design/**/*.md : Design specification pages in `docs/design/` must be consulted before implementing features (7 pages: index, agents, organization, communication, engine, memory, operations)

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to docs/design/*.md : Design spec pages: 7 pages in `docs/design/` — index, agents, organization, communication, engine, memory, operations

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:13:44.964Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:13:44.964Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue — DESIGN_SPEC.md is a pointer file linking to 7 design pages (Agents, Organization, Communication, Engine, Memory, Operations)

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/components/ExpandableArchitecture.astro
  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue

Applied to files:

  • site/src/components/FeatureShowcase.astro
📚 Learning: 2026-03-18T08:23:08.912Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T08:23:08.912Z
Learning: When approved deviations occur, update the relevant `docs/design/` page to reflect the new reality.

Applied to files:

  • site/src/components/FeatureShowcase.astro
📚 Learning: 2026-04-01T21:35:00.759Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Always read the relevant `docs/design/` page before implementing any feature or planning any issue; design spec is the starting point for architecture, data models, and behavior

Applied to files:

  • site/src/components/FeatureShowcase.astro
  • site/src/pages/index.astro
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Create a `.stories.tsx` Storybook file alongside each new shared component with all states (default, hover, loading, error, empty)

Applied to files:

  • site/src/components/islands/mini/TaskBoardMini.tsx
  • site/src/components/islands/DashboardPreview.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Export props as a TypeScript interface for new components

Applied to files:

  • site/src/components/islands/mini/OrgChartMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-20T08:28:32.845Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-20T08:28:32.845Z
Learning: Applies to src/synthorg/templates/**/*.py : Templates: pre-built company templates, personality presets, and builder.

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-17T22:08:13.456Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T22:08:13.456Z
Learning: Security: SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies: disabled/weighted/per-category/milestone), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume).

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/security/**/*.py : Security package (security/): SecOps agent, rule engine (soft-allow/hard-deny, fail-closed), audit log, output scanner, output scan response policies (redact/withhold/log-only/autonomy-tiered), risk classifier, risk tier classifier, action type registry, ToolInvoker security integration, progressive trust (4 strategies), autonomy levels (presets, resolver, change strategy), timeout policies (park/resume)

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-17T06:30:14.180Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-17T06:30:14.180Z
Learning: Applies to src/synthorg/security/**/*.py : Security module includes SecOps agent, rule engine (soft-allow/hard-deny), audit log, output scanner, risk classifier, autonomy levels (4 strategies), timeout policies.

Applied to files:

  • site/src/pages/index.astro
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Gitleaks scans for secrets via pre-commit hook and weekly CI job

Applied to files:

  • site/src/pages/index.astro
🔇 Additional comments (12)
site/src/components/ScrollSyncPanel.astro (4)

245-256: Reduced-motion: SMIL animations still render in initial HTML.

The <animate> elements are part of the server-rendered markup (lines 247, 250, 255). Users with prefers-reduced-motion: reduce will see animation on first paint before the client script removes them. This was flagged in a previous review.

The fix requires either:

  1. Not rendering <animate> elements server-side, adding them via JS only when motion is allowed
  2. Using CSS to initially pause animations and only enable them client-side

425-436: Reduced-motion preference changes still not handled dynamically.

The script checks prefersReduced.matches once at load time but doesn't listen for changes. Unlike OrgChartMini.tsx which uses addEventListener("change", handler), this component cannot restore animations if the user toggles their preference. This was flagged in a previous review.


280-311: LGTM on the step synchronization logic.

The setStep function with currentStep guard prevents redundant updates. The SVG element lookups and step-specific visibility logic are well-organized.


438-456: LGTM on IntersectionObserver setup.

Proper configuration with -35% root margin for scroll-synced step detection. The astro:before-swap cleanup correctly disconnects the observer for Astro's view transitions.

site/astro.config.mjs (1)

4-4: LGTM!

Standard React integration setup. The import and registration in the integrations array follow the correct pattern for @astrojs/react v5 with Astro 6.

Also applies to: 11-11

site/package.json (1)

12-25: LGTM!

Dependencies are correctly structured: runtime packages (@astrojs/react, react, react-dom) in dependencies, type packages in devDependencies. React 19 aligns with the project's web dashboard stack.

site/src/components/FeatureShowcase.astro (1)

89-114: LGTM!

Well-structured hero card rendering with proper accessibility features:

  • Focus-visible ring styles for keyboard navigation
  • Color-coded visual hierarchy with consistent theming
  • Semantic anchor elements for navigation

The dynamic class generation using ternary operators with full class name literals will be correctly detected by Tailwind's content scanner.

site/src/components/islands/mini/OrgChartMini.tsx (2)

40-49: Well-implemented reduced-motion handling.

Unlike the server-rendered SVG in ScrollSyncPanel.astro, this React component correctly uses state-driven conditional rendering for SMIL animations. The useEffect properly:

  • Initializes from the current preference
  • Listens for dynamic changes
  • Cleans up the listener on unmount

This allows animations to toggle without page reload when the user changes their motion preference.


55-133: LGTM!

The SVG rendering is clean:

  • Decorative chart correctly marked with aria-hidden="true"
  • CSS custom properties (--dp-font-sans, --dp-bg-card) used for theming consistency
  • Communication edge animations conditionally rendered based on motion preference
CLAUDE.md (1)

63-64: LGTM!

Documentation accurately reflects the new architecture:

  • Landing page now uses React islands via @astrojs/react
  • Dependencies correctly listed (Astro 6, @astrojs/react, React 19, Tailwind CSS 4)

Also applies to: 109-110, 236-236

site/src/components/UseCaseCards.astro (2)

72-98: LGTM!

Well-implemented responsive card layout with strong accessibility:

  • role="region" with aria-label identifies the scrollable area
  • tabindex="0" enables keyboard users to scroll the container
  • Snap-scroll alignment (snap-x snap-mandatory) provides good mobile UX
  • Responsive breakpoint switches from horizontal scroll to grid layout

100-135: Nice custom scrollbar and fade mask implementation.

The CSS properly:

  • Uses both standard (scrollbar-width) and WebKit prefixes for cross-browser support
  • Applies gradient mask only on mobile (max-width: 1023px) where scroll is active
  • Includes both -webkit-mask-image and standard mask-image for compatibility

Comment on lines +173 to +180
{architecture.map((arch) => (
<div
id={`panel-${arch.id}`}
role="region"
aria-labelledby={`btn-${arch.id}`}
aria-hidden="true"
inert
class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-in-out"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t make the architecture links JS-only.

Every panel ships closed with aria-hidden + inert, and the click handler is the only path to reveal the submodule links. If JS is blocked or fails, this section becomes dead UI. In Astro, this is a better fit for semantic <details>/<summary> or at least one server-rendered open panel.

Also applies to: 198-232

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/ExpandableArchitecture.astro` around lines 173 - 180, The
current panels in ExpandableArchitecture.astro are rendered as JS-only
collapsible regions (div with id `panel-${arch.id}`, aria-hidden and inert) that
rely on a click handler to reveal links; replace each JS-only panel with a
semantic <details> and <summary> structure (use the mapped identifier
`btn-${arch.id}` as the summary id/label and `panel-${arch.id}` as the details
element) so the collapse is usable without JS, remove `inert`/`aria-hidden` from
the server-rendered markup, and update any associated event handlers or CSS
transitions (targeting the details open state) instead of toggling attributes;
alternatively, if you must keep the current structure, render at least the first
panel server-side as open (add the `open` attribute) so the content is
accessible without JS — ensure IDs and aria-labelledby relationships remain
consistent.

Comment on lines +30 to +44
// Auto-cycle tabs
useEffect(() => {
if (isPaused) return;
const timer = setInterval(() => {
setActiveTab((t) => (t + 1) % pages.length);
setPageKey((k) => k + 1);
}, 6000);
return () => clearInterval(timer);
}, [isPaused]);

// Animation tick (1Hz)
useEffect(() => {
const timer = setInterval(() => setTick((t) => t + 1), 1000);
return () => clearInterval(timer);
}, []);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Pause and reduced-motion should stop the shared preview clock.

isPaused only stops tab rotation. tick keeps advancing, so hover/focus "pause" still leaves the active mini page changing every second, and reduced-motion users still get automatic updates.

🛠️ Example of a shared animation gate
+  const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
+
+  useEffect(() => {
+    const media = window.matchMedia("(prefers-reduced-motion: reduce)");
+    const sync = () => setPrefersReducedMotion(media.matches);
+    sync();
+    media.addEventListener("change", sync);
+    return () => media.removeEventListener("change", sync);
+  }, []);
+
+  const shouldAnimate = !isPaused && !prefersReducedMotion;
+
   // Auto-cycle tabs
   useEffect(() => {
-    if (isPaused) return;
+    if (!shouldAnimate) return;
     const timer = setInterval(() => {
       setActiveTab((t) => (t + 1) % pages.length);
       setPageKey((k) => k + 1);
     }, 6000);
     return () => clearInterval(timer);
-  }, [isPaused]);
+  }, [shouldAnimate]);

   // Animation tick (1Hz)
   useEffect(() => {
+    if (!shouldAnimate) return;
     const timer = setInterval(() => setTick((t) => t + 1), 1000);
     return () => clearInterval(timer);
-  }, []);
+  }, [shouldAnimate]);

Also applies to: 59-69

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/DashboardPreview.tsx` around lines 30 - 44, The
animation tick effect currently always advances tick; change the second
useEffect that sets setInterval for setTick so it early-returns (does not create
the interval) when isPaused or when the user's reduced-motion preference is set
(e.g., prefersReducedMotion/ reduceMotion flag); include those flags in the
effect's dependency array and clear the timer when they change so the shared
preview clock stops when isPaused or reduced-motion is enabled. Ensure you
reference the existing symbols: useEffect, setTick, tick timer, isPaused, and
your reduced-motion flag (prefersReducedMotion) when making the change.

The arc path uses A 50 50 but the JS calculation used radius=52,
causing the dash offset to not match the visible arc length.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 2, 2026 06:39 — with GitHub Actions Inactive
@socket-security
Copy link
Copy Markdown

socket-security bot commented Apr 2, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​types/​grecaptcha@​3.0.91001007180100
Addednpm/​@​astrojs/​sitemap@​3.7.21001008295100
Addednpm/​@​astrojs/​react@​5.0.2991008296100
Addednpm/​tailwindcss@​4.2.21001008498100
Addednpm/​react@​19.2.41001008497100
Addednpm/​astro@​6.1.2971008898100
Addednpm/​react-dom@​19.2.41001009298100

View full report

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/components/islands/mini/BudgetMini.tsx`:
- Around line 17-28: The forecast never exceeds 500 with the current math, so
change the forecast calculation to allow values >500 (e.g. increase the
multiplier) and keep numeric comparison intact: update the forecast expression
in BudgetMini.tsx (symbol: forecast) from (500 * (1 - gaugeValue / 100) *
1.15).toFixed(2) to use a larger multiplier such as 1.5 (and still call
toFixed(2) for display), so forecastColor (symbol: forecastColor) can
realistically hit the "var(--dp-warning)" branch; ensure you still
parseFloat(forecast) for the comparison.
- Line 53: The progress bar in BudgetMini.tsx currently uses the classes
"transition-all duration-1000" which don't respect prefers-reduced-motion;
update the element that renders the progress fill (the same element using
transition-all) to add a reduced-motion fallback such as
"motion-reduce:transition-none" (or equivalent framework utility) so users with
prefers-reduced-motion will get no transition; keep the existing classes and
just append the motion-reduce utility to the className on the progress/fill
element (the element related to .dp-gauge-fill / progress fill).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3f31bbd3-e4e3-4aff-a5f4-64bfafdc9c5e

📥 Commits

Reviewing files that changed from the base of the PR and between 95b4167 and fb64e18.

📒 Files selected for processing (1)
  • site/src/components/islands/mini/BudgetMini.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones in the React dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T21:35:00.759Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to web/src/**/*.{ts,tsx} : Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions in React components; use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders. NEVER hardcode shadow or border values

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
🔇 Additional comments (1)
site/src/components/islands/mini/BudgetMini.tsx (1)

15-16: Good use of useId for SVG gradient IDs.

This avoids duplicate id collisions when multiple instances render.

Also applies to: 115-132

strokeLinecap="round"
strokeDasharray={`${circumference}`}
strokeDashoffset={dashOffset}
className="dp-gauge-fill"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether reduced-motion handling exists for BudgetMini animations.
# Expected: either Tailwind motion-reduce utilities on the elements,
# or CSS media-query overrides for `.dp-gauge-fill` and related transitions.

rg -n -C3 'dp-gauge-fill|transition-all|motion-reduce|prefers-reduced-motion' site/src

Repository: Aureliolo/synthorg

Length of output: 25621


🏁 Script executed:

# Check imports and CSS dependencies in BudgetMini.tsx
head -60 site/src/components/islands/mini/BudgetMini.tsx

Repository: Aureliolo/synthorg

Length of output: 2290


🏁 Script executed:

# Check if DashboardPreview.css or other CSS files are imported
rg -n 'import.*\.css|import.*DashboardPreview' site/src/components/islands/mini/

Repository: Aureliolo/synthorg

Length of output: 44


🏁 Script executed:

# Look for any motion-reduce or prefers-reduced-motion handling in BudgetMini.tsx
rg -n 'motion-reduce|prefers-reduced-motion|matchMedia' site/src/components/islands/mini/BudgetMini.tsx

Repository: Aureliolo/synthorg

Length of output: 44


🏁 Script executed:

# Get full file length
wc -l site/src/components/islands/mini/BudgetMini.tsx

Repository: Aureliolo/synthorg

Length of output: 113


🏁 Script executed:

# Read full BudgetMini.tsx to check all imports and CSS references
cat site/src/components/islands/mini/BudgetMini.tsx

Repository: Aureliolo/synthorg

Length of output: 6083


🏁 Script executed:

# Check where dp-gauge-fill is actually defined
rg -l 'dp-gauge-fill' site/src --type css

Repository: Aureliolo/synthorg

Length of output: 110


🏁 Script executed:

# Check if DashboardPreview.css is imported globally or in layout
rg -n 'DashboardPreview.css|dp-gauge-fill|dp-border|dp-accent' site/src/layouts/ site/src/components/Layout.astro 2>/dev/null || true

Repository: Aureliolo/synthorg

Length of output: 44


🏁 Script executed:

# Check if DashboardPreview.css is imported in the main layout or globally
rg -n 'DashboardPreview.css' site/src --type astro --type tsx --type ts

Repository: Aureliolo/synthorg

Length of output: 91


🏁 Script executed:

# Check where DashboardPreview component is used and how CSS is scoped
head -100 site/src/components/islands/DashboardPreview.tsx | grep -E "import|className|css"

Repository: Aureliolo/synthorg

Length of output: 744


🏁 Script executed:

# Look for how Tailwind handles motion-reduce for duration classes
rg -A2 'motion-reduce|duration-1000' site/src/components --type tsx | head -50

Repository: Aureliolo/synthorg

Length of output: 89


🏁 Script executed:

# Check where BudgetMini is used - is it always within DashboardPreview?
rg -n 'BudgetMini' site/src --type tsx

Repository: Aureliolo/synthorg

Length of output: 89


🏁 Script executed:

# Check Tailwind config to see if motion-reduce is enabled globally
find site -name 'tailwind.config.*' -o -name 'tailwind.config.js' | head -1 | xargs cat

Repository: Aureliolo/synthorg

Length of output: 44


🏁 Script executed:

# Check if there's a globals CSS or base layout that imports DashboardPreview.css
rg -n 'DashboardPreview.css|import.*css' site/src/layouts/ site/src/ -m 10 | grep -E 'layout|main|index'

Repository: Aureliolo/synthorg

Length of output: 183


🏁 Script executed:

# Check if BudgetMini is used outside DashboardPreview
rg -B2 -A2 'BudgetMini' site/src

Repository: Aureliolo/synthorg

Length of output: 1198


🏁 Script executed:

# Check Tailwind config for motion settings
find site -name '*.config.*' -type f | xargs cat 2>/dev/null | grep -A10 'motion\|animation'

Repository: Aureliolo/synthorg

Length of output: 44


🏁 Script executed:

# Check if transition-all respects motion-reduce in Tailwind by default
rg -n 'transition-all.*motion' site --type css

Repository: Aureliolo/synthorg

Length of output: 44


Add reduced-motion fallback for the progress bar animation.

The gauge arc (line 53, .dp-gauge-fill) respects prefers-reduced-motion via the linked CSS file. However, the progress bar animation at lines 97–99 uses transition-all duration-1000 without an explicit fallback. Add motion-reduce:transition-none or similar to disable the animation for users who prefer reduced motion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/mini/BudgetMini.tsx` at line 53, The progress bar
in BudgetMini.tsx currently uses the classes "transition-all duration-1000"
which don't respect prefers-reduced-motion; update the element that renders the
progress fill (the same element using transition-all) to add a reduced-motion
fallback such as "motion-reduce:transition-none" (or equivalent framework
utility) so users with prefers-reduced-motion will get no transition; keep the
existing classes and just append the motion-reduce utility to the className on
the progress/fill element (the element related to .dp-gauge-fill / progress
fill).

With 1.15x, forecast maxed at ~402 (never exceeding 500 budget),
making the warning branch dead code. With 1.5x, forecast reaches
~525 when gauge is low, correctly showing the warning color.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 2, 2026 06:53 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
site/src/components/islands/mini/BudgetMini.tsx (1)

97-99: ⚠️ Potential issue | 🟡 Minor

Add reduced-motion fallback to the agent spend bar transitions.

Line 97 still animates unconditionally; this should respect prefers-reduced-motion.

♿ Minimal fix
-                  className="h-full rounded-full transition-all duration-1000"
+                  className="h-full rounded-full transition-all duration-1000 motion-reduce:transition-none"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/components/islands/mini/BudgetMini.tsx` around lines 97 - 99, The
agent spend bar currently always uses "transition-all duration-1000" (the JSX
element with className="h-full rounded-full transition-all duration-1000" and
style={{ width: `${a.pct}%`, background: a.color }}), which ignores the user's
prefers-reduced-motion setting; detect prefers-reduced-motion (e.g. via
window.matchMedia('(prefers-reduced-motion: reduce)') or a
usePrefersReducedMotion hook) and conditionally remove the transition classes or
set transition: 'none' on that element when reduced motion is requested so the
bar updates instantly for those users.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@site/src/components/islands/mini/BudgetMini.tsx`:
- Around line 97-99: The agent spend bar currently always uses "transition-all
duration-1000" (the JSX element with className="h-full rounded-full
transition-all duration-1000" and style={{ width: `${a.pct}%`, background:
a.color }}), which ignores the user's prefers-reduced-motion setting; detect
prefers-reduced-motion (e.g. via window.matchMedia('(prefers-reduced-motion:
reduce)') or a usePrefersReducedMotion hook) and conditionally remove the
transition classes or set transition: 'none' on that element when reduced motion
is requested so the bar updates instantly for those users.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c90591bf-1d6b-477c-86ae-ca2c34eb5220

📥 Commits

Reviewing files that changed from the base of the PR and between fb64e18 and 21e0fa9.

📒 Files selected for processing (1)
  • site/src/components/islands/mini/BudgetMini.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependency Review
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : Use React 19, TypeScript 6.0+, and design system tokens from shadcn/ui + Tailwind CSS 4 + Radix UI in web dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to web/src/**/*.{ts,tsx} : Always reuse existing components from `web/src/components/ui/` before creating new ones in the React dashboard
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : ALWAYS reuse existing components from `web/src/components/ui/` before creating new ones (StatusBadge, MetricCard, Sparkline, SectionCard, AgentCard, DeptHealthBar, ProgressGauge, StatPill, Avatar, Button, Toast, Skeleton, EmptyState, ErrorBoundary, ConfirmDialog, CommandPalette, InlineEdit, AnimatedPresence, StaggerGroup, Drawer, InputField, SelectField, SliderField, ToggleField, TaskStatusIndicator, PriorityBadge, ProviderHealthBadge, TokenUsageBar, CodeMirrorEditor, SegmentedControl, ThemeToggle, LiveRegion, MobileUnsupportedOverlay, LazyCodeMirrorEditor, TagInput, MetadataGrid, ProjectStatusBadge, ContentTypeBadge)

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T21:35:00.759Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-01T21:35:00.759Z
Learning: Applies to web/src/**/*.{ts,tsx} : Never hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions in React components; use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Tailwind semantic classes (`text-foreground`, `bg-card`, `text-accent`, `text-success`, `bg-danger`) or CSS variables (`var(--so-*)`) for colors. NEVER hardcode hex values or rgba() in `.tsx`/`.ts` files

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/components/ui/**/*.tsx : Use design tokens exclusively in new components -- no hardcoded colors, fonts, or spacing

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-03-31T14:17:24.182Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T14:17:24.182Z
Learning: Applies to web/src/**/*.{ts,tsx} : NEVER hardcode hex colors, font-family, pixel spacing, or Framer Motion transitions — use design tokens and `@/lib/motion` presets

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Do NOT recreate status dots inline -- use `<StatusBadge>` component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use token variables (`var(--so-shadow-card-hover)`, `border-border`, `border-bright`) for shadows and borders. NEVER hardcode shadow or border values

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use Framer Motion presets from `@/lib/motion` instead of hardcoded transition durations

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
📚 Learning: 2026-04-01T06:54:44.133Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `health?` prop (optional, shows N/A when null) and `agentCount` (required) for DeptHealthBar component

Applied to files:

  • site/src/components/islands/mini/BudgetMini.tsx
🔇 Additional comments (2)
site/src/components/islands/mini/BudgetMini.tsx (2)

24-26: Arc dash math now correctly matches the SVG geometry.

Line 24 using radius 50 aligns with the A 50 50 path, so the gauge fill percentage renders consistently.


17-29: ⚠️ Potential issue | 🟠 Major

Forecast warning state is still unreachable with current thresholds.

At Line 28, forecast <= 500 stays true for the current gaugeValue range from Lines 17-21, so the warning color branch never executes.

💡 Proposed fix
-  const spent = (500 * (1 - gaugeValue / 100)).toFixed(2);
-  const remaining = (500 * (gaugeValue / 100)).toFixed(2);
-  const forecast = (500 * (1 - gaugeValue / 100) * 1.5).toFixed(2);
+  const monthlyBudget = 500;
+  const spentValue = monthlyBudget * (1 - gaugeValue / 100);
+  const remainingValue = monthlyBudget * (gaugeValue / 100);
+  const forecastValue = spentValue * 1.5;
+  const spent = spentValue.toFixed(2);
+  const remaining = remainingValue.toFixed(2);
+  const forecast = forecastValue.toFixed(2);
@@
-  const forecastColor = parseFloat(forecast) <= 500 ? "var(--dp-success)" : "var(--dp-warning)";
+  const warningThreshold = monthlyBudget * 0.6; // tune to intended UX threshold
+  const forecastColor =
+    forecastValue >= warningThreshold ? "var(--dp-warning)" : "var(--dp-success)";
⛔ Skipped due to learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `color?` and `animated?` props for Sparkline component (inline SVG trend lines)
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use `variant?` prop (defaults to `'circular'`) and `max?` prop (defaults to 100) for ProgressGauge component
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: web/CLAUDE.md:0-0
Timestamp: 2026-04-01T06:54:44.133Z
Learning: Applies to web/src/**/*.{tsx,ts} : Use role="meter" for TokenUsageBar component with animated multi-segment transitions

@Aureliolo Aureliolo merged commit 49868cb into main Apr 2, 2026
27 checks passed
@Aureliolo Aureliolo deleted the feat/landing-page-interactive branch April 2, 2026 07:15
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview April 2, 2026 07:15 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Apr 2, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.6](v0.5.5...v0.5.6)
(2026-04-02)


### Features

* calendar + hybrid ceremony scheduling strategies
([#985](#985))
([59a9b84](59a9b84)),
closes [#969](#969)
[#970](#970)
* landing page interactive components
([#984](#984))
([49868cb](49868cb))
* log aggregation and shipping (syslog, HTTP, compression)
([#964](#964))
([84be9f8](84be9f8))
* restructure builtin templates into inheritance tree
([#982](#982))
([3794c12](3794c12))
* sprint ceremony runtime scheduler with pluggable strategies
([#983](#983))
([43564a9](43564a9))


### Maintenance

* add no-bash-file-writes rule to CLAUDE.md
([#968](#968))
([a854dcc](a854dcc))
* bump web dependencies (lodash, eslint-react v4, storybook, playwright,
esbuild, codemirror)
([#987](#987))
([c344dfb](c344dfb))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: landing page interactive components

2 participants