Skip to content

feat: redesign homepage information flow#5234

Open
hriszc wants to merge 9 commits intoasyncapi:masterfrom
hriszc:codex/homepage-redesign
Open

feat: redesign homepage information flow#5234
hriszc wants to merge 9 commits intoasyncapi:masterfrom
hriszc:codex/homepage-redesign

Conversation

@hriszc
Copy link
Copy Markdown

@hriszc hriszc commented Mar 10, 2026

Fixes #3192

This redesign keeps the existing homepage content model intact but changes the information flow and visual hierarchy:

  • rebuild the hero into a stronger two-column entry point with clearer CTA priority
  • convert feature, adopter, community, sponsor, and testimonial areas into more distinct responsive sections
  • reduce visual clutter by grouping related content into clearer cards and surfaces
  • preserve existing translations and components so the review stays focused on homepage UX and responsiveness

Validation: npm run lint (passes with only pre-existing repository warnings).

Summary by CodeRabbit

  • New Features

    • Persistent two-column hero with a right-side spec panel, three feature cards, and embedded demo animation
    • Prominent rounded search control in the hero and a new Features section below the hero
  • Style

    • Full visual redesign: dark radial gradients, decorative dividers, frosted/right-panel treatment, rounded cards, refined typography, spacing, and responsive grids
    • Multiple site sections converted to card-based, bordered blocks for improved visual hierarchy
  • Documentation

    • Expanded localized UI strings for hero badge, spec signal text, feature card content, slogan and links

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 10, 2026

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 2eb10b9
🔍 Latest deploy log https://app.netlify.com/projects/asyncapi-website/deploys/69bb3bd5deef0c00080a038f
😎 Deploy Preview https://deploy-preview-5234--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

Replaces the simple homepage hero with a responsive two-column hero and persistent right-side spec panel, moves DemoAnimation into that panel, restyles the Features component, and converts multiple homepage sections into card-based, rounded, bordered layouts; adds new localized strings for hero badges, spec signals, and feature cards.

Changes

Cohort / File(s) Summary
Hero Component Redesign
components/Hero.tsx
Full rewrite of the hero: dark themed two-column layout, radial gradients, badge/headline/paragraph typography changes, rounded Algolia search button, left content layout updates, right spec panel with three feature cards and DemoAnimation moved into panel.
Features Section Styling
components/features/index.tsx
Restyled features container to a rounded, blurred card with adjusted spacing, added feature identifier badges, padded feature cards with hover translate/border/shadow, updated typography and link row layout.
Homepage Layout Redesign
pages/[lang]/index.tsx
Applied full-page gradient background and increased top padding; converted Adopters, Newsletter, Community, Sponsors, Testimonials into rounded, bordered card sections with responsive grids, new CTAs and reorganized content blocks.
Locale Additions
public/locales/en/landing-page.json, public/locales/de/landing-page.json, public/locales/zh_cn/landing-page.json
Expanded main locale structure: added heroBadge, specSignalTitle, specSignalSubtitle, cards (standardize/generate/align with label/title/description), and slogan_text/slogan_link; reorganized main block.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A hop, a patch, with pixels bright,

Badges bloom and gradients light,
Two columns hum, the demo twirls,
Cards align like tiny pearls,
I nibble code and cheer the sight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: redesign homepage information flow' directly and clearly summarizes the main objective of this pull request—redesigning the homepage's information architecture and content organization.
Linked Issues check ✅ Passed The PR successfully addresses all coding-related requirements from issue #3192: responsive layout (Hero, Features, pages/[lang]/index.tsx demonstrate responsive grids), enhanced visual elements (styled cards, gradient backgrounds, improved typography), and reduced clutter (card-based organization of features, adopters, sponsors, testimonials).
Out of Scope Changes check ✅ Passed All changes align with the linked issue scope: Hero redesign, Features styling, landing page layout restructuring, and localization updates for new UI elements are all within the homepage redesign objectives. No unrelated changes detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@hriszc hriszc mentioned this pull request Mar 10, 2026
3 tasks
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (818586e) to head (2eb10b9).
⚠️ Report is 6 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #5234   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines          796       830   +34     
  Branches       146       159   +13     
=========================================
+ Hits           796       830   +34     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@asyncapi-bot
Copy link
Copy Markdown
Contributor

asyncapi-bot commented Mar 10, 2026

⚡️ Lighthouse report for the changes in this PR:

Category Score
🔴 Performance 37
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-5234--asyncapi-website.netlify.app/

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
components/features/index.tsx (1)

35-35: Consider using replaceAll() for clarity.

SonarCloud flags this as preferring String#replaceAll() over String#replace() with a global regex. While functionally equivalent, replaceAll() is more semantic for this use case.

Suggested change
-                    {feature.id.replace(/-/g, ' ')}
+                    {feature.id.replaceAll('-', ' ')}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/features/index.tsx` at line 35, The code uses
feature.id.replace(/-/g, ' ') which SonarCloud suggests replacing with the more
semantic String#replaceAll; update the rendering to use
feature.id.replaceAll('-', ' ') in components/features/index.tsx (where
feature.id.replace(...) is used) and ensure your TS/JS target environment
supports replaceAll or include a polyfill/tslib target change if needed.
pages/[lang]/index.tsx (3)

96-147: Nested Container components may be redundant.

There are nested Container wide components inside the parent section Container. Since the parent already applies wide, the inner Containers may only add unnecessary wrapper divs.

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

In `@pages/`[lang]/index.tsx around lines 96 - 147, The code nests multiple
Container wide wrappers (the Container components wrapping the community blocks
and then again around NewsroomSection), which is redundant; remove the extra
Container wrapper by placing NewsroomSection inside the existing outer Container
(or remove the inner Container and render <NewsroomSection /> directly),
ensuring you keep any necessary spacing/styling previously provided by the
removed Container; update the JSX where Container and NewsroomSection are used
so only one Container wide wraps these sections (look for the Container
component and the NewsroomSection symbol) and verify the layout still matches in
the page.

208-235: Testimonial content is hardcoded rather than using translation keys.

The testimonial text is inline rather than using t('...') translation keys. If the homepage needs full localization, these should be moved to translation files. However, testimonial quotes are often intentionally kept in the original language for authenticity.

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

In `@pages/`[lang]/index.tsx around lines 208 - 235, The Testimonial props (text,
authorName, authorDescription) are hardcoded in the JSX; extract these strings
into your i18n translation files and replace the inline literals with
translation lookups (e.g., use t('testimonials.matt.text'),
t('testimonials.matt.authorName'), etc.) when rendering the <Testimonial>
components; update each Testimonial instance (references: the Testimonial
component and its props text, authorName, authorDescription) to use the
translation keys via your t() hook/import, and add corresponding keys to the
locale JSONs; if a specific testimonial must remain in the original language for
authenticity, leave that instance as-is but add a comment explaining why it’s
exempt.

63-79: Consider extracting adopter logos into a data array.

The logo list items have identical structure with only the logo component and height varying. Mapping over a data array would reduce duplication and make future additions easier.

Example refactor
const adopters = [
  { Logo: AdidasLogo, height: 'h-8' },
  { Logo: AxwayLogo, height: 'h-14' },
  { Logo: SlackLogo, height: 'h-10' },
  { Logo: SalesforceLogo, height: 'h-16' },
  { Logo: SapLogo, height: 'h-12' },
];

// Then in JSX:
<ul className='grid items-center gap-10 md:grid-cols-2 md:gap-8 lg:grid-cols-5'>
  {adopters.map(({ Logo, height }, i) => (
    <li key={i} className='flex justify-center rounded-2xl border border-slate-100 bg-slate-50 px-6 py-8'>
      <Logo className={`${height} text-gray-400 hover:text-black`} />
    </li>
  ))}
</ul>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/`[lang]/index.tsx around lines 63 - 79, Extract the repeated <li>
blocks into a data array (e.g., const adopters = [{ Logo: AdidasLogo, height:
'h-8' }, ...]) and replace the hardcoded list with a map over adopters to render
each item; for each entry render the same wrapper <li> (use the existing class
string 'flex justify-center rounded-2xl border border-slate-100 bg-slate-50 px-6
py-8') and render Logo with className combining the height value and shared
classes (e.g., `${height} text-gray-400 hover:text-black`), and include a stable
key for each mapped item (use a name or index) to keep behavior identical while
removing duplication of AdidasLogo, AxwayLogo, SlackLogo, SalesforceLogo, and
SapLogo.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Hero.tsx`:
- Around line 96-120: The Hero.tsx hardcoded texts ("Specification signal",
"Standardize", "Events", etc.) should be replaced with translation keys and the
component should use the same translation helper used elsewhere (e.g., the
useTranslations()/t function) — import the translation hook at the top of
Hero.tsx, replace each literal string in the specification panel and the three
feature cards with t('hero.specification'), t('hero.card.standardize.title'),
t('hero.card.standardize.subtitle'), etc., and add corresponding keys to your
i18n resource files; also decide whether to reuse the canonical source from
FeatureList.ts by mapping FeatureList items into the cards (e.g., reference the
Features component or import the FeatureList array) so content isn’t duplicated,
and update tests/fixtures accordingly.
- Around line 40-42: Hardcoded badge text in components/Hero.tsx bypasses i18n;
replace the literal string inside the badge div with a call to the translation
helper (t) — e.g., t('hero.badge') or a similar namespaced key — and add that
key and its translated value to your translation JSON/TS files for all locales.
Update the JSX in the Hero component where the inline div (the badge) renders
the text and ensure the new translation key exists in the localization files so
the badge is localized.

In `@pages/`[lang]/index.tsx:
- Line 152: The section with className 'pb-20' that currently uses
role='contentinfo' and aria-label='Our Sponsors' is using an incorrect ARIA
role; update that element to either remove the role attribute or change it to
role='region' (e.g., replace role='contentinfo' with role='region' on the
<section className='pb-20' aria-label='Our Sponsors'> element) so the sponsors
area is correctly announced and not treated as site-wide footer content.

---

Nitpick comments:
In `@components/features/index.tsx`:
- Line 35: The code uses feature.id.replace(/-/g, ' ') which SonarCloud suggests
replacing with the more semantic String#replaceAll; update the rendering to use
feature.id.replaceAll('-', ' ') in components/features/index.tsx (where
feature.id.replace(...) is used) and ensure your TS/JS target environment
supports replaceAll or include a polyfill/tslib target change if needed.

In `@pages/`[lang]/index.tsx:
- Around line 96-147: The code nests multiple Container wide wrappers (the
Container components wrapping the community blocks and then again around
NewsroomSection), which is redundant; remove the extra Container wrapper by
placing NewsroomSection inside the existing outer Container (or remove the inner
Container and render <NewsroomSection /> directly), ensuring you keep any
necessary spacing/styling previously provided by the removed Container; update
the JSX where Container and NewsroomSection are used so only one Container wide
wraps these sections (look for the Container component and the NewsroomSection
symbol) and verify the layout still matches in the page.
- Around line 208-235: The Testimonial props (text, authorName,
authorDescription) are hardcoded in the JSX; extract these strings into your
i18n translation files and replace the inline literals with translation lookups
(e.g., use t('testimonials.matt.text'), t('testimonials.matt.authorName'), etc.)
when rendering the <Testimonial> components; update each Testimonial instance
(references: the Testimonial component and its props text, authorName,
authorDescription) to use the translation keys via your t() hook/import, and add
corresponding keys to the locale JSONs; if a specific testimonial must remain in
the original language for authenticity, leave that instance as-is but add a
comment explaining why it’s exempt.
- Around line 63-79: Extract the repeated <li> blocks into a data array (e.g.,
const adopters = [{ Logo: AdidasLogo, height: 'h-8' }, ...]) and replace the
hardcoded list with a map over adopters to render each item; for each entry
render the same wrapper <li> (use the existing class string 'flex justify-center
rounded-2xl border border-slate-100 bg-slate-50 px-6 py-8') and render Logo with
className combining the height value and shared classes (e.g., `${height}
text-gray-400 hover:text-black`), and include a stable key for each mapped item
(use a name or index) to keep behavior identical while removing duplication of
AdidasLogo, AxwayLogo, SlackLogo, SalesforceLogo, and SapLogo.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ba8c9062-ecd4-426e-9e32-ef2ac0e4d140

📥 Commits

Reviewing files that changed from the base of the PR and between 184ad8d and 6430335.

📒 Files selected for processing (3)
  • components/Hero.tsx
  • components/features/index.tsx
  • pages/[lang]/index.tsx

@hriszc
Copy link
Copy Markdown
Author

hriszc commented Mar 17, 2026

Addressed the latest review items on the PR branch. I moved the homepage hero/spec-signal copy into locale strings, updated the card copy to use i18n-backed keys, and switched the sponsors landmark from contentinfo to region. I also re-validated the touched locale JSON files after the change.

@sonarqubecloud
Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pages/[lang]/index.tsx (1)

152-152: Remove redundant role="region" attribute.

The <section> element already has an implicit ARIA role of region. Defining it explicitly is redundant and flagged by static analysis. The aria-label alone provides sufficient context.

Suggested fix
-        <section className='pb-20' role='region' aria-label='Our Sponsors'>
+        <section className='pb-20' aria-label='Our Sponsors'>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/`[lang]/index.tsx at line 152, Remove the redundant role attribute from
the section element that renders the sponsors block: locate the <section
className='pb-20' aria-label='Our Sponsors'> (currently includes role='region')
and delete the role="region" so the element relies on its implicit ARIA role
while keeping the aria-label intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Hero.tsx`:
- Around line 100-104: The Prettier error is caused by overly long JSX attribute
values in the Hero component's card div (the <div className='rounded-2xl border
border-white/10 bg-slate-900/70 p-4 text-left'> block) and sibling <p> elements;
break long className strings and long JSX lines into multiple lines (e.g., split
the className into multiple lines or wrap each <p> tag's props/content onto
separate lines) to satisfy Prettier, and then run npm run lint:fix (or your
Prettier) to auto-format the other similar blocks mentioned (the nearby <p>
elements for standardize.title/description and the other card blocks).

---

Nitpick comments:
In `@pages/`[lang]/index.tsx:
- Line 152: Remove the redundant role attribute from the section element that
renders the sponsors block: locate the <section className='pb-20'
aria-label='Our Sponsors'> (currently includes role='region') and delete the
role="region" so the element relies on its implicit ARIA role while keeping the
aria-label intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 374f3c64-be2c-4d3f-b4b2-eae6320a9bcb

📥 Commits

Reviewing files that changed from the base of the PR and between 6430335 and b050c78.

📒 Files selected for processing (5)
  • components/Hero.tsx
  • pages/[lang]/index.tsx
  • public/locales/de/landing-page.json
  • public/locales/en/landing-page.json
  • public/locales/zh_cn/landing-page.json

@hriszc
Copy link
Copy Markdown
Author

hriszc commented Mar 18, 2026

Addressed the remaining review nits on the PR branch. I removed the redundant role="region" from the sponsors section and tightened the hero card JSX formatting so the touched landing-page files lint cleanly. Verification run: npm run lint -- --file components/Hero.tsx --file pages/[lang]/index.tsx.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pages/[lang]/index.tsx (1)

152-157: Redundant nested <section> elements.

The outer <section> at line 152 wraps a <Container as='section'>, creating semantically redundant nested sections. Consider removing the outer wrapper or changing the inner Container to render as a <div>.

Suggested fix
-        <section className='pb-20' aria-label='Our Sponsors'>
-          <Container
-            className='rounded-[2rem] border border-slate-200 bg-white px-6 py-10 text-center shadow-sm md:px-10'
-            wide
-            as='section'
-          >
+        <section className='pb-20' aria-label='Our Sponsors'>
+          <Container
+            className='rounded-[2rem] border border-slate-200 bg-white px-6 py-10 text-center shadow-sm md:px-10'
+            wide
+          >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/`[lang]/index.tsx around lines 152 - 157, The outer semantic <section>
wraps a <Container as='section'> causing redundant nested sections; fix by
removing one of them — either delete the outer <section> wrapper or change the
Container's prop from as='section' to as='div' (adjust className/aria-label
accordingly) so only a single appropriate landmark element (the Container or the
outer wrapper) remains; update the aria-label to stay on the remaining section
element if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Hero.tsx`:
- Around line 124-127: The Features component renders a <section> and is
currently nested inside the <header> in the Hero component; move the Features
invocation out of the header so the header only contains introductory content
(or alternatively change the outer <header> in the Hero component to a
non-semantic container like <div>/<section> if the whole block is meant to be a
hero). Locate the Hero component (components/Hero.tsx) and either remove the
<div className='relative mt-10 md:mt-14'><Features /></div> from inside the
<header> and place it directly after the closing </header>, or change the
<header> tag to a <section> or <div> around the hero content and leave <Features
/> in place; ensure no duplicate semantics remain and run a quick
accessibility/HTML validator check.

---

Nitpick comments:
In `@pages/`[lang]/index.tsx:
- Around line 152-157: The outer semantic <section> wraps a <Container
as='section'> causing redundant nested sections; fix by removing one of them —
either delete the outer <section> wrapper or change the Container's prop from
as='section' to as='div' (adjust className/aria-label accordingly) so only a
single appropriate landmark element (the Container or the outer wrapper)
remains; update the aria-label to stay on the remaining section element if
needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f75d7eb1-0adf-4215-b34b-982a469d7a5f

📥 Commits

Reviewing files that changed from the base of the PR and between b050c78 and 2eb10b9.

📒 Files selected for processing (2)
  • components/Hero.tsx
  • pages/[lang]/index.tsx

Comment on lines +124 to 127
<div className='relative mt-10 md:mt-14'>
<Features />
</div>
<Features />
</header>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

<section> inside <header> is semantically incorrect.

The Features component renders a <section> element (per context snippet 3), but it's placed inside the <header> element. HTML semantics dictate that <header> should contain introductory content and navigational aids, not standalone content sections.

Consider either:

  1. Moving Features outside the <header> and returning it as a sibling
  2. Changing the outer <header> to a <div> or <section> if the entire block is meant to be a hero section rather than just the header
Option 1: Move Features outside header
       </header>
+      <div className='mt-10 md:mt-14'>
+        <Features />
+      </div>
     </>
   );
 }

And remove lines 124-126 from inside the header.

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

In `@components/Hero.tsx` around lines 124 - 127, The Features component renders a
<section> and is currently nested inside the <header> in the Hero component;
move the Features invocation out of the header so the header only contains
introductory content (or alternatively change the outer <header> in the Hero
component to a non-semantic container like <div>/<section> if the whole block is
meant to be a hero). Locate the Hero component (components/Hero.tsx) and either
remove the <div className='relative mt-10 md:mt-14'><Features /></div> from
inside the <header> and place it directly after the closing </header>, or change
the <header> tag to a <section> or <div> around the hero content and leave
<Features /> in place; ensure no duplicate semantics remain and run a quick
accessibility/HTML validator check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To Be Triaged

Development

Successfully merging this pull request may close these issues.

Website Homepage Redesign

2 participants