Skip to content

⚡ Bolt: Optimize BackgroundCarousel image rendering#61

Open
anyulled wants to merge 2 commits intomainfrom
bolt-optimize-background-carousel-12419383181279936805
Open

⚡ Bolt: Optimize BackgroundCarousel image rendering#61
anyulled wants to merge 2 commits intomainfrom
bolt-optimize-background-carousel-12419383181279936805

Conversation

@anyulled
Copy link
Owner

@anyulled anyulled commented Feb 26, 2026

💡 What: Optimized components/BackgroundCarousel.tsx to conditionally render next/image components inside Swiper slides.
🎯 Why: The carousel was rendering all 15 large background images at once, which increased memory usage and DOM node count.
📊 Impact: Reduces the number of simultaneously rendered images from 15 (plus duplicates) to ~7-9, significantly reducing memory footprint and DOM complexity.
🔬 Measurement: Verified with a Playwright script that the number of images in the DOM is reduced while maintaining visual correctness during loop transitions. Tests passed.


PR created automatically by Jules for task 12419383181279936805 started by @anyulled

Summary by CodeRabbit

  • Bug Fixes

    • Eliminated visual flicker during carousel loop transitions and improved slide-change smoothness.
    • Reduced unnecessary image rendering to improve carousel performance while preserving motion effects and image quality.
  • Tests

    • Updated end-to-end test selector to target the correct event header elements, keeping venue and date visibility checks intact.

- Implement conditional rendering for images in BackgroundCarousel to reduce DOM nodes and memory usage.
- Only render active, next, previous, and loop boundary slides.
- Ensure loop transitions are smooth by always rendering the first 2 and last 2 slides.
- Add activeIndex state tracking via Swiper's onSlideChange event.

Co-authored-by: anyulled <100741+anyulled@users.noreply.github.com>
@google-labs-jules
Copy link
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel
Copy link

vercel bot commented Feb 26, 2026

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

Project Deployment Actions Updated (UTC)
devbcn Ready Ready Preview, Comment Feb 26, 2026 9:51am

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @anyulled, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the performance of the 'BackgroundCarousel' component by optimizing how background images are loaded and rendered. By intelligently determining which images are necessary for immediate display or smooth transitions, it drastically cuts down on resource consumption without compromising the visual integrity of the carousel.

Highlights

  • Image Rendering Optimization: Implemented conditional rendering for 'next/image' components within the 'BackgroundCarousel' to load images only when they are active, adjacent, or critical for smooth loop transitions.
  • Performance Improvement: Reduced the number of simultaneously rendered images from 15 to approximately 7-9, leading to a significant decrease in memory usage and DOM node count.
  • Enhanced User Experience: Maintained visual correctness during carousel loop transitions while improving overall page load performance and responsiveness.
Changelog
  • components/BackgroundCarousel.tsx
    • Introduced 'activeIndex' state to track the currently displayed slide.
    • Configured the 'Swiper' component to update the 'activeIndex' on slide changes.
    • Implemented conditional rendering logic for 'next/image' components based on their proximity to the active slide and their position for loop duplicates.
Activity
  • PR created automatically by Jules for task 12419383181279936805, initiated by @anyulled.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request effectively optimizes the BackgroundCarousel by conditionally rendering images, which will reduce memory usage and the number of DOM nodes. The logic to determine which slides to render is sound, correctly accounting for the active, next, and previous slides, as well as buffer slides at the start and end to ensure smooth looping. I have one suggestion to refactor the rendering logic slightly for better performance and readability.

Comment on lines +76 to +107
{IMAGES.map((image, index) => {
const isActive = index === activeIndex;
const isNext = index === (activeIndex + 1) % IMAGES.length;
const isPrev = index === (activeIndex - 1 + IMAGES.length) % IMAGES.length;

/*
* Always render the first 2 and last 2 slides to ensure loop duplicates have content
* This prevents flickering during loop transitions as Swiper clones these slides
*/
const isStart = index < 2;
const isEnd = index >= IMAGES.length - 2;

const shouldRender = isActive || isNext || isPrev || isStart || isEnd;

return (
<SwiperSlide key={image}>
<div className={`background-carousel__slide ${prefersReducedMotion ? "" : "ken-burns"}`}>
{shouldRender && (
<Image
src={image}
alt="Conference venue background"
fill
priority={index === 0}
sizes="100vw"
style={{ objectFit: "cover" }}
quality={85}
/>
)}
</div>
</SwiperSlide>
);
})}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This is a great optimization! To further improve performance and readability, you could calculate the set of indices to render once before mapping over the images. This avoids redundant calculations inside the loop for every image.

Using an Immediately Invoked Function Expression (IIFE) allows you to contain this logic cleanly within the JSX, improving both performance and separation of concerns.

        {(() => {
          const imageCount = IMAGES.length;
          /*
           * To prevent flicker with loop, we need to render more than just the active slide.
           * This set includes:
           * - The active, previous, and next slides for smooth transitions.
           * - The first 2 and last 2 slides, which Swiper clones for the loop effect.
           */
          const indicesToRender = new Set([
            activeIndex,
            (activeIndex + 1) % imageCount,
            (activeIndex - 1 + imageCount) % imageCount,
            0,
            1,
            imageCount - 2,
            imageCount - 1,
          ]);

          return IMAGES.map((image, index) => (
            <SwiperSlide key={image}>
              <div className={`background-carousel__slide ${prefersReducedMotion ? "" : "ken-burns"}`}>
                {indicesToRender.has(index) && (
                  <Image
                    src={image}
                    alt="Conference venue background"
                    fill
                    priority={index === 0}
                    sizes="100vw"
                    style={{ objectFit: "cover" }}
                    quality={85}
                  />
                )}
              </div>
            </SwiperSlide>
          ));
        })()}

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7eecb8 and d07fedd.

📒 Files selected for processing (2)
  • components/BackgroundCarousel.tsx
  • cypress/e2e/home/home-editions.cy.ts

📝 Walkthrough

Walkthrough

BackgroundCarousel now tracks the active slide and conditionally renders slide images (active, adjacent, and first/last two slides) to reduce DOM updates and avoid flicker from loop clones; the Ken Burns effect and image attributes are preserved.

Changes

Cohort / File(s) Summary
Slide rendering optimization
components/BackgroundCarousel.tsx
Adds activeIndex state and onSlideChange handler; computes isActive/isNext/isPrev/isStart/isEnd per slide and renders Image only for active, neighbor, or edge slides to minimize DOM updates while preserving Ken Burns and image props.
Test selector update
cypress/e2e/home/home-editions.cy.ts
Replaces selector h5 with .hero8-header__event-line inside .hero8-header for element count and visibility assertions; no change to test logic otherwise.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 I hop through slides with nimble grace,
I show the near ones, let the rest embrace,
Two at the start, two at the end,
No flicker now — a smoother blend,
Hooray, the carousel finds its pace! 🎠

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main optimization in the changeset: improving image rendering performance in the BackgroundCarousel component.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bolt-optimize-background-carousel-12419383181279936805

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

❤️ Share

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

Copy link

@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.

Caution

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

⚠️ Outside diff range comments (1)
components/BackgroundCarousel.tsx (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Fix Prettier formatting issues.

The CI pipeline is failing due to Prettier formatting violations. Run npm run format:check locally to identify the issues, then prettier --write to fix them.

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

In `@components/BackgroundCarousel.tsx` at line 1, Prettier formatting in
BackgroundCarousel.tsx is failing CI; run the formatter and commit the fixes:
run `npm run format:check` to see violations, then run `prettier --write` (or
`npm run format`) against the project (or specifically BackgroundCarousel.tsx)
to fix the formatting, verify the file (BackgroundCarousel, "use client"
directive and surrounding JSX) is now Prettier-compliant, and commit the updated
file so CI passes.
🧹 Nitpick comments (1)
components/BackgroundCarousel.tsx (1)

38-38: Consider synchronizing initial state with Swiper's actual starting index.

The activeIndex is initialized to 0, which works for the default Swiper configuration. However, if initialSlide is ever configured differently in the future, this could cause a brief mismatch where the wrong slides are rendered on mount.

A more defensive approach would be to initialize from the Swiper instance:

♻️ Optional: Initialize from Swiper instance
-        onSwiper={() => {}}
+        onSwiper={(swiper) => setActiveIndex(swiper.realIndex)}

This ensures the initial state always matches Swiper's actual starting position, even if configuration changes.

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

In `@components/BackgroundCarousel.tsx` at line 38, Initialize activeIndex from
the actual Swiper instance instead of hardcoding 0: replace the current
useState(0) for activeIndex with a state that is set when the Swiper instance is
available (use the Swiper onSwiper callback or an existing swiperRef) and call
setActiveIndex(swiper.activeIndex) there (also keep the existing onSlideChange
handler updating setActiveIndex). This ensures activeIndex (and setActiveIndex)
reflect Swiper's real initialSlide value on mount.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@components/BackgroundCarousel.tsx`:
- Line 1: Prettier formatting in BackgroundCarousel.tsx is failing CI; run the
formatter and commit the fixes: run `npm run format:check` to see violations,
then run `prettier --write` (or `npm run format`) against the project (or
specifically BackgroundCarousel.tsx) to fix the formatting, verify the file
(BackgroundCarousel, "use client" directive and surrounding JSX) is now
Prettier-compliant, and commit the updated file so CI passes.

---

Nitpick comments:
In `@components/BackgroundCarousel.tsx`:
- Line 38: Initialize activeIndex from the actual Swiper instance instead of
hardcoding 0: replace the current useState(0) for activeIndex with a state that
is set when the Swiper instance is available (use the Swiper onSwiper callback
or an existing swiperRef) and call setActiveIndex(swiper.activeIndex) there
(also keep the existing onSlideChange handler updating setActiveIndex). This
ensures activeIndex (and setActiveIndex) reflect Swiper's real initialSlide
value on mount.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d46ccee and a7eecb8.

📒 Files selected for processing (1)
  • components/BackgroundCarousel.tsx

- Fix Prettier formatting in `components/BackgroundCarousel.tsx`.
- Update `cypress/e2e/home/home-editions.cy.ts` to assert on `.hero8-header__event-line` instead of `h5`, matching the actual markup.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant