feat: add landing page - #2090
Conversation
|
Warning Rate limit exceeded
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 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR introduces a comprehensive landing page for Nightingale with a multi-section layout (hero, product matrix, quick-start guide, AI assistant), typed data model, five-language localization, complete styling, visual connector components, and integration into the app's router and side menu. ChangesLanding Page with Matrix Architecture
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (2)
src/pages/landing/index.tsx (2)
60-65: ⚡ Quick winHardcoded color values should use theme variables.
The
quickStartIconClassesarray contains hardcoded Tailwind color utilities (bg-violet-500/15 text-violet-500, etc.). Consider extracting these to theme variables or CSS custom properties to ensure consistency with the theme system.As per coding guidelines: "Use Tailwind theme variables or CSS variables instead of hardcoding color values to maintain consistency with the theme system."
♻️ Potential approach
Define semantic color variables in
src/theme/variable.cssfor these states (e.g.,--landing-quickstart-icon-1-bg,--landing-quickstart-icon-1-text) or use existing theme color tokens if available.🤖 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 `@src/pages/landing/index.tsx` around lines 60 - 65, Replace the hardcoded Tailwind color utilities in quickStartIconClasses with semantic theme tokens: define CSS custom properties (e.g., --landing-quickstart-icon-1-bg, --landing-quickstart-icon-1-text, etc.) in your theme/variable.css (or add tokens to tailwind.config) and update quickStartIconClasses entries to use utility classes that reference those variables (e.g., bg-[var(--landing-quickstart-icon-1-bg)] text-[var(--landing-quickstart-icon-1-text)]). Ensure the new variable names map to the original violet/blue/amber/emerald values so the visual output remains the same while using theme variables instead of hardcoded color classes.
54-54: ⚖️ Poor tradeoffConsider migrating from Less to Tailwind.
This file imports
./style.less, but the coding guidelines recommend using Tailwind CSS for styling. While migrating an entire landing page in one PR may be high effort, consider planning incremental migration of the less file to Tailwind utilities in future refactors.As per coding guidelines: "Prefer Tailwind CSS for properties it can directly express (layout, spacing, typography, border-radius, common interaction states); use minimal Less/CSS for what Tailwind cannot accomplish."
🤖 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 `@src/pages/landing/index.tsx` at line 54, The landing page currently imports the legacy stylesheet via the import './style.less' statement; remove that import and incrementally replace Less rules with Tailwind utility classes on the Landing page's JSX elements (start by converting layout, spacing, typography, and common states) while leaving minimal scoped CSS only for patterns Tailwind can't express; update the component's className usage to Tailwind utilities, move any reusable style groups into small component-level className helpers or apply `@apply` in a tiny CSS module if needed, and keep the original Less file until all sections are migrated so you can flip the import out as each part is converted.
🤖 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 `@src/pages/landing/landing.data.test.ts`:
- Around line 59-67: The test's URL regex doesn't match the actual DOCS_V8_BASE
used by the app; update the expectation in the test that iterates over
landingQuickStartCards so the link.url regex matches the real path (e.g., change
/^https:\/\/flashcat\.cloud\/product\/nightingale\// to a regex matching
'https://flashcat.cloud/docs/content/flashcat-monitor/nightingale-v8/'). Locate
the failing assertion in the test that references landingQuickStartCards and
adjust the pattern to align with DOCS_V8_BASE from landing.data.ts.
In `@src/pages/landing/landing.data.ts`:
- Around line 164-166: The second AI quick-start link (object with labelKey
'quickStart.ai.links.1' in landing.data.ts) currently duplicates the first URL
(`${DOCS_V8_BASE}usecase/processor/`); update its url to the correct docs path
(verify the intended target) so it no longer points to the same
`${DOCS_V8_BASE}usecase/processor/` as the first entry, ensuring the
quickStart.ai.links array has distinct, correct URLs.
In `@src/pages/landing/style.less`:
- Line 926: The CSS rule using the keyword currentColor violates the project's
value-keyword-case lint rule; update the declaration in the style for the
affected selector(s) (the rule containing "border-bottom: 8px solid
currentColor;") to use the lowercase keyword "currentcolor" (also update the
other occurrence referenced at the second instance) so stylelint passes.
- Around line 7-67: The file uses many hardcoded color literals in CSS custom
properties (e.g., --landing-primary-rgb, --landing-page-bg,
--landing-shell-main-bg, --landing-shell-duty-bg, --landing-shell-data-bg,
--landing-arrow-bg, --landing-panel-bg, --landing-card-bg,
--landing-card-border, --landing-card-shadow, --landing-card-text,
--landing-card-muted, --landing-glyph-violet-bg, --landing-icon-violet-bg,
--landing-icon-blue-bg, --landing-focus-ring, and their .theme-dark overrides);
move each unique color/rgba/hex/gradient into the shared theme token file
(src/theme/variable.css) as descriptive tokens (for example
--theme-landing-page-bg, --theme-landing-card-border, etc.), export or reuse
existing tokens where appropriate, then replace the hardcoded values in this
file with var(--your-new-token) references (including in the .theme-dark
.landing-page override block) to ensure consistent theming across light/dark and
other referenced lines called out in the review.
- Line 1238: The rule at the max-width: 720px media query incorrectly raises
.landing-hero-title-main to 40px; change the media-query override for
.landing-hero-title-main (the max-width: 720px block) so it reduces the
font-size to a smaller value appropriate for mobile (e.g., below the base 30px)
or remove the override entirely so the base 30px remains; update the style in
the .landing-hero-title-main declaration within the max-width: 720px media query
to the intended smaller size.
---
Nitpick comments:
In `@src/pages/landing/index.tsx`:
- Around line 60-65: Replace the hardcoded Tailwind color utilities in
quickStartIconClasses with semantic theme tokens: define CSS custom properties
(e.g., --landing-quickstart-icon-1-bg, --landing-quickstart-icon-1-text, etc.)
in your theme/variable.css (or add tokens to tailwind.config) and update
quickStartIconClasses entries to use utility classes that reference those
variables (e.g., bg-[var(--landing-quickstart-icon-1-bg)]
text-[var(--landing-quickstart-icon-1-text)]). Ensure the new variable names map
to the original violet/blue/amber/emerald values so the visual output remains
the same while using theme variables instead of hardcoded color classes.
- Line 54: The landing page currently imports the legacy stylesheet via the
import './style.less' statement; remove that import and incrementally replace
Less rules with Tailwind utility classes on the Landing page's JSX elements
(start by converting layout, spacing, typography, and common states) while
leaving minimal scoped CSS only for patterns Tailwind can't express; update the
component's className usage to Tailwind utilities, move any reusable style
groups into small component-level className helpers or apply `@apply` in a tiny
CSS module if needed, and keep the original Less file until all sections are
migrated so you can flip the import out as each part is converted.
🪄 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: f414311f-4af7-4933-9283-594992ab93cd
⛔ Files ignored due to path filters (5)
public/image/landing/hero-dashboard-dark.pngis excluded by!**/*.pngpublic/image/landing/hero-dashboard.pngis excluded by!**/*.pngpublic/image/landing/hero/dark-gradient.svgis excluded by!**/*.svgpublic/image/landing/hero/light-gradient.svgis excluded by!**/*.svgpublic/image/landing/hero/window-dots.svgis excluded by!**/*.svg
📒 Files selected for processing (14)
.gitignoresrc/components/SideMenu/MenuList.tsxsrc/pages/landing/index.tsxsrc/pages/landing/landing.data.test.tssrc/pages/landing/landing.data.tssrc/pages/landing/locale/en_US.tssrc/pages/landing/locale/index.tssrc/pages/landing/locale/ja_JP.tssrc/pages/landing/locale/ru_RU.tssrc/pages/landing/locale/zh_CN.tssrc/pages/landing/locale/zh_HK.tssrc/pages/landing/matrixConnectors.tsxsrc/pages/landing/style.lesssrc/routers/index.tsx
| it('快速上手 4 张卡片,每卡 2 个文档链接,全部指向 flashcat.cloud', () => { | ||
| expect(landingQuickStartCards).toHaveLength(4); | ||
| landingQuickStartCards.forEach((card) => { | ||
| expect(card.links).toHaveLength(2); | ||
| card.links.forEach((link) => { | ||
| expect(link.url).toMatch(/^https:\/\/flashcat\.cloud\/product\/nightingale\//); | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Test regex does not match actual URLs.
The test expects quick-start links to match /^https:\/\/flashcat\.cloud\/product\/nightingale\//, but DOCS_V8_BASE in landing.data.ts is defined as 'https://flashcat.cloud/docs/content/flashcat-monitor/nightingale-v8/'. This test will fail.
🐛 Proposed fix
- expect(link.url).toMatch(/^https:\/\/flashcat\.cloud\/product\/nightingale\//);
+ expect(link.url).toMatch(/^https:\/\/flashcat\.cloud\/(product\/nightingale|docs\/content\/flashcat-monitor\/nightingale-v8)\//);📝 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.
| it('快速上手 4 张卡片,每卡 2 个文档链接,全部指向 flashcat.cloud', () => { | |
| expect(landingQuickStartCards).toHaveLength(4); | |
| landingQuickStartCards.forEach((card) => { | |
| expect(card.links).toHaveLength(2); | |
| card.links.forEach((link) => { | |
| expect(link.url).toMatch(/^https:\/\/flashcat\.cloud\/product\/nightingale\//); | |
| }); | |
| }); | |
| }); | |
| it('快速上手 4 张卡片,每卡 2 个文档链接,全部指向 flashcat.cloud', () => { | |
| expect(landingQuickStartCards).toHaveLength(4); | |
| landingQuickStartCards.forEach((card) => { | |
| expect(card.links).toHaveLength(2); | |
| card.links.forEach((link) => { | |
| expect(link.url).toMatch(/^https:\/\/flashcat\.cloud\/(product\/nightingale|docs\/content\/flashcat-monitor\/nightingale-v8)\//); | |
| }); | |
| }); | |
| }); |
🤖 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 `@src/pages/landing/landing.data.test.ts` around lines 59 - 67, The test's URL
regex doesn't match the actual DOCS_V8_BASE used by the app; update the
expectation in the test that iterates over landingQuickStartCards so the
link.url regex matches the real path (e.g., change
/^https:\/\/flashcat\.cloud\/product\/nightingale\// to a regex matching
'https://flashcat.cloud/docs/content/flashcat-monitor/nightingale-v8/'). Locate
the failing assertion in the test that references landingQuickStartCards and
adjust the pattern to align with DOCS_V8_BASE from landing.data.ts.
| { labelKey: 'quickStart.ai.links.0', url: `${DOCS_V8_BASE}usecase/processor/` }, | ||
| { labelKey: 'quickStart.ai.links.1', url: `${DOCS_V8_BASE}usecase/processor/` }, | ||
| ], |
There was a problem hiding this comment.
Duplicate URL in AI quick-start links.
Both AI quick-start links point to the same URL (${DOCS_V8_BASE}usecase/processor/). This appears to be a copy-paste error. Verify the intended URL for the second link.
🤖 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 `@src/pages/landing/landing.data.ts` around lines 164 - 166, The second AI
quick-start link (object with labelKey 'quickStart.ai.links.1' in
landing.data.ts) currently duplicates the first URL
(`${DOCS_V8_BASE}usecase/processor/`); update its url to the correct docs path
(verify the intended target) so it no longer points to the same
`${DOCS_V8_BASE}usecase/processor/` as the first entry, ensuring the
quickStart.ai.links array has distinct, correct URLs.
| --landing-primary-rgb: 108 83 177; | ||
| --landing-page-bg: #ffffff; | ||
| --landing-shell-main-bg: #f2edfd; | ||
| --landing-shell-duty-bg: #f9effd; | ||
| --landing-shell-data-bg: linear-gradient(180deg, #edf2fd 0, rgba(0, 81, 255, 0.06) 28px); | ||
| --landing-arrow-bg: linear-gradient(180deg, #f2edfd 0%, #edf2fd 100%); | ||
| --landing-arrow-alert-bg: linear-gradient(180deg, #f9effd 0%, #edf2fd 100%); | ||
| --landing-arrow-label: #5f45a1; | ||
| --landing-panel-bg: rgba(255, 255, 255, 0.6); | ||
| --landing-panel-violet-border: rgba(40, 0, 231, 0.2); | ||
| --landing-panel-pink-border: rgba(146, 0, 231, 0.2); | ||
| --landing-panel-blue-border: rgba(0, 64, 233, 0.16); | ||
| --landing-panel-tag-bg: #faf8fe; | ||
| --landing-panel-tag-pink-bg: #fdf9fe; | ||
| --landing-panel-tag-blue-bg: #f8fafe; | ||
| --landing-panel-tag-color: #181c25; | ||
| --landing-card-bg: #ffffff; | ||
| --landing-card-hover-bg: #fafbff; | ||
| --landing-card-border: rgba(104, 38, 217, 0.12); | ||
| --landing-card-shadow: 0 2px 8px rgba(52, 38, 89, 0.1); | ||
| --landing-card-shadow-hover: 0 10px 28px rgba(52, 38, 89, 0.18); | ||
| --landing-card-text: #181c25; | ||
| --landing-card-muted: #657386; | ||
| --landing-glyph-violet-bg: linear-gradient(180deg, #b39cf4 0%, #8f74f0 100%); | ||
| --landing-icon-violet-bg: rgba(104, 38, 217, 0.1); | ||
| --landing-icon-violet-color: #6b51af; | ||
| --landing-icon-blue-bg: rgba(0, 81, 255, 0.06); | ||
| --landing-icon-blue-color: #5f45a1; | ||
| --landing-focus-ring: rgba(104, 38, 217, 0.45); | ||
| } | ||
|
|
||
| .theme-dark .landing-page { | ||
| --landing-primary-rgb: 148 112 255; | ||
| --landing-page-bg: #0d0c12; | ||
| --landing-shell-main-bg: rgba(73, 22, 254, 0.1); | ||
| --landing-shell-duty-bg: rgba(73, 22, 254, 0.1); | ||
| --landing-shell-data-bg: rgba(0, 64, 233, 0.08); | ||
| --landing-arrow-bg: linear-gradient(180deg, rgba(73, 22, 254, 0.18) 0%, rgba(73, 22, 254, 0.08) 100%); | ||
| --landing-arrow-alert-bg: linear-gradient(180deg, rgba(73, 22, 254, 0.18) 0%, rgba(0, 64, 233, 0.08) 100%); | ||
| --landing-arrow-label: #b8a4ff; | ||
| --landing-panel-bg: #0d0c12; | ||
| --landing-panel-violet-border: rgba(131, 89, 255, 0.45); | ||
| --landing-panel-pink-border: rgba(131, 89, 255, 0.45); | ||
| --landing-panel-blue-border: rgba(47, 125, 220, 0.42); | ||
| --landing-panel-tag-bg: #0d0c12; | ||
| --landing-panel-tag-pink-bg: #0d0c12; | ||
| --landing-panel-tag-blue-bg: #0d0c12; | ||
| --landing-panel-tag-color: var(--fc-text-2); | ||
| --landing-card-bg: #161618; | ||
| --landing-card-hover-bg: #1b1b1f; | ||
| --landing-card-border: rgba(148, 112, 255, 0.18); | ||
| --landing-card-shadow: none; | ||
| --landing-card-shadow-hover: 0 0 0 1px rgba(148, 112, 255, 0.32); | ||
| --landing-card-text: var(--fc-text-2); | ||
| --landing-card-muted: #878792; | ||
| --landing-glyph-violet-bg: linear-gradient(180deg, rgba(127, 91, 225, 0.8) 0%, rgba(85, 95, 236, 0.8) 100%); | ||
| --landing-icon-violet-bg: rgba(148, 112, 255, 0.14); | ||
| --landing-icon-violet-color: #b8a4ff; | ||
| --landing-icon-blue-bg: rgba(76, 136, 255, 0.1); | ||
| --landing-icon-blue-color: #878792; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift
Consolidate hardcoded color literals into shared theme tokens.
This stylesheet defines many raw hex/rgba colors directly, which will make dark/light consistency and future theme updates harder to maintain. Move these into src/theme/variable.css (or existing shared tokens) and reference variables here.
As per coding guidelines "Use theme variables from src/theme/variable.css and existing theme system for color and theme-related values; avoid magic color values."
Also applies to: 133-134, 157-162, 173-185, 191-193, 214-218, 250-257, 263-269, 299-301, 316-327, 511-516, 695-695, 700-700, 707-707, 995-1003, 1009-1009, 1115-1120, 1133-1133, 1174-1175, 1194-1194
🤖 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 `@src/pages/landing/style.less` around lines 7 - 67, The file uses many
hardcoded color literals in CSS custom properties (e.g., --landing-primary-rgb,
--landing-page-bg, --landing-shell-main-bg, --landing-shell-duty-bg,
--landing-shell-data-bg, --landing-arrow-bg, --landing-panel-bg,
--landing-card-bg, --landing-card-border, --landing-card-shadow,
--landing-card-text, --landing-card-muted, --landing-glyph-violet-bg,
--landing-icon-violet-bg, --landing-icon-blue-bg, --landing-focus-ring, and
their .theme-dark overrides); move each unique color/rgba/hex/gradient into the
shared theme token file (src/theme/variable.css) as descriptive tokens (for
example --theme-landing-page-bg, --theme-landing-card-border, etc.), export or
reuse existing tokens where appropriate, then replace the hardcoded values in
this file with var(--your-new-token) references (including in the .theme-dark
.landing-page override block) to ensure consistent theming across light/dark and
other referenced lines called out in the review.
| height: 0; | ||
| border-left: 6px solid transparent; | ||
| border-right: 6px solid transparent; | ||
| border-bottom: 8px solid currentColor; |
There was a problem hiding this comment.
Fix currentColor casing to satisfy stylelint.
Use currentcolor to match the configured value-keyword-case rule and avoid lint failure.
Suggested fix
- border-bottom: 8px solid currentColor;
+ border-bottom: 8px solid currentcolor;
...
- border-left: 8px solid currentColor;
+ border-left: 8px solid currentcolor;Also applies to: 932-932
🧰 Tools
🪛 Stylelint (17.11.0)
[error] 926-926: Expected "currentColor" to be "currentcolor" (value-keyword-case)
(value-keyword-case)
🤖 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 `@src/pages/landing/style.less` at line 926, The CSS rule using the keyword
currentColor violates the project's value-keyword-case lint rule; update the
declaration in the style for the affected selector(s) (the rule containing
"border-bottom: 8px solid currentColor;") to use the lowercase keyword
"currentcolor" (also update the other occurrence referenced at the second
instance) so stylelint passes.
| } | ||
|
|
||
| @media (max-width: 720px) { | ||
| .landing-hero-title-main { font-size: 40px; } |
There was a problem hiding this comment.
Mobile breakpoint increases hero title size instead of reducing it.
At max-width: 720px, .landing-hero-title-main jumps to 40px from the base 30px, which is likely the opposite of intended responsive behavior and can overflow on small screens.
Suggested fix
`@media` (max-width: 720px) {
- .landing-hero-title-main { font-size: 40px; }
+ .landing-hero-title-main { font-size: 24px; }
.landing-card-grid > .landing-feature-card { flex-basis: calc(50% - 6px); }
.landing-infrastructure-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.landing-chip-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}📝 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.
| .landing-hero-title-main { font-size: 40px; } | |
| `@media` (max-width: 720px) { | |
| .landing-hero-title-main { font-size: 24px; } | |
| .landing-card-grid > .landing-feature-card { flex-basis: calc(50% - 6px); } | |
| .landing-infrastructure-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } | |
| .landing-chip-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } | |
| } |
🤖 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 `@src/pages/landing/style.less` at line 1238, The rule at the max-width: 720px
media query incorrectly raises .landing-hero-title-main to 40px; change the
media-query override for .landing-hero-title-main (the max-width: 720px block)
so it reduces the font-size to a smaller value appropriate for mobile (e.g.,
below the base 30px) or remove the override entirely so the base 30px remains;
update the style in the .landing-hero-title-main declaration within the
max-width: 720px media query to the intended smaller size.
Summary by CodeRabbit