From c58d03cb3b663cc3c65b03b67dfada42796b5e7e Mon Sep 17 00:00:00 2001 From: Aryan Mehrotra Date: Tue, 5 May 2026 23:49:18 +0530 Subject: [PATCH] showcase: shared gradient layer + testimonials masonry fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ShowcaseGradient is a small decorative orb layer (cyan + indigo, matching the Hero's existing vocabulary). Drop it inside any `relative overflow-x-clip` wrapper and three pointer-events-none orbs distribute down the page at alternating sides. Wired into the framework's pitch surfaces: - homepage (replaces the inline orb cluster) - /why-gofr, /comparison/*, /migrate/* via MarketingPage's new opt-in `withGradient` prop - /showcase (its custom layout doesn't use MarketingPage, so it composes ShowcaseGradient directly) Reading-mode pages keep the calm canvas they had — /faq, /learn also use MarketingPage but don't pass withGradient. /docs/** and the rest of the site are untouched. Also fixes the testimonials masonry on narrow viewports (`Reviews.jsx`): added `block break-inside-avoid w-full` to each card and `gap-x-6` between columns. Without break-inside-avoid, CSS multi-column layout was splitting tall cards across the column boundary, rendering the two halves on top of each other. Co-Authored-By: Claude Opus 4.6 --- src/app/comparison/layout.jsx | 2 +- src/app/migrate/layout.jsx | 2 +- src/app/showcase/page.jsx | 6 ++-- src/app/why-gofr/layout.jsx | 2 +- src/components/HomePage.jsx | 4 ++- src/components/MarketingPage.jsx | 17 +++++++-- src/components/Reviews.jsx | 8 +++-- src/components/ShowcaseGradient.jsx | 56 +++++++++++++++++++++++++++++ 8 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 src/components/ShowcaseGradient.jsx diff --git a/src/app/comparison/layout.jsx b/src/app/comparison/layout.jsx index b9d1c77..cec017f 100644 --- a/src/app/comparison/layout.jsx +++ b/src/app/comparison/layout.jsx @@ -1,4 +1,4 @@ import { MarketingPage } from '@/components/MarketingPage' -const Layout = ({ children }) => {children} +const Layout = ({ children }) => {children} export default Layout diff --git a/src/app/migrate/layout.jsx b/src/app/migrate/layout.jsx index b9d1c77..cec017f 100644 --- a/src/app/migrate/layout.jsx +++ b/src/app/migrate/layout.jsx @@ -1,4 +1,4 @@ import { MarketingPage } from '@/components/MarketingPage' -const Layout = ({ children }) => {children} +const Layout = ({ children }) => {children} export default Layout diff --git a/src/app/showcase/page.jsx b/src/app/showcase/page.jsx index b0a0c68..0dd574b 100644 --- a/src/app/showcase/page.jsx +++ b/src/app/showcase/page.jsx @@ -4,6 +4,7 @@ import { useEffect, useState } from 'react' import Image from 'next/image' import Link from 'next/link' import { formatNumber } from '@/lib/common' +import { ShowcaseGradient } from '@/components/ShowcaseGradient' import companies from './companies.json' import testimonials from '../../../utils/testimonials.json' @@ -53,8 +54,9 @@ export default function ShowcasePage() { }, []) return ( -
-
+
+ +
{/* Hero */}

diff --git a/src/app/why-gofr/layout.jsx b/src/app/why-gofr/layout.jsx index b9d1c77..cec017f 100644 --- a/src/app/why-gofr/layout.jsx +++ b/src/app/why-gofr/layout.jsx @@ -1,4 +1,4 @@ import { MarketingPage } from '@/components/MarketingPage' -const Layout = ({ children }) => {children} +const Layout = ({ children }) => {children} export default Layout diff --git a/src/components/HomePage.jsx b/src/components/HomePage.jsx index c29d23a..693b4da 100644 --- a/src/components/HomePage.jsx +++ b/src/components/HomePage.jsx @@ -7,6 +7,7 @@ import { EcosystemRecognition } from '@/components/EcosystemRecognition' import { FadeInOnScroll } from '@/components/FadeInOnScroll' import { StaggerChildren } from '@/components/StaggerChildren' import blurCyanImage from "@/images/blur-cyan.png"; +import { ShowcaseGradient } from '@/components/ShowcaseGradient' import Image from "next/image"; import React from "react"; import Testimonials from "@/components/Reviews"; @@ -19,7 +20,8 @@ import Testimonials from "@/components/Reviews"; // continuous strip rather than two seams. export function HomePage() { return ( -
+
+ {/* Density-matched section padding. Uniform `py-24` everywhere made the page feel padded-for-padding's-sake when section content was thin (a 100 px marquee strip, a 1-row logo wall). diff --git a/src/components/MarketingPage.jsx b/src/components/MarketingPage.jsx index 73db1ec..73524df 100644 --- a/src/components/MarketingPage.jsx +++ b/src/components/MarketingPage.jsx @@ -1,13 +1,26 @@ +import { ShowcaseGradient } from '@/components/ShowcaseGradient' + // Wrapper for the SEO-only Markdoc pages (/why-gofr, /comparison/*, // /migrate/*, /learn, /faq). It supplies the flex container DocsLayout // expects, but unlike DocsPage it does NOT render a left sidebar — these // pages aren't core navigation, they're SEO landing content. Right-rail // "On this page" TOC from DocsLayout still renders. Cross-links to the // other SEO pages live in the global footer. -export function MarketingPage({ children }) { +// +// `withGradient` adds the decorative orb layer (ShowcaseGradient). +// Opt-in because /faq and /learn are reading-mode reference pages +// where the gradient is just visual noise; /why-gofr, /comparison/*, +// /migrate/* are positioning surfaces where it belongs. +export function MarketingPage({ children, withGradient = false }) { return (
-
+
+ {withGradient && } {children}
diff --git a/src/components/Reviews.jsx b/src/components/Reviews.jsx index 81d9d51..c132d79 100644 --- a/src/components/Reviews.jsx +++ b/src/components/Reviews.jsx @@ -9,9 +9,13 @@ export default function Testimonials() { {/*

*/} {/* User Testimonials*/} {/*

*/} -
+
{testimonials.map((testimonial, index) => ( -
+ // `block break-inside-avoid` keeps each card whole inside + // the CSS multi-column flow. Without it, a tall card gets + // split at the column boundary and the two halves render + // on top of each other on narrow viewports. +
diff --git a/src/components/ShowcaseGradient.jsx b/src/components/ShowcaseGradient.jsx new file mode 100644 index 0000000..e6cb387 --- /dev/null +++ b/src/components/ShowcaseGradient.jsx @@ -0,0 +1,56 @@ +import Image from 'next/image' +import blurCyanImage from '@/images/blur-cyan.png' +import blurIndigoImage from '@/images/blur-indigo.png' + +// Decorative gradient layer for the framework's pitch / showcase +// surfaces — homepage, /why-gofr, /comparison/*, /showcase, /migrate/*. +// Three pointer-events-none orbs distributed down the page at +// alternating sides, reusing the cyan + indigo vocabulary the hero +// already establishes. Drop inside any `relative overflow-x-clip` +// wrapper. +// +// Why an absolute layer instead of a CSS background-image: +// - Matches the existing Hero implementation (Image PNGs, opacity). +// - Lets us anchor each orb relative to a known parent, so different +// pages can opt in without re-tuning a body-level gradient. +// +// Why `unoptimized` is mandatory: the site builds with +// `output: 'export'`, which disables /_next/image. Without unoptimized, +// Next emits a /_next/image?url=... src that 404s in production and +// renders as a broken-image icon. +export function ShowcaseGradient() { + return ( + <> + + + + + ) +}