Skip to content

fix: move themeColor and viewport out of metadata into separate viewport export#311

Open
HamidKhan1001 wants to merge 3 commits intoAOSSIE-Org:devfrom
HamidKhan1001:fix/viewport-themecolor-metadata
Open

fix: move themeColor and viewport out of metadata into separate viewport export#311
HamidKhan1001 wants to merge 3 commits intoAOSSIE-Org:devfrom
HamidKhan1001:fix/viewport-themecolor-metadata

Conversation

@HamidKhan1001
Copy link

@HamidKhan1001 HamidKhan1001 commented Feb 22, 2026

PR description:

## Problem
`themeColor` and `viewport` were incorrectly placed inside the 
`metadata` export in `app/layout.js`. Since Next.js 13.4+, these 
must be defined in a separate `viewport` export.

## Fix
Removed both fields from `metadata` and added a new `viewport` export.

## Reference
https://nextjs.org/docs/app/api-reference/functions/generate-viewport

Fixes # (issue)

## Type of change
code change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking CHANGE which fixes an issue)
#310 

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

Please include screenshots below if applicable.

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
- [ ] I have checked my code and corrected any misspellings

## Maintainer Checklist

- [ ] closes #310  (Replace xxxx with the GitHub issue number)
- [ ] Tag the PR with the appropriate labels

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Bug Fixes**
  * Fixed memory leaks by ensuring animation timelines are properly cleaned up when components unmount, preventing resource buildup and improving long-term app performance.

* **Refactor**
  * Restructured viewport configuration from inline property to exported structured format for improved code organization and maintainability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@HamidKhan1001 HamidKhan1001 requested a review from a team as a code owner February 22, 2026 15:18
@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2026

📝 Walkthrough

Walkthrough

The pull request moves themeColor and viewport from the metadata export to a dedicated viewport export in Next.js layout configuration, converting viewport from a string to a structured object. Additionally, GSAP timeline cleanup logic is added to properly terminate animations on component unmount.

Changes

Cohort / File(s) Summary
Viewport Configuration Migration
app/layout.js
Removes themeColor and viewport from metadata export and introduces a new viewport export with structured properties (themeColor, width, initialScale), aligning with Next.js 13.4+ API expectations.
Animation Lifecycle Cleanup
app/page.jsx
Adds explicit cleanup calls (kill()) for GSAP timelines (heroTl, techStackTl, aboutTl, downloadTl) during component unmount to prevent memory leaks and orphaned animations.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 Hop! Hop! The layout now sings,
Viewports dance where Next.js brings,
GSAP timelines bid farewell,
Clean unmounts, no memory knell,
Code springs free, bugs dispel!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes an unrelated GSAP timeline cleanup commit that addresses memory leaks but is not part of the linked issue #310 requirements. Separate the GSAP timeline cleanup into a different PR or link it to an appropriate issue that covers memory leak fixes.
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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: moving themeColor and viewport from metadata to a separate viewport export.
Linked Issues check ✅ Passed The PR addresses all coding requirements from issue #310: removes themeColor and viewport from metadata and adds a separate viewport export with proper structure.

✏️ 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

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.

🧹 Nitpick comments (2)
app/layout.js (1)

23-27: LGTM — correct migration to the dedicated viewport export.

themeColor in the metadata export is deprecated as of Next.js 14 and viewport in metadata is similarly deprecated; both must be in the viewport export instead, exactly as done here.

Two minor, optional improvements worth considering:

  1. Redundant fields: Next.js automatically sets the viewport meta tag, so manual configuration is usually unnecessary as the default is already width=device-width, initial-scale=1. The width and initialScale entries therefore duplicate the framework default and can be omitted, leaving only themeColor which is the non-default value.

  2. JSDoc type annotation: Since this is a .js file, adding a JSDoc comment provides editor type-checking and autocomplete for the Viewport shape. For JavaScript projects you can use JSDoc to add type safety: /** @type {import("next").Viewport} */.

♻️ Optional simplification
+/** `@type` {import("next").Viewport} */
 export const viewport = {
   themeColor: "#000000",
-  width: "device-width",
-  initialScale: 1,
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/layout.js` around lines 23 - 27, Remove redundant viewport fields by
keeping only themeColor in the exported viewport object (symbol: viewport) since
Next.js defaults to width=device-width and initial-scale=1; additionally, add a
JSDoc type annotation above the viewport export (use import("next").Viewport) to
provide editor type-checking and autocomplete in this .js file.
app/page.jsx (1)

213-224: Consider collecting and killing the anonymous feature-item timelines in cleanup.

The four named timelines are now correctly killed. However, the anonymous tl instances created inside the gsap.utils.toArray(".feature-item").forEach(...) block (lines 84–106) are not tracked or killed. ScrollTrigger.getAll().forEach((t) => t.kill()) only kills the ScrollTrigger instances — it does not automatically kill the associated GSAP timeline objects. Those timelines remain in GSAP's internal ticker post-unmount, holding stale DOM references and risking duplicate animations on re-mount (particularly in React StrictMode).

♻️ Proposed fix: collect feature timelines for cleanup
+    const featureTls = [];
     gsap.utils.toArray(".feature-item").forEach((feature, i) => {
       const image = feature.querySelector(".feature-image");
       const text = feature.querySelector(".feature-content h3");
 
       const tl = gsap.timeline({
         scrollTrigger: {
           trigger: feature,
           start: "top 80%",
           toggleActions: "play none none reverse",
         },
       });
 
       tl.fromTo(/* ... */);
+      featureTls.push(tl);
     });

Then in the cleanup:

      heroTl.kill();
      techStackTl.kill();
      aboutTl.kill();
      downloadTl.kill();
+     featureTls.forEach((tl) => tl.kill());
      ScrollTrigger.getAll().forEach((t) => t.kill());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/page.jsx` around lines 213 - 224, The anonymous timelines created inside
gsap.utils.toArray(".feature-item").forEach(...) (the local tl instances) are
not being destroyed; modify the code to collect those tl objects into a
module/local array (e.g., featureTimelines) when you create them and then, in
the cleanup return block where you currently kill heroTl, techStackTl, aboutTl,
downloadTl and call ScrollTrigger.getAll().forEach(...), also iterate over
featureTimelines and call .kill() on each (and optionally clear the array) so
the feature-item timelines are removed from GSAP's ticker and no stale DOM refs
remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/layout.js`:
- Around line 23-27: Remove redundant viewport fields by keeping only themeColor
in the exported viewport object (symbol: viewport) since Next.js defaults to
width=device-width and initial-scale=1; additionally, add a JSDoc type
annotation above the viewport export (use import("next").Viewport) to provide
editor type-checking and autocomplete in this .js file.

In `@app/page.jsx`:
- Around line 213-224: The anonymous timelines created inside
gsap.utils.toArray(".feature-item").forEach(...) (the local tl instances) are
not being destroyed; modify the code to collect those tl objects into a
module/local array (e.g., featureTimelines) when you create them and then, in
the cleanup return block where you currently kill heroTl, techStackTl, aboutTl,
downloadTl and call ScrollTrigger.getAll().forEach(...), also iterate over
featureTimelines and call .kill() on each (and optionally clear the array) so
the feature-item timelines are removed from GSAP's ticker and no stale DOM refs
remain.

@HamidKhan1001 HamidKhan1001 changed the base branch from main to dev February 22, 2026 19:49
@reach2saksham
Copy link

Hi @HamidKhan1001, this is an incorrect PR template. You will need to fix your PR by properly using our standard tempelate and then clearly mentioning the related issue which is #310

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.

3 participants