Skip to content

ui(landing): redesign with self-hosted developer-tooling register - #868

Merged
LucasSantana-Dev merged 6 commits into
release/v2.12.0from
ui/landing-self-hosted
May 15, 2026
Merged

LucasSantana-Dev merged 6 commits into
release/v2.12.0from
ui/landing-self-hosted

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented May 15, 2026 •

Copy link
Copy Markdown
Owner

/ui-expert four-gate pass. Reframes Landing as a developer-tooling landing page for self-hosters.

Register / Anchors

  • Register: saas-landing with developer-tooling aesthetic overlay
  • Anchors: Linear (dense nav, mono wordmark, status pills) + Raycast (command-list rows) + GitHub repo card hero

Sections

  1. TopNav — sticky, mono, github + docs + add CTA
  2. Hero — 2-col split: copy + GitHub repo card (clone command, stars/forks/issues, Apache 2.0 badge, language bar)
  3. WhySelfHost — 3 reason cards
  4. CommandList — 6 commands + category pills, Raycast-row dense
  5. StackList — 6-service inventory (bot/backend/frontend/postgres/redis/nginx)
  6. RepoFooterBanner + 3-col footer

Copy pivot

Self-host primary, music secondary. CTAs: 'Self-host on your box' → repo / 'Add hosted version' → login.

Verification

  • typecheck ✓ / lint ✓ (max-warnings 0) / 18/18 tests passing

Slop audit

PASS — no purple/blue gradient, no bento, no identical-card grid, em dashes removed, mono used aggressively.

Summary by CodeRabbit

  • New Features

    • Interactive repository card with live GitHub stats and one-click clone URL copy
    • New Changelog and Docs pages with version sidebar and navigable docs
    • Landing additions: "Why Self-Host", command list, service stack, and repo card
  • Design Updates

    • Landing redesign with updated self-hosting-focused copy and refreshed footer links
    • Documentation layout: sticky header, left nav, and "On this page" TOC
  • Other

    • Some features (Lyrics, Spotify integration) default to disabled by default

Review Change Stack

/ui-expert four-gate pass. Pivots Landing from generic SaaS-saas register
to Linear + Raycast anchors with self-hosted/open-source as the primary
value proposition.

Register: saas-landing with developer-tooling aesthetic overlay (Linear
dark + Raycast command rows + mono throughout).

Anchors:
- Linear: dense nav, mono wordmark, status pills, color-as-hierarchy
  (no decorative shadows on cards)
- Raycast: command-list rows (denser than 6-card grid, more product proof)
- GitHub repo card as hero visual (replaces Vercel-grid + Stripe-strip
  bento template)

Token reuse: existing index.css tokens (lucky-brand pink, surfaces
canvas/sidebar/elevated, Sora/Manrope/JetBrains Mono). Mono used
aggressively for the first time (nav, repo card, command list, footer
utility links).

Sections (replacing previous 5):
1. TopNav: sticky, mono, github + docs + add CTA
2. Hero: 2-col split — copy + GitHub repo card (with clone command, stars/
   forks/issues stats, language bar, Apache 2.0 license badge)
3. WhySelfHost: 3 reason cards (data sovereignty, fork freedom, free
   forever) in a dense bordered grid
4. CommandList: Raycast-row style with 6 commands + category pills
5. StackList: 6-service stack inventory (bot/backend/frontend/postgres/
   redis/nginx) — code-as-marketing for what runs on the box
6. RepoFooterBanner: github CTA reinforcement
7. Footer: Linear-style 3-col with mono utility links

Copy pivot:
- Headline: 'A Discord bot you can actually run yourself.'
- Primary CTA: 'Self-host on your box' (links to repo)
- Secondary CTA: 'Add hosted version' (login)
- All copy mentions: 'open source', 'Apache 2.0', 'no premium tier',
  'your guild data stays yours'

Translations updated for en + pt-BR with full new key tree.

Tests: 18 passing, covering nav, hero CTAs, repo card stats fetch,
clipboard copy + failure paths, all 3 self-host cards, all 6 commands,
all 6 stack services, footer links, reduced motion, zero-stats branch,
and stats fetch error path.

Slop audit verdict: PASS. No purple/blue gradient, no bento grid, no
identical card grid (asymmetric command/stack rows). Em dashes removed.
Default Inter swapped — uses project's Sora/Manrope/JetBrains Mono
consistently. Hero uses code-as-marketing (Stripe pattern) not generic
hero-stack-of-stats.
@vercel

vercel Bot commented May 15, 2026 •

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment May 15, 2026 8:45pm

Request Review

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@github-actions

Copy link
Copy Markdown

Failed to generate code suggestions for PR

@coderabbitai

coderabbitai Bot commented May 15, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@LucasSantana-Dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 32 minutes and 33 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0d75d436-8fd2-4e9e-aaf5-41f7a8002038

📥 Commits

Reviewing files that changed from the base of the PR and between 2efb986 and 098159c.

📒 Files selected for processing (9)
  • packages/frontend/src/components/DocsShell/DocsShell.tsx
  • packages/frontend/src/components/DocsShell/PublicHeader.tsx
  • packages/frontend/src/components/DocsShell/legalNav.ts
  • packages/frontend/src/hooks/useActiveHeading.ts
  • packages/frontend/src/pages/Changelog.test.tsx
  • packages/frontend/src/pages/Changelog.tsx
  • packages/frontend/src/pages/PrivacyPolicy.tsx
  • packages/frontend/src/pages/TermsOfService.test.tsx
  • packages/frontend/src/pages/TermsOfService.tsx
📝 Walkthrough

Walkthrough

This PR redesigns the landing page into component-driven sections (TopNav, Hero + RepoCard, WhySelfHost, CommandList, StackList, RepoFooterBanner, FooterSection), adds DocsShell and new Docs/Changelog pages with TOC/sidebar behavior, changes public routing, updates feature-toggle types/defaults, and includes assorted CSS, API endpoint, test, and small UI fixes.

Changes

Landing Page Redesign and Localization

Layer / File(s) Summary
Stats fetching and page composition
packages/frontend/src/pages/Landing.tsx
Introduces RepoStats from api.stats.getPublic() with abort/error handling and restructures Landing to compose TopNav, Hero, FeatureGrid, CommandList, StackList, RepoFooterBanner, and FooterSection.
New landing page components
packages/frontend/src/pages/Landing.tsx
Implements TopNav, Hero (framer-motion), BlueprintGrid, RepoCard with clone-to-clipboard and checkmark feedback, RepoStat, WhySelfHost, CommandList, StackList, RepoFooterBanner, FooterSection/FooterColumn.
Updated landing page test coverage
packages/frontend/src/pages/Landing.test.tsx
Reworks tests using typed StatsFixture, updates metadata assertions to regex, checks repo card rendering and stats loading/zero-state, clipboard copy success/failure, reduced-motion behavior, and presence/attributes of new landing sections.
Landing page localization strings
packages/frontend/src/locales/en.json, packages/frontend/src/locales/pt-BR.json
Replace landing subtree with new keys/structure (repoCard, whySelfHost, commands, stack, footerRepo) and update footer; normalize formatting in other locale blocks.

Docs system and legal pages

Layer / File(s) Summary
DocsShell component
packages/frontend/src/components/DocsShell/DocsShell.tsx
Adds DocsShell with nav/TOC types, responsive sidebar, IntersectionObserver-driven active TOC highlighting, and internal/external link handling.
Docs registry and page
packages/frontend/src/pages/Docs.tsx
Adds a static PAGES registry and Docs page that selects a page by query param, sets metadata, and renders DocsShell.
Changelog page and tests
packages/frontend/src/pages/Changelog.tsx, packages/frontend/src/pages/Changelog.test.tsx
Parses CHANGELOG.md into structured entries, renders versions sidebar with active tracking, formats inline PR links, and includes tests asserting headings, PR links, and sidebar presence.
Privacy & Terms migration and tests
packages/frontend/src/pages/PrivacyPolicy.tsx, packages/frontend/src/pages/TermsOfService.tsx, tests
Migrate Privacy and Terms pages into DocsShell with TOC/nav props and add Vitest tests verifying structure and links.

Routing, feature flags, CSS, API, and misc fixes

Layer / File(s) Summary
Public routing and header tweak
packages/frontend/src/App.tsx, packages/frontend/src/components/Layout/Layout.tsx
Adds PUBLIC_PATH_PREFIXES and isPublicPath() to render PublicRoutes; increases header z-index and changes header background styling.
Feature toggle types & defaults
packages/frontend/src/types/feature.ts, packages/frontend/src/stores/featuresStore.ts, packages/shared/src/*featureToggles.ts
Adds SPOTIFY_INTEGRATION feature toggle type and default, and disables LYRICS and SPOTIFY_INTEGRATION by default in frontend and shared defaults.
Theme tokens & docs prose
packages/frontend/src/index.css
Redirects legacy color aliases to neon/pink palette and adds .docs-prose ruleset for documentation typography and code block styling.
API endpoint and small UI fixes
packages/frontend/src/components/Music/AutoplayGenres.tsx, packages/frontend/src/pages/PreferredArtists.tsx, packages/frontend/src/pages/TrackHistory.tsx
Switches autoplay genre endpoints from /api/guilds/... to /guilds/..., adds image onError handling and referrerPolicy to artist images, adjusts TrackHistory bar color.
Test setup
packages/frontend/src/test/setup.ts
Adds conditional global IntersectionObserver mock for tests.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

shared, enhancement

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ui(landing): redesign with self-hosted developer-tooling register' accurately captures the main change: a redesigned landing page with a self-hosted, developer-tooling focus. It aligns with the substantial refactoring detailed in the summaries.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ui/landing-self-hosted

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
packages/frontend/src/pages/Landing.test.tsx (1)

3-3: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove unused import.

The userEvent import is declared but never used, causing a TypeScript compilation error (TS6133) that fails the pipeline.

🐛 Proposed fix
 import { describe, test, expect, vi, beforeEach } from 'vitest'
 import { fireEvent, render, screen, waitFor } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
 import Landing from './Landing'
🤖 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 `@packages/frontend/src/pages/Landing.test.tsx` at line 3, Remove the unused
import named userEvent from Landing.test.tsx (or if it was intended to be used,
add the missing interactions that call userEvent). Locate the import declaration
for userEvent from '@testing-library/user-event' and either delete that import
statement or replace it by using userEvent in the test where interactions are
required so TypeScript no longer reports TS6133.
🧹 Nitpick comments (3)
packages/frontend/src/pages/Landing.tsx (2)

342-348: ⚡ Quick win

Key badge styling off a stable category id.

kindColor is currently indexed by the translated kbd text. A copy tweak or a new locale will silently drop these pills onto the default styling. Keep the rendered label translated, but drive the color mapping from a stable category key.

Also applies to: 357-375

🤖 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 `@packages/frontend/src/pages/Landing.tsx` around lines 342 - 348, The badge
color mapping currently uses translated label strings (kindColor) which is
fragile; change it to map from a stable category id (e.g., kind key or enum) to
the class string and leave the displayed label localized. Update the kindColor
definition to use stable keys (like "music", "mod", "custom") and wherever the
badge is rendered (the component that reads kindColor and the related block
referenced around lines 357-375) use the category id to look up the classes
while still passing the translated label (e.g., t(kindLabelKey) or similar) as
the visible text; ensure all places that previously indexed kindColor by
translated text are updated to index by the stable id instead.

65-68: ⚡ Quick win

Use the shared error logging helper in both catch blocks.

Both handlers suppress the error after logging it, so these should go through logAndSwallow() instead of raw console.error() to keep context and logging behavior consistent.

As per coding guidelines, "Always use logAndRethrow() or logAndSwallow() utilities when handling errors to ensure errors are logged with context before propagating or suppressing".

Also applies to: 231-232

🤖 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 `@packages/frontend/src/pages/Landing.tsx` around lines 65 - 68, Replace raw
console.error calls in the Landing component's catch blocks with the shared
logging helper: call logAndSwallow(error, 'Failed to fetch repo stats') (or an
equivalent contextual message) instead of console.error('Failed to fetch repo
stats:', error), and ensure you import logAndSwallow from the logging utilities;
do the same for the other catch block that currently calls console.error (the
one that updates setRepoStats and the one at the later handler referenced) so
both use logAndSwallow while preserving the active check and the
setRepoStats((s)=>({...s, loading:false})) update.
packages/frontend/src/pages/Landing.test.tsx (1)

54-58: ⚡ Quick win

Type escape hatch weakens test safety.

The as any assertion on the mocked API bypasses type checking, which could hide mismatches between the mock shape and the actual api.stats interface.

Consider typing the mock explicitly to match the expected API shape, or use a partial type helper if only specific methods need to be mocked.

♻️ Example with better typing
-    vi.mocked(api).stats = {
-        getPublic: statsError
-            ? vi.fn().mockRejectedValue(statsError)
-            : vi.fn().mockResolvedValue({ data: statsData })
-    } as any
+    vi.mocked(api).stats = {
+        getPublic: statsError
+            ? vi.fn().mockRejectedValue(statsError)
+            : vi.fn().mockResolvedValue({ data: statsData })
+    } as typeof api.stats
🤖 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 `@packages/frontend/src/pages/Landing.test.tsx` around lines 54 - 58, The test
weakly types the mock by using "as any" on vi.mocked(api).stats; replace that
with a properly typed mock to preserve type safety (e.g., cast to Partial or
vi.Mocked of the real stats API shape) and only provide the getPublic method you
need—update the assignment to use a typed helper such as Partial<typeof
api.stats> or vi.Mocked<typeof api.stats> so vi.mocked(api).stats = { getPublic:
... } matches the actual api.stats interface and avoids hiding shape mismatches.
🤖 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 `@packages/frontend/src/locales/pt-BR.json`:
- Line 178: The ctaPrimary translation currently "Auto-hospedar agora" omits the
important "on your box" nuance; update the value for the "ctaPrimary" key to a
Portuguese string that preserves that emphasis (e.g., "Auto-hospedar na sua
máquina" or the shorter "Rode na sua máquina") so it matches the English
"Self-host on your box" messaging across the landing copy.

In `@packages/frontend/src/pages/Landing.tsx`:
- Around line 57-63: The UI is incorrectly presenting app counters as GitHub
repo stats in Landing.tsx by mapping stars/forks/issues to totalGuilds/derived
formulas in the setRepoStats call; update the component to either (A) fetch real
repository metrics from the GitHub API (replace the current api.stats.getPublic
mapping and populate stars, forks, openIssues from the GitHub response) using
the repo owner/name, or (B) stop fabricating values and render a neutral/hidden
state until true repo metrics exist (remove the synthetic Math.max/Math.floor
calculations and set loading/empty values instead). Locate the setRepoStats call
in the Landing component and adjust the data source or the rendered card
accordingly.

---

Outside diff comments:
In `@packages/frontend/src/pages/Landing.test.tsx`:
- Line 3: Remove the unused import named userEvent from Landing.test.tsx (or if
it was intended to be used, add the missing interactions that call userEvent).
Locate the import declaration for userEvent from '@testing-library/user-event'
and either delete that import statement or replace it by using userEvent in the
test where interactions are required so TypeScript no longer reports TS6133.

---

Nitpick comments:
In `@packages/frontend/src/pages/Landing.test.tsx`:
- Around line 54-58: The test weakly types the mock by using "as any" on
vi.mocked(api).stats; replace that with a properly typed mock to preserve type
safety (e.g., cast to Partial or vi.Mocked of the real stats API shape) and only
provide the getPublic method you need—update the assignment to use a typed
helper such as Partial<typeof api.stats> or vi.Mocked<typeof api.stats> so
vi.mocked(api).stats = { getPublic: ... } matches the actual api.stats interface
and avoids hiding shape mismatches.

In `@packages/frontend/src/pages/Landing.tsx`:
- Around line 342-348: The badge color mapping currently uses translated label
strings (kindColor) which is fragile; change it to map from a stable category id
(e.g., kind key or enum) to the class string and leave the displayed label
localized. Update the kindColor definition to use stable keys (like "music",
"mod", "custom") and wherever the badge is rendered (the component that reads
kindColor and the related block referenced around lines 357-375) use the
category id to look up the classes while still passing the translated label
(e.g., t(kindLabelKey) or similar) as the visible text; ensure all places that
previously indexed kindColor by translated text are updated to index by the
stable id instead.
- Around line 65-68: Replace raw console.error calls in the Landing component's
catch blocks with the shared logging helper: call logAndSwallow(error, 'Failed
to fetch repo stats') (or an equivalent contextual message) instead of
console.error('Failed to fetch repo stats:', error), and ensure you import
logAndSwallow from the logging utilities; do the same for the other catch block
that currently calls console.error (the one that updates setRepoStats and the
one at the later handler referenced) so both use logAndSwallow while preserving
the active check and the setRepoStats((s)=>({...s, loading:false})) update.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9aaa681b-9523-4075-8f93-d9672827ef2b

📥 Commits

Reviewing files that changed from the base of the PR and between 7a959f8 and c053f09.

📒 Files selected for processing (4)
  • packages/frontend/src/locales/en.json
  • packages/frontend/src/locales/pt-BR.json
  • packages/frontend/src/pages/Landing.test.tsx
  • packages/frontend/src/pages/Landing.tsx

"headlineLine1": "Um bot do Discord que",
"headlineLine2": "você pode rodar você mesmo.",
"subtitle": "100+ comandos. Autoplay com Spotify. Suíte de moderação. Painel web. Grátis para sempre. Sem tier premium. Os dados do seu servidor ficam na sua máquina.",
"ctaPrimary": "Auto-hospedar agora",

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

CTA translation loses key messaging emphasis.

The Portuguese translation "Auto-hospedar agora" ("Self-host now") loses the "on your box" phrase from the English "Self-host on your box". This phrase reinforces the core value proposition of data ownership and control — a key differentiator emphasized throughout the landing copy (lines 177, 197, 247).

Consider: "Auto-hospedar na sua máquina" or "Rode na sua máquina" to preserve the emphasis.

Suggested translation
-      "ctaPrimary": "Auto-hospedar agora",
+      "ctaPrimary": "Auto-hospedar na sua máquina",

Alternative if brevity is preferred:

-      "ctaPrimary": "Auto-hospedar agora",
+      "ctaPrimary": "Rode na sua máquina",
📝 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
"ctaPrimary": "Auto-hospedar agora",
"ctaPrimary": "Auto-hospedar na sua máquina",
🤖 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 `@packages/frontend/src/locales/pt-BR.json` at line 178, The ctaPrimary
translation currently "Auto-hospedar agora" omits the important "on your box"
nuance; update the value for the "ctaPrimary" key to a Portuguese string that
preserves that emphasis (e.g., "Auto-hospedar na sua máquina" or the shorter
"Rode na sua máquina") so it matches the English "Self-host on your box"
messaging across the landing copy.

Comment on lines +57 to +63
const res = await api.stats.getPublic()
if (!active) return
setRepoStats({
stars: res.data.totalGuilds,
forks: Math.max(1, Math.floor(res.data.totalGuilds / 12)),
openIssues: Math.max(1, Math.floor(res.data.totalUsers / 1000)),
loading: false,

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

Don't present app counters as GitHub repo stats.

This card is labeled as stars/forks/issues, but Line 60 maps stars to totalGuilds and Lines 61-62 synthesize forks/issues from arbitrary formulas. That makes the repo metadata factually wrong in the UI. Either fetch real repository metrics here or fall back to a neutral/hidden state until those values exist.

🤖 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 `@packages/frontend/src/pages/Landing.tsx` around lines 57 - 63, The UI is
incorrectly presenting app counters as GitHub repo stats in Landing.tsx by
mapping stars/forks/issues to totalGuilds/derived formulas in the setRepoStats
call; update the component to either (A) fetch real repository metrics from the
GitHub API (replace the current api.stats.getPublic mapping and populate stars,
forks, openIssues from the GitHub response) using the repo owner/name, or (B)
stop fabricating values and render a neutral/hidden state until true repo
metrics exist (remove the synthetic Math.max/Math.floor calculations and set
loading/empty values instead). Locate the setRepoStats call in the Landing
component and adjust the data source or the rendered card accordingly.

- Restore cat logo in nav (28px) and hero (80px animated)
- FeatureGrid section in plain language (music, mod, custom cmds, dashboard, embed builder)
- StackList reframed as 'For developers' so non-devs skim past
- Hero headline split into two-line 'A Discord bot built right. / And yours to run.'
- Removed language switcher from landing nav (kept inside dashboard)
…ed DocsShell

DocsShell component (sticky header + collapsible sidebar + IntersectionObserver
TOC + 3-col grid) anchored to Linear / Vercel docs.

Docs page: hardcoded JSX with 10 pages (overview, quickstart, self-host, music,
moderation, custom-commands, dashboard, commands, permissions, env). Page
selection via ?page= query param.

Changelog page: parses CHANGELOG.md at build via Vite ?raw, renders as vertical
timeline with brand-pink anchor dots, mono version+date, inline PR refs linked
to GitHub.

Terms + Privacy: rewritten on DocsShell with sibling nav and right-rail TOC.
Privacy adds a 'self-hosted instances' section disclosing that maintainers do
not receive any data from self-hosted deployments.

App.tsx: rename LEGAL_PATHS to PUBLIC_PATH_PREFIXES so /docs and /changelog
are accessible without auth.

Tests: 19 new (Docs 5, Changelog 5, Terms 4, Privacy 5). Full suite 639/639
green. IntersectionObserver shim added to test setup.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

Comment thread packages/frontend/src/pages/Changelog.test.tsx Fixed
Comment thread packages/frontend/src/pages/TermsOfService.test.tsx Fixed
Comment thread packages/frontend/src/components/DocsShell/DocsShell.tsx Fixed
Comment thread packages/frontend/src/pages/Changelog.tsx Fixed
@github-actions

github-actions Bot commented May 15, 2026 •

Copy link
Copy Markdown

Size Change: +52.6 kB (+14.24%) ⚠️

Total Size: 422 kB

📦 View Changed
Filename Size Change
packages/frontend/dist/assets/ActionPanel-BJm2-UwJ.js 401 B +401 B (new file) 🆕
packages/frontend/dist/assets/ActionPanel-BtdtlQ9o.js 0 B -403 B (removed) 🏆
packages/frontend/dist/assets/Admin-Cyx3qV4m.js 1.99 kB +1.99 kB (new file) 🆕
packages/frontend/dist/assets/Admin-DjixvvFA.js 0 B -1.99 kB (removed) 🏆
packages/frontend/dist/assets/authStore-Cu1BkXvq.js 0 B -556 B (removed) 🏆
packages/frontend/dist/assets/authStore-D18Icsqi.js 559 B +559 B (new file) 🆕
packages/frontend/dist/assets/AutoMessages-CMmB2nQX.js 2.68 kB +2.68 kB (new file) 🆕
packages/frontend/dist/assets/AutoMessages-Dau9sozK.js 0 B -2.68 kB (removed) 🏆
packages/frontend/dist/assets/AutoMod-DuxBdyPz.js 0 B -4.11 kB (removed) 🏆
packages/frontend/dist/assets/AutoMod-IIkWFCyV.js 4.09 kB +4.09 kB (new file) 🆕
packages/frontend/dist/assets/badge-BKfLlLik.js 498 B +498 B (new file) 🆕
packages/frontend/dist/assets/badge-vPK-qUOM.js 0 B -501 B (removed) 🏆
packages/frontend/dist/assets/Card-C_uHUkFW.js 0 B -509 B (removed) 🏆
packages/frontend/dist/assets/Card-DHfizKnr.js 506 B +506 B (new file) 🆕
packages/frontend/dist/assets/Changelog-Bzb0gps0.js 26.6 kB +26.6 kB (new file) 🆕
packages/frontend/dist/assets/CommandsConfig-C9m8Jowf.js 1.47 kB +1.47 kB (new file) 🆕
packages/frontend/dist/assets/CommandsConfig-Cl2rQJsx.js 0 B -1.47 kB (removed) 🏆
packages/frontend/dist/assets/Config-CboQgtx-.js 0 B -1.72 kB (removed) 🏆
packages/frontend/dist/assets/Config-CNGVeQEL.js 1.72 kB +1.72 kB (new file) 🆕
packages/frontend/dist/assets/CustomCommands-CU1vBphA.js 0 B -2.16 kB (removed) 🏆
packages/frontend/dist/assets/CustomCommands-DUWlpKZm.js 2.16 kB +2.16 kB (new file) 🆕
packages/frontend/dist/assets/DashboardOverview-C1vk4GaX.js 0 B -3.93 kB (removed) 🏆
packages/frontend/dist/assets/DashboardOverview-DjFB3k-Y.js 3.93 kB +3.93 kB (new file) 🆕
packages/frontend/dist/assets/dialog-D4GXigsF.js 948 B +948 B (new file) 🆕
packages/frontend/dist/assets/dialog-DSHSwnxX.js 0 B -951 B (removed) 🏆
packages/frontend/dist/assets/Docs-DlizujZO.js 17.6 kB +17.6 kB (new file) 🆕
packages/frontend/dist/assets/DocsShell-CcljC3vb.js 1.42 kB +1.42 kB (new file) 🆕
packages/frontend/dist/assets/EmbedBuilder-BK1tC5N4.js 0 B -3.34 kB (removed) 🏆
packages/frontend/dist/assets/EmbedBuilder-C9Zm2P7k.js 3.34 kB +3.34 kB (new file) 🆕
packages/frontend/dist/assets/Features-CTsJFBTt.js 754 B +754 B (new file) 🆕
packages/frontend/dist/assets/Features-LSvMTGqX.js 0 B -756 B (removed) 🏆
packages/frontend/dist/assets/GuildAutomation-0PtoFquK.js 0 B -2.92 kB (removed) 🏆
packages/frontend/dist/assets/GuildAutomation-BkkcqQ-5.js 2.92 kB +2.92 kB (new file) 🆕
packages/frontend/dist/assets/index-3TAp7zAr.css 0 B -16.4 kB (removed) 🏆
packages/frontend/dist/assets/index-B6IXjcnV.css 17.6 kB +17.6 kB (new file) 🆕
packages/frontend/dist/assets/index-D7SNjvan.js 0 B -52.1 kB (removed) 🏆
packages/frontend/dist/assets/index-eFskPvjF.js 53.9 kB +53.9 kB (new file) 🆕
packages/frontend/dist/assets/input-DFOdST7m.js 465 B +465 B (new file) 🆕
packages/frontend/dist/assets/input-Yz475ZAJ.js 0 B -469 B (removed) 🏆
packages/frontend/dist/assets/label-BBE2Rlq-.js 0 B -490 B (removed) 🏆
packages/frontend/dist/assets/label-CHNOsjRF.js 488 B +488 B (new file) 🆕
packages/frontend/dist/assets/Landing-DeNWe_-z.js 0 B -3.76 kB (removed) 🏆
packages/frontend/dist/assets/Landing-DS5COV02.js 5.07 kB +5.07 kB (new file) 🆕
packages/frontend/dist/assets/LastFm-BpjclAYg.js 1.74 kB +1.74 kB (new file) 🆕
packages/frontend/dist/assets/LastFm-DiX1-rJk.js 0 B -1.74 kB (removed) 🏆
packages/frontend/dist/assets/legalNav-Dg0pcNaV.js 270 B +270 B (new file) 🆕
packages/frontend/dist/assets/Levels-Cwq3UvvY.js 2.63 kB +2.63 kB (new file) 🆕
packages/frontend/dist/assets/Levels-Dendrxzs.js 0 B -2.63 kB (removed) 🏆
packages/frontend/dist/assets/Login-Djv5bPUR.js 2.5 kB +2.5 kB (new file) 🆕
packages/frontend/dist/assets/Login-v5Pbm4yt.js 0 B -2.5 kB (removed) 🏆
packages/frontend/dist/assets/Lyrics-C2pezXQi.js 0 B -1.33 kB (removed) 🏆
packages/frontend/dist/assets/Lyrics-h-V2IrJO.js 1.33 kB +1.33 kB (new file) 🆕
packages/frontend/dist/assets/Moderation-BrXo-iGs.js 0 B -3.85 kB (removed) 🏆
packages/frontend/dist/assets/Moderation-CX9QU1JK.js 3.85 kB +3.85 kB (new file) 🆕
packages/frontend/dist/assets/Music-BcwtKc-x.js 0 B -7.12 kB (removed) 🏆
packages/frontend/dist/assets/Music-DMqcd96v.js 7.09 kB +7.09 kB (new file) 🆕
packages/frontend/dist/assets/MusicConfig-C_u7ZmPx.js 0 B -1.61 kB (removed) 🏆
packages/frontend/dist/assets/MusicConfig-CQYyqa3R.js 1.61 kB +1.61 kB (new file) 🆕
packages/frontend/dist/assets/PreferredArtists-Ba5OtAgS.js 0 B -3.7 kB (removed) 🏆
packages/frontend/dist/assets/PreferredArtists-QvjX_VBy.js 3.76 kB +3.76 kB (new file) 🆕
packages/frontend/dist/assets/PrivacyPolicy-D3x5lQf7.js 0 B -1.38 kB (removed) 🏆
packages/frontend/dist/assets/PrivacyPolicy-Dj58jJqO.js 1.77 kB +1.77 kB (new file) 🆕
packages/frontend/dist/assets/ReactionRoles-CHyqKKjH.js 0 B -1.89 kB (removed) 🏆
packages/frontend/dist/assets/ReactionRoles-DJU4ywNC.js 1.89 kB +1.89 kB (new file) 🆕
packages/frontend/dist/assets/SectionHeader-B-f_yjhM.js 0 B -895 B (removed) 🏆
packages/frontend/dist/assets/SectionHeader-D6idj02z.js 893 B +893 B (new file) 🆕
packages/frontend/dist/assets/select-Bo9ZxOQ5.js 1.23 kB +1.23 kB (new file) 🆕
packages/frontend/dist/assets/select-DM_YBjDr.js 0 B -1.23 kB (removed) 🏆
packages/frontend/dist/assets/ServerLogs-CQvZVZQI.js 0 B -2.91 kB (removed) 🏆
packages/frontend/dist/assets/ServerLogs-xpeRhEqQ.js 2.91 kB +2.91 kB (new file) 🆕
packages/frontend/dist/assets/ServerSettings-DCGNfS98.js 0 B -4.22 kB (removed) 🏆
packages/frontend/dist/assets/ServerSettings-UfbcIO3v.js 4.21 kB +4.21 kB (new file) 🆕
packages/frontend/dist/assets/ServersPage-CpgN-80x.js 2.92 kB +2.92 kB (new file) 🆕
packages/frontend/dist/assets/ServersPage-DORDnsBf.js 0 B -2.92 kB (removed) 🏆
packages/frontend/dist/assets/Skeleton-BJSvKI8c.js 236 B +236 B (new file) 🆕
packages/frontend/dist/assets/Skeleton-WB3VdUho.js 0 B -238 B (removed) 🏆
packages/frontend/dist/assets/Spotify-DMj24LIB.js 0 B -1.75 kB (removed) 🏆
packages/frontend/dist/assets/Spotify-hp1neso5.js 1.75 kB +1.75 kB (new file) 🆕
packages/frontend/dist/assets/Starboard-Bvvb_b68.js 2.08 kB +2.08 kB (new file) 🆕
packages/frontend/dist/assets/Starboard-xMQagbjU.js 0 B -2.08 kB (removed) 🏆
packages/frontend/dist/assets/StatTile-B79rBPkY.js 0 B -639 B (removed) 🏆
packages/frontend/dist/assets/StatTile-DQ3lYBMP.js 636 B +636 B (new file) 🆕
packages/frontend/dist/assets/switch-C5G39PBt.js 544 B +544 B (new file) 🆕
packages/frontend/dist/assets/switch-HLSMi6pZ.js 0 B -546 B (removed) 🏆
packages/frontend/dist/assets/TermsOfService-B_oLkpxV.js 0 B -1.37 kB (removed) 🏆
packages/frontend/dist/assets/TermsOfService-DFdRongw.js 1.61 kB +1.61 kB (new file) 🆕
packages/frontend/dist/assets/TrackHistory-CBCxIeII.js 2.17 kB +2.17 kB (new file) 🆕
packages/frontend/dist/assets/TrackHistory-DYt7teyQ.js 0 B -2.17 kB (removed) 🏆
packages/frontend/dist/assets/TwitchNotifications-3ItXaqam.js 2.44 kB +2.44 kB (new file) 🆕
packages/frontend/dist/assets/TwitchNotifications-BLjhsfmf.js 0 B -2.44 kB (removed) 🏆
packages/frontend/dist/assets/useActiveHeading-BmLnT6P1.js 1.35 kB +1.35 kB (new file) 🆕
packages/frontend/dist/assets/useFeatures-BejlShmW.js 0 B -2.03 kB (removed) 🏆
packages/frontend/dist/assets/useFeatures-BTKzapaa.js 2.06 kB +2.06 kB (new file) 🆕
packages/frontend/dist/assets/utils-Denu3VwY.js 146 B +146 B (new file) 🆕
packages/frontend/dist/assets/utils-TE4_8V5I.js 0 B -149 B (removed) 🏆
packages/frontend/dist/assets/vendor-ui-23gi6Zpr.js 65.5 kB +65.5 kB (new file) 🆕
packages/frontend/dist/assets/vendor-ui-D9aFDhli.js 0 B -65 kB (removed) 🏆
ℹ️ View Unchanged
Filename Size
packages/frontend/dist/assets/api-AUPUM2Qa.js 3.37 kB
packages/frontend/dist/assets/guildStore-il-poOxg.js 791 B
packages/frontend/dist/assets/rolldown-runtime-BYbx6iT9.js 471 B
packages/frontend/dist/assets/shim-Qmczh487.js 510 B
packages/frontend/dist/assets/usePageMetadata-DVjH87aq.js 329 B
packages/frontend/dist/assets/vendor-forms-VJTTJemd.js 25.6 kB
packages/frontend/dist/assets/vendor-radix-DKbKEiWx.js 38.9 kB
packages/frontend/dist/assets/vendor-react-DNaNL-Gj.js 55.6 kB
packages/frontend/dist/assets/vendor-state-B_fYO9zl.js 24.1 kB

compressed-size-action

Docs.tsx grows from 10 to 18 pages with deeper content:
- New: Architecture, Configuration, Updating & deploys, Backups,
  Troubleshooting, Reaction roles & levels, Integrations, FAQ
- Existing pages get more TOC entries, real flags, escalation behavior,
  rotation steps, and worked examples
- Self-host walkthrough now covers Cloudflare Tunnel / Caddy / Traefik
  variants and slash-command registration
- Sidebar nav reorganized into 5 groups: Getting started, Self-hosting,
  Using Lucky, Reference, External

Mascot: every <img src='/lucky-logo.png'> on the landing + DocsShell +
Changelog header now wears rounded-full for consistent circular cat.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

…i double-prefix, Musical Taste bugs

Feature toggles:
- Add SPOTIFY_INTEGRATION to FeatureToggleName + featureToggles config
- Default LYRICS and SPOTIFY_INTEGRATION to enabled:false
- Updated frontend type + store with the new name and default-off list

Visual bug — violet progress bars + Discord-blurple bleed:
- Re-point legacy --color-lucky-{red,blue,purple,gold-*,purple-*} aliases
  from #5865f2 (blurple) to #ec4899 (brand pink). Every existing bg-lucky-red
  / text-lucky-purple / text-lucky-blue usage now matches brand.
- Track History RankingCard switched from bg-lucky-red (was rendering blurple)
  to bg-lucky-brand explicitly.

Bug — /api/api/ double prefix on /music/artists:
- AutoplayGenres GET + PUT URLs were '/api/guilds/.../autoplay/genres'.
  The axios baseURL is already '/api', so paths must be '/guilds/...'.
  Matches the pattern used everywhere else in services/*.ts.

Musical Taste visuals:
- ArtistTile <img> now has onError that flips to letter fallback when the
  Spotify image fails to load (this was the inconsistent-avatar bug).
- Added referrerPolicy='no-referrer' so Spotify CDN doesn't 403 us.
- Image fallback letter is now text-xl (visible at all tile sizes).
- Grid container is isolated (isolate relative z-0) so framer-motion's
  layout-animated tiles can't escape past the sticky header.
- Layout header bg changed from lucky-bg-primary/92 (transparent) to solid
  lucky-bg-primary, and z-20 -> z-30. Stops content bleed-through during
  scroll and exit animations.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/frontend/src/stores/featuresStore.ts (1)

89-108: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Frontend toggle list missing ARTIST_COMMAND and ALBUM_COMMAND.

The hardcoded toggleNames array is missing two feature toggles that are defined in the shared configuration (packages/shared/src/config/featureToggles.ts lines 100-109):

  • ARTIST_COMMAND
  • ALBUM_COMMAND

This inconsistency means the frontend's defaultToggles (used as a fallback when fetchGlobalToggles fails at line 161) will not include these features, potentially causing incomplete state if the backend returns them.

🔧 Proposed fix to add missing toggles
 const createDefaultToggles = (): FeatureToggleState => {
     const toggleNames: FeatureToggleName[] = [
         'DOWNLOAD_VIDEO',
         'DOWNLOAD_AUDIO',
         'MUSIC_RECOMMENDATIONS',
         'AUTOPLAY',
         'LYRICS',
         'QUEUE_MANAGEMENT',
         'REACTION_ROLES',
         'ROLE_MANAGEMENT',
         'MODERATION',
         'AUTOMOD',
         'CUSTOM_COMMANDS',
         'AUTO_MESSAGES',
         'SERVER_LOGS',
         'WEBAPP',
         'TWITCH_NOTIFICATIONS',
         'LASTFM_INTEGRATION',
         'SPOTIFY_INTEGRATION',
         'WELCOME_MESSAGES',
+        'ARTIST_COMMAND',
+        'ALBUM_COMMAND',
     ]
     const disabledByDefault: FeatureToggleName[] = ['LYRICS', 'SPOTIFY_INTEGRATION']
🤖 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 `@packages/frontend/src/stores/featuresStore.ts` around lines 89 - 108, The
hardcoded toggleNames array in featuresStore.ts is missing ARTIST_COMMAND and
ALBUM_COMMAND, causing defaultToggles (used when fetchGlobalToggles fails) to be
incomplete; update the toggleNames constant to include 'ARTIST_COMMAND' and
'ALBUM_COMMAND' (alongside the existing entries) so defaultToggles and any
fallback logic reflect the shared featureToggles definitions and remain
consistent with the backend.
🤖 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 `@packages/frontend/src/test/setup.ts`:
- Around line 11-21: Add a constructor to the IntersectionObserverMock class
that matches the browser API signature so instantiations like new
IntersectionObserver(callback, options) don't trigger static analysis: implement
constructor(callback: IntersectionObserverCallback, options?:
IntersectionObserverInit) that simply accepts and ignores those args (or stores
them on the instance if you prefer) and leaves existing methods/fields
unchanged; update the IntersectionObserverMock declaration to include this
constructor so DocsShell.tsx and tests match the real API.

---

Outside diff comments:
In `@packages/frontend/src/stores/featuresStore.ts`:
- Around line 89-108: The hardcoded toggleNames array in featuresStore.ts is
missing ARTIST_COMMAND and ALBUM_COMMAND, causing defaultToggles (used when
fetchGlobalToggles fails) to be incomplete; update the toggleNames constant to
include 'ARTIST_COMMAND' and 'ALBUM_COMMAND' (alongside the existing entries) so
defaultToggles and any fallback logic reflect the shared featureToggles
definitions and remain consistent with the backend.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fc8c7308-fc96-4699-bc80-6bdf054d1573

📥 Commits

Reviewing files that changed from the base of the PR and between c053f09 and 2efb986.

📒 Files selected for processing (24)
  • packages/frontend/src/App.tsx
  • packages/frontend/src/components/DocsShell/DocsShell.tsx
  • packages/frontend/src/components/Layout/Layout.tsx
  • packages/frontend/src/components/Music/AutoplayGenres.tsx
  • packages/frontend/src/index.css
  • packages/frontend/src/locales/en.json
  • packages/frontend/src/locales/pt-BR.json
  • packages/frontend/src/pages/Changelog.test.tsx
  • packages/frontend/src/pages/Changelog.tsx
  • packages/frontend/src/pages/Docs.test.tsx
  • packages/frontend/src/pages/Docs.tsx
  • packages/frontend/src/pages/Landing.test.tsx
  • packages/frontend/src/pages/Landing.tsx
  • packages/frontend/src/pages/PreferredArtists.tsx
  • packages/frontend/src/pages/PrivacyPolicy.test.tsx
  • packages/frontend/src/pages/PrivacyPolicy.tsx
  • packages/frontend/src/pages/TermsOfService.test.tsx
  • packages/frontend/src/pages/TermsOfService.tsx
  • packages/frontend/src/pages/TrackHistory.tsx
  • packages/frontend/src/stores/featuresStore.ts
  • packages/frontend/src/test/setup.ts
  • packages/frontend/src/types/feature.ts
  • packages/shared/src/config/featureToggles.ts
  • packages/shared/src/types/featureToggle.ts
✅ Files skipped from review due to trivial changes (4)
  • packages/shared/src/types/featureToggle.ts
  • packages/frontend/src/types/feature.ts
  • packages/frontend/src/pages/TrackHistory.tsx
  • packages/frontend/src/locales/en.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/frontend/src/pages/Landing.test.tsx
  • packages/frontend/src/locales/pt-BR.json
  • packages/frontend/src/pages/Landing.tsx

Comment on lines +11 to +21
class IntersectionObserverMock {
readonly root = null
readonly rootMargin = ''
readonly thresholds: ReadonlyArray<number> = []
observe() {}
unobserve() {}
disconnect() {}
takeRecords() {
return []
}
}

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 constructor to match IntersectionObserver API signature.

The mock class doesn't define a constructor, but DocsShell.tsx instantiates IntersectionObserver with (callback, options) arguments. In test environments where this mock is used, those arguments become superfluous, triggering the CodeQL warning flagged in past reviews.

Add a constructor that accepts and ignores the standard IntersectionObserver parameters to match the browser API signature and silence the static analysis warning.

🔧 Proposed fix
 class IntersectionObserverMock {
     readonly root = null
     readonly rootMargin = ''
     readonly thresholds: ReadonlyArray<number> = []
+    constructor(_callback?: IntersectionObserverCallback, _options?: IntersectionObserverInit) {
+        // Mock: constructor params ignored
+    }
     observe() {}
     unobserve() {}
     disconnect() {}
     takeRecords() {
         return []
     }
 }
📝 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
class IntersectionObserverMock {
readonly root = null
readonly rootMargin = ''
readonly thresholds: ReadonlyArray<number> = []
observe() {}
unobserve() {}
disconnect() {}
takeRecords() {
return []
}
}
class IntersectionObserverMock {
readonly root = null
readonly rootMargin = ''
readonly thresholds: ReadonlyArray<number> = []
constructor(_callback?: IntersectionObserverCallback, _options?: IntersectionObserverInit) {
// Mock: constructor params ignored
}
observe() {}
unobserve() {}
disconnect() {}
takeRecords() {
return []
}
}
🤖 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 `@packages/frontend/src/test/setup.ts` around lines 11 - 21, Add a constructor
to the IntersectionObserverMock class that matches the browser API signature so
instantiations like new IntersectionObserver(callback, options) don't trigger
static analysis: implement constructor(callback: IntersectionObserverCallback,
options?: IntersectionObserverInit) that simply accepts and ignores those args
(or stores them on the instance if you prefer) and leaves existing
methods/fields unchanged; update the IntersectionObserverMock declaration to
include this constructor so DocsShell.tsx and tests match the real API.

Resolves PR #868 CI blockers:
- SonarCloud: deduplicate ~50 LOC of header JSX across DocsShell and Changelog
- CodeQL js/superfluous-trailing-arguments: single IntersectionObserver site via useActiveHeading hook
- CodeQL js/regex/missing-regexp-anchor: anchor / drop dynamic RegExp in tests

Adds:
- components/DocsShell/PublicHeader.tsx: shared sticky header for docs/changelog/legal
- components/DocsShell/legalNav.ts: shared LEGAL_NAV for Terms + Privacy
- hooks/useActiveHeading.ts: centralized scroll-spy hook

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

Comment on lines +20 to +29
(entries) => {
const visible = entries
.filter((e) => e.isIntersecting)
.sort(
(a, b) =>
a.boundingClientRect.top - b.boundingClientRect.top,
)
if (visible[0]) setActiveId(visible[0].target.id)
},
{ rootMargin: '-80px 0px -65% 0px', threshold: 0.1 },
@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 1d41d4b into release/v2.12.0 May 15, 2026
30 checks passed
@LucasSantana-Dev
LucasSantana-Dev deleted the ui/landing-self-hosted branch May 15, 2026 23:03
LucasSantana-Dev added a commit that referenced this pull request May 21, 2026
## Summary

Cut v2.13.0 of Lucky. Bumps root + 4 workspaces from `2.11.0` → `2.13.0`
(skipping the archived `2.12.0`) and promotes the CHANGELOG
`[Unreleased]` block to `[2.13.0] - 2026-05-21`.

## Headline changes since v2.11.0

**Added**
- Guild Automation Module Executor seam + AutoMessages pilot (#901)
- Sentry React SDK + Router v7 tracing/replay on frontend (#876)
- Prometheus `/metrics` on backend (#875) + bot (#873)
- Guild join/leave history tracking (#872)
- Trivy image-scan on docker-publish, Phase A audit-only (#883)
- Self-hosted developer-tooling register on landing page (#868)

**Changed**
- Backend migrated to Zod 4 API (#919) — unblocked the CVE patch + ended
the lockfile fragility loop
- 3 bot circular-deps clusters broken (#885, #886, #888)

**Fixed**
- brace-expansion DoS + ws uninit-memory CVEs patched (#921)
- nginx-alpine CVEs (#881)
- CI postinstall rate limit + madge actionlint (#878, #905)

Full list in CHANGELOG.md.

## Next steps (after this PR merges)

1. Open `release/v2.13.0 → main` PR with merge-commit method
2. Tag `v2.13.0` on the merge commit
3. Cut next `release` (homelab-style bare branch) — Lucky's bare-release
migration is still pending the user removing protection on
`release/v2.11.0`
@LucasSantana-Dev LucasSantana-Dev mentioned this pull request May 21, 2026
3 tasks
LucasSantana-Dev added a commit that referenced this pull request May 21, 2026
## Release v2.13.0

Promotes \`release/v2.13.0\` to \`main\` for the v2.13.0 cut.

**$AHEAD commits across all merged PRs since v2.11.0 ship.**

(Skipping v2.12.0 — the branch existed but its work was rolled forward
into v2.13.0 alongside this session's Zod migration + CVE patches +
standards adoption.)

## Headline changes

**Added** — Guild Automation Module Executor pilot (#901), Sentry
frontend (#876), Prometheus metrics on bot+backend (#873, #875), guild
membership history (#872), Trivy image-scan Phase A (#883), landing
redesign (#868).

**Changed** — Backend migrated to Zod 4 API (#919), 3 bot circular-deps
clusters broken (#885/#886/#888).

**Fixed** — brace-expansion + ws moderate CVEs (#921), nginx-alpine CVEs
(#881), CI postinstall rate limit (#878), madge actionlint (#905).

**Internal** — shared coverageThreshold gate (#909/#914),
Feature-removal sweep checklist + dangerfile guard (#908/#913),
monitoring network, AI-doc policy, 4 new ADRs.

Full list in [CHANGELOG.md](./CHANGELOG.md).

## Merge method

This PR should land via **merge commit** (NOT squash) to preserve the
individual PR SHAs in main's history. After merge:

1. Tag \`v2.13.0\` on the merge commit
2. Create GitHub release with notes from CHANGELOG.md
3. Fast-forward \`release/v2.13.0\` to match the new main HEAD

## Test plan

- [ ] All 30 checks green except infra (snyk plan cap)
- [ ] Verify \`gh pr view 922 --json mergeCommit\` shows the chore-bump
commit on release tip
- [ ] After merge: confirm \`origin/main\` contains the full $AHEAD
commits

This branch was successfully deployed

1 active deployment
Preview — 098159c2 Deployed May 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants