Skip to content

feat(docs): add Next.js-style landing page to the docs site#107

Merged
ZingerLittleBee merged 14 commits into
mainfrom
toronto
May 15, 2026
Merged

feat(docs): add Next.js-style landing page to the docs site#107
ZingerLittleBee merged 14 commits into
mainfrom
toronto

Conversation

@ZingerLittleBee
Copy link
Copy Markdown
Owner

@ZingerLittleBee ZingerLittleBee commented May 15, 2026

Summary

  • Replace the placeholder docs home (/$lang) with a dark-only, Next.js-style marketing landing page rendered inside the existing Fumadocs HomeLayout.
  • Bilingual (EN/CN) with all copy centralised in translations.ts; no new runtime deps.
  • 7 sections: Hero (with animated mini server card + copy-to-clipboard install command), trust strip, three pillars, an 8-tile bento grid, how-it-works flow, and final CTA.
  • All visuals are pure CSS keyframes + inline SVG (no screenshots, no animation libraries). Scoped under .serverbee-landing so the docs reader is unaffected; landing CSS budget kept small.
  • Landing route forces dark mode and hides the theme switch (the page is dark-only); docs pages keep the theme toggle.
  • Accessibility: prefers-reduced-motion fallback, aria-label/role="img" on every animated demo, visible focus rings; fully responsive and SSR-safe.

Notable polish

  • Install command wraps cleanly instead of overflowing.
  • Orbit icons stay upright while their centers travel along a dashed ring path.
  • Stream particles and the how-it-works light band sweep the full track width.
  • Bento body text clamps to 3 lines (unlayered rule to outrank Fumadocs base styles); file-tree no longer overflows into the card heading.

Test plan

  • bun run typecheck passes (apps/docs)
  • bun x ultracite check src passes (apps/docs)
  • bun run build (production SSR build) succeeds
  • /en and /cn render every section with translated copy
  • Fumadocs nav still works (search, language switch, GitHub link)
  • Docs pages (e.g. /en/docs/quick-start) still show the theme toggle
  • prefers-reduced-motion: reduce shows no motion and no broken layout

Summary by CodeRabbit

  • New Features
    • Launched a new docs landing page featuring multiple animated sections with bilingual support (English and Chinese).
    • Includes hero, trust indicators, feature pillars, animated demos, how-it-works, and call-to-action sections.
    • Added one-click copy functionality for installation commands.
    • All animations use CSS and SVG with full support for reduced motion preferences.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
server-bee-docs Ready Ready Preview, Comment May 15, 2026 1:07pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

📝 Walkthrough

Walkthrough

This PR implements a complete landing page for the ServerBee docs featuring a dark-mode-only, bilingual (English/Chinese) layout with scoped CSS animations, seven content sections, thirteen micro-animation components, and full i18n support.

Changes

Landing Page Feature

Layer / File(s) Summary
Styles, Translations, and Foundation
apps/docs/src/styles/app.css, apps/docs/src/styles/landing.css, apps/docs/src/components/landing/translations.ts
Landing CSS is scoped to .serverbee-landing and includes keyframes for pulse, ring, orbit, stream particles, blink, typewriter, and fade cycles; a @media (prefers-reduced-motion: reduce) override; utilities for line-clamping; and translations for English/Chinese hero, trust, pillars, bento, how-it-works, and final CTA copy with fallback to English.
Core UI Primitives
apps/docs/src/components/landing/primitives/*
Reusable components: Section wraps content with max-width centering, GradientHeading renders h1/h2/h3 tags with responsive sizing, CodeCopy provides clipboard copy with 1.5-second success feedback, and HexBackground renders a decorative SVG hex pattern in an absolutely positioned layer.
Hero Dashboard Animation
apps/docs/src/components/landing/animations/mini-dashboard.tsx
MiniDashboard composes Ring (SVG circular progress with label/value), Sparkline (horizontal SVG line chart with clip-path animation), and Stat (label/value pairs); used as visual showcase in hero section.
Pillar Section Animations
apps/docs/src/components/landing/animations/install-binary.tsx, data-stream.tsx, orbit-icons.tsx
Three feature cards: InstallBinaryAnim shows systemd-active status with pulsing dot; DataStreamAnim renders Endpoint nodes and Particle streams with staggered delays; OrbitIconsAnim positions three icons at 120° intervals via OrbitItem transform math.
Bento Grid Animations
apps/docs/src/components/landing/animations/{ping-chart,terminal-demo,file-tree,docker-stack,color-ring,alert-bell,monitor-dots,upgrade-loop}.tsx, light-band.tsx
Eight micro-demos plus divider: network latency (SVG paths + 60-cell grid), terminal transcript, file-tree rows with indent, docker containers, conic-gradient color ring, bell icon with channel pills, monitor probes, version upgrade transition, and horizontal light-band gradient arrow.
Section Components
apps/docs/src/components/landing/sections/*
Six section components compose animations and copy: Hero integrates mini-dashboard, badge, heading, two CTAs, and install block; TrustStrip lists trust icons; Pillars maps three animations to cards; Bento grids eight animated tiles; HowItWorks shows 3-step flow with arrows; FinalCta links to docs and install.
Landing Page Orchestration & Route
apps/docs/src/components/landing/index.tsx, apps/docs/src/routes/$lang/index.tsx
LandingPage composes all six sections and wraps in dark-scheme wrapper; route rewrite replaces inline CTA with LandingPage rendering, disables theme switch, and maps lang param to LandingLang with fallback to English.
Documentation & Spec
docs/superpowers/specs/2026-05-15-docs-landing-page-design.md, docs/superpowers/plans/2026-05-15-docs-landing-page.md
Spec defines goals (dark-only, bilingual, no deps, CSS animations), information architecture (7 sections), and acceptance criteria; plan breaks implementation into 7 tasks (CSS, primitives, hero, pillars, bento, how-it-works/CTA, QA) with verification milestones.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A landing page hops into view,
Dark and bilingual, animated true,
With rings that spin, streams that flow,
Bento tiles put on a show!
No new deps, just CSS dreams—
ServerBee now sparkles and gleams.

🚥 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 80.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 clearly and specifically describes the main change: adding a Next.js-style landing page to the docs site, which aligns with the extensive changeset introducing multiple landing page sections, animations, and translations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch toronto

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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

🧹 Nitpick comments (10)
apps/docs/src/components/landing/animations/data-stream.tsx (1)

32-40: 💤 Low value

Consider using explicit aria-hidden value.

Line 35 uses aria-hidden without an explicit value. While this works in React (treated as true), the recommended practice is to use aria-hidden="true" or aria-hidden={true} for clarity and consistency.

♻️ Suggested improvement
     <span
-      aria-hidden
+      aria-hidden="true"
       className={`stream-particle absolute top-1/2 h-1.5 w-3 -translate-y-1/2 rounded-full ${colorClass}`}
       style={{ animationDelay: delay, animationDirection: reverse ? 'reverse' : 'normal' }}
     />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/animations/data-stream.tsx` around lines 32
- 40, The Particle component uses a bare aria-hidden attribute which relies on
JSX truthiness; update the JSX in function Particle to set aria-hidden
explicitly (e.g., aria-hidden="true" or aria-hidden={true}) on the span so
accessibility intent is clear and consistent with other components.
apps/docs/src/components/landing/animations/color-ring.tsx (1)

2-3: ⚡ Quick win

Move gradient calculation outside render path.

The stops array and gradient string are recalculated on every render, even though they never change. Extract stops as a module constant and either compute gradient once at module scope or memoize it with useMemo.

⚡ Proposed fix to optimize gradient calculation
+const COLOR_STOPS = ['#ffb300', '#4cc9f0', '#22c55e', '#a855f7', '#ef4444', '#ffb300']
+const CONIC_GRADIENT = COLOR_STOPS.map((c, i) => `${c} ${(i / (COLOR_STOPS.length - 1)) * 360}deg`).join(', ')
+
 export function ColorRingAnim() {
-  const stops = ['#ffb300', '#4cc9f0', '#22c55e', '#a855f7', '#ef4444', '#ffb300']
-  const gradient = stops.map((c, i) => `${c} ${(i / (stops.length - 1)) * 360}deg`).join(', ')
   return (
     <div
       aria-label="Animated demo of theme customization"
       className="flex h-full items-center justify-center"
       role="img"
     >
       <div className="relative">
-        <div className="orbit-anim h-28 w-28 rounded-full" style={{ background: `conic-gradient(${gradient})` }} />
+        <div className="orbit-anim h-28 w-28 rounded-full" style={{ background: `conic-gradient(${CONIC_GRADIENT})` }} />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/animations/color-ring.tsx` around lines 2 -
3, The stops array and gradient string are being recalculated on every render;
move stops to a module-level constant (e.g., const STOPS = ['#ffb300', ...]) and
compute gradient once at module scope (e.g., const GRADIENT =
STOPS.map(...).join(', ')) or, if you prefer to keep it near the component, wrap
gradient computation in useMemo inside the ColorRing component so stops/gradient
are not recomputed on each render; update any references from stops/gradient to
the new STOPS/GRADIENT or memoized variable.
apps/docs/src/components/landing/animations/alert-bell.tsx (1)

4-4: ⚡ Quick win

Move static channels array outside component.

The channels array is recreated on every render. Since it never changes, extract it as a module-level constant to avoid unnecessary allocations.

⚡ Proposed fix to optimize array allocation
 import { Bell } from 'lucide-react'

+const ALERT_CHANNELS = ['Webhook', 'Telegram', 'Bark', 'Email', 'APNs']
+
 export function AlertBellAnim() {
-  const channels = ['Webhook', 'Telegram', 'Bark', 'Email', 'APNs']
   return (
     <div
       aria-label="Animated demo of multi-channel alerts"
       className="flex h-full flex-col items-center justify-center gap-3"
       role="img"
     >
       <div className="relative">
         <Bell className="bell-shake h-9 w-9 text-amber-300" />
         <span className="absolute -top-0.5 -right-0.5 h-2.5 w-2.5 rounded-full bg-red-500 ring-2 ring-zinc-950" />
       </div>
       <div className="flex flex-wrap justify-center gap-1.5">
-        {channels.map((c, i) => (
+        {ALERT_CHANNELS.map((c, i) => (
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/animations/alert-bell.tsx` at line 4, The
channels array is being recreated on every render inside the component; extract
const channels = ['Webhook','Telegram','Bark','Email','APNs'] to a module-level
constant (move it outside the AlertBell component) so it is allocated once, and
update any references inside the AlertBell component to use that module-level
identifier.
apps/docs/src/components/landing/animations/monitor-dots.tsx (1)

2-8: ⚡ Quick win

Move static probes array outside component.

The probes array and its objects are recreated on every render. Since this data never changes, extract it as a module-level constant to prevent unnecessary allocations.

⚡ Proposed fix to optimize array allocation
+const MONITOR_PROBES = [
+  { name: 'SSL', meta: 'expires in 73d' },
+  { name: 'DNS', meta: 'A · CNAME' },
+  { name: 'HTTP', meta: '200 · keyword OK' },
+  { name: 'TCP', meta: ':443 · 18 ms' },
+  { name: 'WHOIS', meta: 'renews 2027-04' }
+]
+
 export function MonitorDotsAnim() {
-  const probes = [
-    { name: 'SSL', meta: 'expires in 73d' },
-    { name: 'DNS', meta: 'A · CNAME' },
-    { name: 'HTTP', meta: '200 · keyword OK' },
-    { name: 'TCP', meta: ':443 · 18 ms' },
-    { name: 'WHOIS', meta: 'renews 2027-04' }
-  ]
   return (
     <div
       aria-label="Animated demo of service monitors"
       className="grid h-full grid-cols-1 gap-1.5 font-mono text-xs sm:grid-cols-2"
       role="img"
     >
-      {probes.map((p, i) => (
+      {MONITOR_PROBES.map((p, i) => (
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/animations/monitor-dots.tsx` around lines 2
- 8, The probes array is recreated on every render; extract it as a module-level
constant (e.g., const PROBES = [...]) outside the component in monitor-dots.tsx,
replace the in-component "probes" usage with that constant, and ensure any
references inside the component (map, lookup) now point to PROBES to avoid
repeated allocations.
apps/docs/src/components/landing/sections/hero.tsx (1)

23-23: ⚡ Quick win

Use self-closing JSX syntax with space.

The <br/> tag should follow JSX convention with a space before the closing slash.

♻️ Proposed fix
-            <br />
+            <br />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/sections/hero.tsx` at line 23, Replace the
self-closing line break JSX tag `<br/>` with the space-before-slash form `<br
/>` in the Hero component JSX (locate the `<br/>` occurrence in
apps/docs/src/components/landing/sections/hero.tsx) to follow JSX conventions;
update the single tag instance used in the component render/return so it uses
the spaced self-closing syntax.
apps/docs/src/components/landing/sections/bento.tsx (1)

52-52: 💤 Low value

Consider using a className utility for cleaner concatenation.

The template literal for className concatenation works but could be cleaner with a utility like clsx or a cn() helper function, especially if more conditional classes are added later.

💡 Alternative approach

If you add clsx or have a cn() utility:

className={cn(
  "group flex flex-col gap-4 overflow-hidden rounded-2xl border border-white/10 bg-white/[0.02] p-5",
  "transition hover:border-amber-400/30 hover:bg-white/[0.04]",
  span
)}

Or keep the current approach if this is the only dynamic class.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/sections/bento.tsx` at line 52, The current
JSX uses a template literal to build the className on the element (the long
string including "group flex flex-col ..." concatenated with the span variable);
switch this to a className utility for cleaner concatenation and easier
conditional classes by replacing the template literal with a call to your
project's helper (e.g., cn(...) or clsx(...)) passing the static class strings
and the span variable as separate arguments; update the element in
apps/docs/src/components/landing/sections/bento.tsx that currently sets
className={`... ${span}`} to use cn(...) or clsx(...) so future conditional
classes are simpler to add.
apps/docs/src/components/landing/sections/trust-strip.tsx (1)

21-21: ⚡ Quick win

Provide explicit boolean value for aria-hidden.

While React accepts boolean attributes without values, it's better practice to provide an explicit value for screen reader compatibility.

♻️ Proposed fix
-            <Icon aria-hidden className="h-5 w-5 text-amber-400" />
+            <Icon aria-hidden="true" className="h-5 w-5 text-amber-400" />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/sections/trust-strip.tsx` at line 21, The
Icon usage currently has a bare boolean attribute; update the Icon element to
use an explicit boolean value for accessibility by changing aria-hidden to
aria-hidden={true} (or {false} if the icon conveys meaningful information) on
the Icon component so screen readers handle it correctly.
docs/superpowers/plans/2026-05-15-docs-landing-page.md (2)

588-588: 💤 Low value

Remove redundant identity transform.

The patternTransform="translate(0 0)" is an identity transform that has no effect. It can be safely removed to simplify the code.

♻️ Proposed fix
-          <pattern id="hex" width="40" height="46" patternUnits="userSpaceOnUse" patternTransform="translate(0 0)">
+          <pattern id="hex" width="40" height="46" patternUnits="userSpaceOnUse">
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-05-15-docs-landing-page.md` at line 588, Remove
the redundant identity transform from the SVG pattern by deleting the
patternTransform="translate(0 0)" attribute on the <pattern id="hex" width="40"
height="46" patternUnits="userSpaceOnUse"> element; leaving the rest of the tag
and its attributes unchanged simplifies the markup without altering rendering.

1088-1098: 💤 Low value

Clarify or document the color selection logic.

Line 1094 uses i % 7 === 5 to determine amber vs green dot colors. With 18 total dots, this results in only 2 amber dots (at indices 5 and 12), which may not represent a realistic "packet loss" pattern.

Consider documenting the intended pattern or using a more explicit array/set to define which indices should be amber to make the visualization intent clearer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-05-15-docs-landing-page.md` around lines 1088 -
1098, The current color selection uses the expression i % 7 === 5 inside the
Array.from({ length: 18 }).map to pick amber vs green for the dots, which yields
only indices 5 and 12 as amber and is unclear; replace that modulo heuristic
with an explicit definition (e.g., a constant array or Set like amberIndices =
new Set([/* indices */]) or namedPattern) and use amberIndices.has(i) in the
map, or at minimum add a clear inline comment above the className="h-2
rounded-sm fade-cycle" render explaining the intended visual pattern so the
purpose of the color distribution is explicit and easier to modify.
docs/superpowers/specs/2026-05-15-docs-landing-page-design.md (1)

192-198: ⚡ Quick win

Clarify reduced-motion implementation strategy.

Line 197 states that prefers-reduced-motion: reduce will "pause every keyframe animation" using animation-play-state: paused. This approach can leave animations in an incomplete or visually confusing state (e.g., a typewriter animation paused at width: 0 would be invisible).

Consider specifying that reduced-motion should either:

  1. Set animation: none and apply static end-state styles, or
  2. Use animation-duration: 0.001ms to jump to the final frame immediately

This ensures users with motion sensitivity see complete, legible content rather than mid-animation frozen states.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/specs/2026-05-15-docs-landing-page-design.md` around lines
192 - 198, The reduced-motion note currently says to pause animations via
prefers-reduced-motion: reduce using animation-play-state: paused which can
freeze content mid-animation (e.g., a typewriter keyframe); update the spec to
instead specify one of two implementations: either set animation: none and
provide explicit static end-state styles for components using keyframes
(mentioning typewriter, carousel, and animated demo regions) so content is fully
visible, or set animation-duration: 0.001ms (or equivalent) under
prefers-reduced-motion to jump to the final keyframe instantly; reference the
prefers-reduced-motion rule, animation-play-state, animation: none, and
animation-duration when describing the change so implementers know which CSS
properties to alter.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/docs/src/components/landing/animations/mini-dashboard.tsx`:
- Around line 38-63: The Ring component currently ignores the value prop when
rendering progress; calculate the circle circumference (2 * Math.PI * 34) and
compute an offset = circumference * (1 - value/100) and apply it to the animated
circle (the element with class "ring-anim") via strokeDashoffset (or by setting
a CSS custom property consumed by .ring-anim) instead of leaving a fixed visual
for all values; update the local dash/circumference calculation and set
strokeDasharray/strokeDashoffset on the circle in Ring to reflect the value
prop.

In `@docs/superpowers/plans/2026-05-15-docs-landing-page.md`:
- Around line 194-202: The reduced-motion media query currently forces tiny
durations which causes flicker; update the rule for the .serverbee-landing
selectors inside `@media` (prefers-reduced-motion: reduce) to fully disable
animations and transitions instead of using 0.001ms: set animation: none and
transition: none (remove or stop using animation-duration: 0.001ms and
transition-duration: 0.001ms and you can remove animation-iteration-count) so
all animations and transitions on .serverbee-landing, .serverbee-landing
*::before and .serverbee-landing *::after are effectively disabled for
reduced-motion users.
- Around line 27-61: The fenced code block containing the file structure diagram
in the docs landing page markdown is missing a language specifier; fix it by
changing the opening fence from ``` to ```text (so the block is explicitly
marked as plain text) in the 2026-05-15-docs-landing-page.md file where the
apps/docs/src/ tree is shown.

In `@docs/superpowers/specs/2026-05-15-docs-landing-page-design.md`:
- Around line 98-100: The fenced code block containing the install command lacks
a language specifier; update the block around the line with "curl -fsSL
https://serverbee.app/install.sh | sh" to use a shell/bash language identifier
(e.g., change the opening ``` to ```bash) so Markdown renderers highlight it
correctly.
- Around line 50-60: The fenced ASCII-art grid block lacks a language specifier;
update the opening fence (the triple backticks before the box diagram) to
include a language tag such as text or ascii (e.g., change ``` to ```text) so
Markdown renders it correctly and meets docs standards; ensure the closing fence
remains as three backticks and do not alter the ASCII content inside the block.

---

Nitpick comments:
In `@apps/docs/src/components/landing/animations/alert-bell.tsx`:
- Line 4: The channels array is being recreated on every render inside the
component; extract const channels = ['Webhook','Telegram','Bark','Email','APNs']
to a module-level constant (move it outside the AlertBell component) so it is
allocated once, and update any references inside the AlertBell component to use
that module-level identifier.

In `@apps/docs/src/components/landing/animations/color-ring.tsx`:
- Around line 2-3: The stops array and gradient string are being recalculated on
every render; move stops to a module-level constant (e.g., const STOPS =
['#ffb300', ...]) and compute gradient once at module scope (e.g., const
GRADIENT = STOPS.map(...).join(', ')) or, if you prefer to keep it near the
component, wrap gradient computation in useMemo inside the ColorRing component
so stops/gradient are not recomputed on each render; update any references from
stops/gradient to the new STOPS/GRADIENT or memoized variable.

In `@apps/docs/src/components/landing/animations/data-stream.tsx`:
- Around line 32-40: The Particle component uses a bare aria-hidden attribute
which relies on JSX truthiness; update the JSX in function Particle to set
aria-hidden explicitly (e.g., aria-hidden="true" or aria-hidden={true}) on the
span so accessibility intent is clear and consistent with other components.

In `@apps/docs/src/components/landing/animations/monitor-dots.tsx`:
- Around line 2-8: The probes array is recreated on every render; extract it as
a module-level constant (e.g., const PROBES = [...]) outside the component in
monitor-dots.tsx, replace the in-component "probes" usage with that constant,
and ensure any references inside the component (map, lookup) now point to PROBES
to avoid repeated allocations.

In `@apps/docs/src/components/landing/sections/bento.tsx`:
- Line 52: The current JSX uses a template literal to build the className on the
element (the long string including "group flex flex-col ..." concatenated with
the span variable); switch this to a className utility for cleaner concatenation
and easier conditional classes by replacing the template literal with a call to
your project's helper (e.g., cn(...) or clsx(...)) passing the static class
strings and the span variable as separate arguments; update the element in
apps/docs/src/components/landing/sections/bento.tsx that currently sets
className={`... ${span}`} to use cn(...) or clsx(...) so future conditional
classes are simpler to add.

In `@apps/docs/src/components/landing/sections/hero.tsx`:
- Line 23: Replace the self-closing line break JSX tag `<br/>` with the
space-before-slash form `<br />` in the Hero component JSX (locate the `<br/>`
occurrence in apps/docs/src/components/landing/sections/hero.tsx) to follow JSX
conventions; update the single tag instance used in the component render/return
so it uses the spaced self-closing syntax.

In `@apps/docs/src/components/landing/sections/trust-strip.tsx`:
- Line 21: The Icon usage currently has a bare boolean attribute; update the
Icon element to use an explicit boolean value for accessibility by changing
aria-hidden to aria-hidden={true} (or {false} if the icon conveys meaningful
information) on the Icon component so screen readers handle it correctly.

In `@docs/superpowers/plans/2026-05-15-docs-landing-page.md`:
- Line 588: Remove the redundant identity transform from the SVG pattern by
deleting the patternTransform="translate(0 0)" attribute on the <pattern
id="hex" width="40" height="46" patternUnits="userSpaceOnUse"> element; leaving
the rest of the tag and its attributes unchanged simplifies the markup without
altering rendering.
- Around line 1088-1098: The current color selection uses the expression i % 7
=== 5 inside the Array.from({ length: 18 }).map to pick amber vs green for the
dots, which yields only indices 5 and 12 as amber and is unclear; replace that
modulo heuristic with an explicit definition (e.g., a constant array or Set like
amberIndices = new Set([/* indices */]) or namedPattern) and use
amberIndices.has(i) in the map, or at minimum add a clear inline comment above
the className="h-2 rounded-sm fade-cycle" render explaining the intended visual
pattern so the purpose of the color distribution is explicit and easier to
modify.

In `@docs/superpowers/specs/2026-05-15-docs-landing-page-design.md`:
- Around line 192-198: The reduced-motion note currently says to pause
animations via prefers-reduced-motion: reduce using animation-play-state: paused
which can freeze content mid-animation (e.g., a typewriter keyframe); update the
spec to instead specify one of two implementations: either set animation: none
and provide explicit static end-state styles for components using keyframes
(mentioning typewriter, carousel, and animated demo regions) so content is fully
visible, or set animation-duration: 0.001ms (or equivalent) under
prefers-reduced-motion to jump to the final keyframe instantly; reference the
prefers-reduced-motion rule, animation-play-state, animation: none, and
animation-duration when describing the change so implementers know which CSS
properties to alter.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8418b149-d2ca-42ba-98e4-e9781a2d64f6

📥 Commits

Reviewing files that changed from the base of the PR and between d4d30da and b85e2f9.

📒 Files selected for processing (30)
  • apps/docs/src/components/landing/animations/alert-bell.tsx
  • apps/docs/src/components/landing/animations/color-ring.tsx
  • apps/docs/src/components/landing/animations/data-stream.tsx
  • apps/docs/src/components/landing/animations/docker-stack.tsx
  • apps/docs/src/components/landing/animations/file-tree.tsx
  • apps/docs/src/components/landing/animations/install-binary.tsx
  • apps/docs/src/components/landing/animations/light-band.tsx
  • apps/docs/src/components/landing/animations/mini-dashboard.tsx
  • apps/docs/src/components/landing/animations/monitor-dots.tsx
  • apps/docs/src/components/landing/animations/orbit-icons.tsx
  • apps/docs/src/components/landing/animations/ping-chart.tsx
  • apps/docs/src/components/landing/animations/terminal-demo.tsx
  • apps/docs/src/components/landing/animations/upgrade-loop.tsx
  • apps/docs/src/components/landing/index.tsx
  • apps/docs/src/components/landing/primitives/code-copy.tsx
  • apps/docs/src/components/landing/primitives/gradient-heading.tsx
  • apps/docs/src/components/landing/primitives/hex-background.tsx
  • apps/docs/src/components/landing/primitives/section.tsx
  • apps/docs/src/components/landing/sections/bento.tsx
  • apps/docs/src/components/landing/sections/final-cta.tsx
  • apps/docs/src/components/landing/sections/hero.tsx
  • apps/docs/src/components/landing/sections/how-it-works.tsx
  • apps/docs/src/components/landing/sections/pillars.tsx
  • apps/docs/src/components/landing/sections/trust-strip.tsx
  • apps/docs/src/components/landing/translations.ts
  • apps/docs/src/routes/$lang/index.tsx
  • apps/docs/src/styles/app.css
  • apps/docs/src/styles/landing.css
  • docs/superpowers/plans/2026-05-15-docs-landing-page.md
  • docs/superpowers/specs/2026-05-15-docs-landing-page-design.md

Comment on lines +38 to +63
function Ring({ label, value, color }: { label: string; value: number; color: string }) {
const dash = 220
return (
<div className="flex items-center gap-3 rounded-xl bg-white/[0.03] p-3">
<svg aria-hidden="true" focusable="false" height="60" viewBox="0 0 80 80" width="60">
<circle cx="40" cy="40" fill="none" r="34" stroke="rgba(255,255,255,0.08)" strokeWidth="8" />
<circle
className="ring-anim"
cx="40"
cy="40"
fill="none"
r="34"
stroke={color}
strokeDasharray={dash}
strokeLinecap="round"
strokeWidth="8"
transform="rotate(-90 40 40)"
/>
</svg>
<div>
<div className="font-mono text-xs text-zinc-400">{label}</div>
<div className="font-semibold text-xl text-zinc-100">{value}%</div>
</div>
</div>
)
}
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 | ⚡ Quick win

Ring progress visualization doesn't use the value prop.

The Ring component accepts a value prop (e.g., 42, 61) but doesn't calculate strokeDashoffset to reflect that value. Currently, strokeDasharray is fixed at 220 and no strokeDashoffset is set, meaning both rings will display identically regardless of their different values.

For a proper progress ring, calculate and apply the offset:

const circumference = 2 * Math.PI * 34  // ≈ 213.6
const offset = circumference * (1 - value / 100)

Then add strokeDashoffset={offset} to the animated circle, or apply it via the .ring-anim CSS class using a CSS custom property.

🔧 Proposed fix
 function Ring({ label, value, color }: { label: string; value: number; color: string }) {
-  const dash = 220
+  const radius = 34
+  const circumference = 2 * Math.PI * radius
+  const offset = circumference * (1 - value / 100)
   return (
     <div className="flex items-center gap-3 rounded-xl bg-white/[0.03] p-3">
       <svg aria-hidden="true" focusable="false" height="60" viewBox="0 0 80 80" width="60">
         <circle cx="40" cy="40" fill="none" r="34" stroke="rgba(255,255,255,0.08)" strokeWidth="8" />
         <circle
           className="ring-anim"
           cx="40"
           cy="40"
           fill="none"
-          r="34"
+          r={radius}
           stroke={color}
-          strokeDasharray={dash}
+          strokeDasharray={circumference}
+          strokeDashoffset={offset}
           strokeLinecap="round"
           strokeWidth="8"
           transform="rotate(-90 40 40)"
         />
       </svg>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/src/components/landing/animations/mini-dashboard.tsx` around lines
38 - 63, The Ring component currently ignores the value prop when rendering
progress; calculate the circle circumference (2 * Math.PI * 34) and compute an
offset = circumference * (1 - value/100) and apply it to the animated circle
(the element with class "ring-anim") via strokeDashoffset (or by setting a CSS
custom property consumed by .ring-anim) instead of leaving a fixed visual for
all values; update the local dash/circumference calculation and set
strokeDasharray/strokeDashoffset on the circle in Ring to reflect the value
prop.

Comment on lines +27 to +61
```
apps/docs/src/
routes/$lang/index.tsx # REWRITE (existed)
styles/landing.css # NEW — keyframes, scoped utilities
styles/app.css # MODIFY — import landing.css
components/landing/
index.tsx # NEW — composes all sections
translations.ts # NEW — en/cn strings + install command constant
primitives/
section.tsx # NEW
gradient-heading.tsx # NEW
code-copy.tsx # NEW
hex-background.tsx # NEW
sections/
hero.tsx # NEW
trust-strip.tsx # NEW
pillars.tsx # NEW
bento.tsx # NEW
how-it-works.tsx # NEW
final-cta.tsx # NEW
animations/
mini-dashboard.tsx # NEW
install-binary.tsx # NEW
data-stream.tsx # NEW
orbit-icons.tsx # NEW
ping-chart.tsx # NEW
terminal-demo.tsx # NEW
file-tree.tsx # NEW
docker-stack.tsx # NEW
color-ring.tsx # NEW
alert-bell.tsx # NEW
monitor-dots.tsx # NEW
upgrade-loop.tsx # NEW
light-band.tsx # NEW
```
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 | ⚡ Quick win

Add language specifier to fenced code block.

The file structure diagram should specify a language identifier (use text or leave empty for plain text) to comply with Markdown best practices.

📝 Proposed fix
-```
+```text
 apps/docs/src/
   routes/$lang/index.tsx                  # REWRITE (existed)
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 27-27: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-05-15-docs-landing-page.md` around lines 27 - 61,
The fenced code block containing the file structure diagram in the docs landing
page markdown is missing a language specifier; fix it by changing the opening
fence from ``` to ```text (so the block is explicitly marked as plain text) in
the 2026-05-15-docs-landing-page.md file where the apps/docs/src/ tree is shown.

Comment on lines +194 to +202
@media (prefers-reduced-motion: reduce) {
.serverbee-landing *,
.serverbee-landing *::before,
.serverbee-landing *::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
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 | ⚡ Quick win

Fix reduced-motion implementation to prevent animation flickering.

Lines 198-199 set animation-duration: 0.001ms !important for reduced motion. This can cause flickering as animations rapidly complete. The better approach is to disable animations entirely or set duration to 0s.

Additionally, setting transition-duration: 0.001ms can cause layout shifts. Consider using transition: none instead.

♻️ Proposed fix
   `@media` (prefers-reduced-motion: reduce) {
     .serverbee-landing *,
     .serverbee-landing *::before,
     .serverbee-landing *::after {
-      animation-duration: 0.001ms !important;
+      animation: none !important;
       animation-iteration-count: 1 !important;
-      transition-duration: 0.001ms !important;
+      transition: none !important;
     }
   }
📝 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
@media (prefers-reduced-motion: reduce) {
.serverbee-landing *,
.serverbee-landing *::before,
.serverbee-landing *::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
`@media` (prefers-reduced-motion: reduce) {
.serverbee-landing *,
.serverbee-landing *::before,
.serverbee-landing *::after {
animation: none !important;
animation-iteration-count: 1 !important;
transition: none !important;
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-05-15-docs-landing-page.md` around lines 194 -
202, The reduced-motion media query currently forces tiny durations which causes
flicker; update the rule for the .serverbee-landing selectors inside `@media`
(prefers-reduced-motion: reduce) to fully disable animations and transitions
instead of using 0.001ms: set animation: none and transition: none (remove or
stop using animation-duration: 0.001ms and transition-duration: 0.001ms and you
can remove animation-iteration-count) so all animations and transitions on
.serverbee-landing, .serverbee-landing *::before and .serverbee-landing *::after
are effectively disabled for reduced-motion users.

Comment on lines +50 to +60
```
┌──────────────────────────┬──────────────┬──────────────┐
│ Network quality (2x2) │ Themes 1x1 │ Alerts 1x1 │
│ ├──────────────┼──────────────┤
│ │ Service monitors 1x2 │
├──────────────────────────┼──────────────┴──────────────┤
│ Web Terminal (2x2) │ File Manager 1x2 │
│ ├──────────────┬──────────────┤
│ │ Docker 1x1 │ Auto-upgrade │
└──────────────────────────┴──────────────┴──────────────┘
```
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 | ⚡ Quick win

Add language specifier to fenced code block.

The ASCII art grid visualization should specify a language identifier (use text or ascii) to improve Markdown rendering and comply with documentation standards.

📝 Proposed fix
-```
+```text
 ┌──────────────────────────┬──────────────┬──────────────┐
 │  Network quality (2x2)   │ Themes 1x1   │ Alerts 1x1   │
📝 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
```
┌──────────────────────────┬──────────────┬──────────────┐
│ Network quality (2x2) │ Themes 1x1 │ Alerts 1x1 │
│ ├──────────────┼──────────────┤
│ │ Service monitors 1x2 │
├──────────────────────────┼──────────────┴──────────────┤
│ Web Terminal (2x2) │ File Manager 1x2 │
│ ├──────────────┬──────────────┤
│ │ Docker 1x1 │ Auto-upgrade │
└──────────────────────────┴──────────────┴──────────────┘
```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 50-50: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/specs/2026-05-15-docs-landing-page-design.md` around lines
50 - 60, The fenced ASCII-art grid block lacks a language specifier; update the
opening fence (the triple backticks before the box diagram) to include a
language tag such as text or ascii (e.g., change ``` to ```text) so Markdown
renders it correctly and meets docs standards; ensure the closing fence remains
as three backticks and do not alter the ASCII content inside the block.

Comment on lines +98 to +100
```
curl -fsSL https://serverbee.app/install.sh | sh
```
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 | ⚡ Quick win

Add language specifier to fenced code block.

The install command code block should specify a language identifier (use bash or shell) to improve Markdown rendering.

📝 Proposed fix
-```
+```bash
 curl -fsSL https://serverbee.app/install.sh | sh
 ```
📝 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
```
curl -fsSL https://serverbee.app/install.sh | sh
```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 98-98: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/specs/2026-05-15-docs-landing-page-design.md` around lines
98 - 100, The fenced code block containing the install command lacks a language
specifier; update the block around the line with "curl -fsSL
https://serverbee.app/install.sh | sh" to use a shell/bash language identifier
(e.g., change the opening ``` to ```bash) so Markdown renderers highlight it
correctly.

@ZingerLittleBee ZingerLittleBee merged commit 504bea5 into main May 15, 2026
12 of 17 checks passed
@ZingerLittleBee ZingerLittleBee deleted the toronto branch May 15, 2026 13:39
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.

1 participant