Repository: dscnitrourkela/project-huckleberry
Pull request #49: feat: add layout and events page
Author: login: BlessedAmrita
Created: 2025-05-09T05:06:31Z | Merged: 2025-05-09T09:00:15Z



### Description

- ✨ Added a **common layout** for `About Us`, `Projects`, and `Events` pages under `/app/(common)/layout.tsx`
- 📄 Created an **Events page** at `/events` with listing functionality
- 🧾 Added **individual event details page** at `/events/[eventID]`
- 🧩 Structured components for event UI:
  - `EventDetails.tsx`
  - `EventInfoCard.tsx`
  - `EventsCard.tsx`
- 🖋️ Integrated **Product Sans fonts** locally for consistent typography



Diff:
diff --git a/src/app/(home)/(common)/events/[eventID]/page.tsx b/src/app/(home)/(common)/events/[eventID]/page.tsx
new file mode 100644
index 0000000..8abe7a1
--- /dev/null
+++ b/src/app/(home)/(common)/events/[eventID]/page.tsx
@@ -0,0 +1,9 @@
+import EventDetail from '@/components/home/events/EventDetails';
+export default async function EventPage({
+  params,
+}: {
+  params: Promise<{ eventID: string }>;
+}) {
+  const { eventID } = await params;
+  return <EventDetail eventID={eventID} />;
+}
diff --git a/src/app/(home)/(common)/events/page.tsx b/src/app/(home)/(common)/events/page.tsx
new file mode 100644
index 0000000..c309d00
--- /dev/null
+++ b/src/app/(home)/(common)/events/page.tsx
@@ -0,0 +1,26 @@
+'use client';
+import React from 'react';
+import EventsCard from '@/components/home/events/EventsCard';
+import { events } from '@/config/events';
+function page() {
+  return (
+    <div className="relative overflow-hidden ">
+      {/* Event Cards */}
+      <div className="w-full space-y-12 px-4 sm:px-8 max-w-7xl mx-auto pb-16">
+        {events.map((event, index) => (
+          <EventsCard
+            key={event.id}
+            id={event.id}
+            heading={event.heading}
+            title={event.title}
+            date={event.date}
+            description={event.description}
+            imageUrl={event.imageUrl}
+            cardBgColor={event.cardBgColor}
+          />
+        ))}
+      </div>
+    </div>
+  );
+}
+export default page;
diff --git a/src/app/(home)/(common)/layout.tsx b/src/app/(home)/(common)/layout.tsx
new file mode 100644
index 0000000..283af8f
--- /dev/null
+++ b/src/app/(home)/(common)/layout.tsx
@@ -0,0 +1,30 @@
+'use client';
+import React from 'react';
+import { usePathname } from 'next/navigation';
+import LayoutHero from '@/components/home/LayoutHero';
+import { pageContent } from '@/config/layout';
+import Circle from '@/components/shared/Circle';
+
+export default function PublicLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  const pathname = usePathname();
+  const content = pageContent[pathname as keyof typeof pageContent];
+  if (!content) return <>{children}</>;
+  return (
+    <div className="relative overflow-hidden bg-white">
+      {/* Background Circle */}
+      <Circle bgColor={content.bgColor} />
+      {/* Hero Section */}
+      <LayoutHero
+        title={content.title}
+        description={content.description}
+        imageUrl={content.imageUrl}
+      />
+      {/* Main Content */}
+      <main className="px-4 sm:px-6 lg:px-8 relative z-20">{children}</main>
+    </div>
+  );
+}
diff --git a/src/app/(home)/(common)/projects/page.tsx b/src/app/(home)/(common)/projects/page.tsx
new file mode 100644
index 0000000..6af3b90
--- /dev/null
+++ b/src/app/(home)/(common)/projects/page.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+
+function page() {
+  return (
+    <div className="w-full h-[100vh] justify-center items-center flex flex-col">
+      <div className="shadow-xl rounded-xl px-[300px] pt-[40px] pb-[60px] bg-[#FDEDEB]">
+        <h1 className="text-xl font-semibold text-gray-900">Projects Page</h1>
+      </div>
+    </div>
+  );
+}
+
+export default page;
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 939ac54..703ca6f 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -17,7 +17,7 @@ export default function RootLayout({
   return (
     <html lang="en" suppressHydrationWarning={true}>
       <body
-        className={`${geistSans.variable} ${geistMono.variable} ${poppins.variable} ${dmSans.variable} ${productSans.variable} antialiased`}
+        className={`${geistSans.variable} ${geistMono.variable} ${poppins.variable} ${dmSans.variable} ${productSans.variable}  antialiased`}
       >
         <Toaster position="top-right" />
         <HOC>{children}</HOC>
diff --git a/src/components/home/LayoutHero.tsx b/src/components/home/LayoutHero.tsx
new file mode 100644
index 0000000..75b5325
--- /dev/null
+++ b/src/components/home/LayoutHero.tsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import Image from 'next/image';
+
+interface LayoutHeroProps {
+  title: string;
+  description: React.ReactNode;
+  imageUrl: string;
+}
+
+const LayoutHero: React.FC<LayoutHeroProps> = ({
+  title,
+  description,
+  imageUrl,
+}) => {
+  return (
+    <div className="w-full max-w-7xl mx-auto pt-6 sm:pt-8 px-4 sm:px-6 lg:px-8">
+      {/* Hero Image */}
+      <div className="relative w-full aspect-[3/1.4] sm:aspect-[3/1.2] md:aspect-[3/1.1] lg:aspect-[3/1.1] rounded-xl overflow-hidden shadow-md">
+        <Image
+          src={imageUrl}
+          alt="Event Hero"
+          fill
+          className="object-cover rounded-xl"
+          priority
+        />
+        <div className="absolute inset-0 bg-gradient-to-t from-black/70 to-white/20 rounded-xl" />
+      </div>
+
+      {/* Heading + Subtext Block */}
+      <div className="py-8 sm:py-12 z-10 relative">
+        <div className="bg-white shadow-md px-4 sm:px-6 lg:px-10 py-6 sm:py-8 flex flex-col sm:flex-row justify-between items-center lg:items-center border-y-2 border-black font-productsans text-black gap-6 lg:gap-0">
+          <h2 className="text-3xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-bold text-[#313131]">
+            {title}
+          </h2>
+          <p className="text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl leading-relaxed sm:mt-2 lg:mt-0 max-w-xl text-left">
+            {description}
+          </p>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default LayoutHero;
diff --git a/src/components/home/events/EventDetails.tsx b/src/components/home/events/EventDetails.tsx
new file mode 100644
index 0000000..5d66a23
--- /dev/null
+++ b/src/components/home/events/EventDetails.tsx
@@ -0,0 +1,100 @@
+import { Calendar, MapPin, Info, Users } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import EventInfoCard from '@/components/home/events/EventInfoCard';
+import Image from 'next/image';
+
+// Mock data to simulate fetching event by ID
+const getEventById = (id: string) => {
+  return {
+    id,
+    coverImage:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+    title: `#${id} HackNITR`,
+    subTitle: 'Largest Student-run Hackathon: HackNITR',
+    description:
+      'Lorem ipsum dolor sit amet consectetur. Eget eu maecenas mattis dapibus fermentum duis. Mattis risus pharetra suspendisse posuere mauris suspendisse est diam quis. Amet nulla lobortis vitae dolor malesuada praesent arcu tincidunt. Feugiat posuere adipiscing pede duis elit in cras netus rhoncus.',
+    location: 'NIT Rourkela, Odisha',
+    mode: 'Offline',
+    eligibility: 'All college students',
+    timestamp: '18/04/2023',
+  };
+};
+interface EventDetailProps {
+  eventID: string;
+}
+const EventDetail = ({ eventID }: EventDetailProps) => {
+  const event = getEventById(eventID);
+  return (
+    <div className="min-h-screen flex flex-col font-productsans font-medium tracking-wide">
+      <main className="flex-1 px-4 sm:px-6 md:px-8 lg:px-16 max-w-7xl mx-auto w-full">
+        <div className="py-10">
+          <h1 className="text-3xl sm:text-4xl lg:text-5xl font-bold mb-4 text-center">
+            {event.title}
+          </h1>
+
+          {/* Image Section */}
+          <div className="w-full max-h-[400px] sm:max-h-[500px] overflow-hidden rounded-xl my-6">
+            <Image
+              src={event.coverImage}
+              alt={event.title}
+              width={800}
+              height={500}
+              className="w-full object-cover"
+            />
+          </div>
+
+          {/* Event Details */}
+          <div className="mt-4 bg-blue-50 rounded-xl p-6">
+            <div className="flex flex-col sm:flex-row justify-between gap-6">
+              <div className="flex-1">
+                <h3 className="text-xl sm:text-2xl font-semibold mb-4">
+                  {event.subTitle}
+                </h3>
+                <div className="text-gray-700 mb-6">{event.description}</div>
+
+                {/* Event Info Cards */}
+                <div className="grid grid-cols-1 sm:grid-cols-2 gap-6 mt-8">
+                  <EventInfoCard
+                    icon={<Calendar className="text-blue-600" />}
+                    title="Date"
+                    description={event.timestamp}
+                    bgColor="bg-blue-100"
+                  />
+
+                  <EventInfoCard
+                    icon={<MapPin className="text-red-600" />}
+                    title="Location"
+                    description={event.location}
+                    bgColor="bg-red-100"
+                  />
+
+                  <EventInfoCard
+                    icon={<Info className="text-green-600" />}
+                    title="Mode"
+                    description={event.mode}
+                    bgColor="bg-green-100"
+                  />
+
+                  <EventInfoCard
+                    icon={<Users className="text-purple-600" />}
+                    title="Eligibility"
+                    description={event.eligibility}
+                    bgColor="bg-purple-100"
+                  />
+                </div>
+              </div>
+            </div>
+
+            {/* Registration Button */}
+            <div className="mt-10 flex justify-center">
+              <Button className="bg-blue-600 hover:bg-blue-700 text-white rounded-md px-8 py-2 sm:px-10 sm:py-3 font-medium transition-all">
+                Apply for Registration
+              </Button>
+            </div>
+          </div>
+        </div>
+      </main>
+    </div>
+  );
+};
+export default EventDetail;
diff --git a/src/components/home/events/EventInfoCard.tsx b/src/components/home/events/EventInfoCard.tsx
new file mode 100644
index 0000000..9c6b0b4
--- /dev/null
+++ b/src/components/home/events/EventInfoCard.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import { cn } from '@/lib/utils';
+interface EventInfoCardProps {
+  icon: React.ReactNode;
+  title: string;
+  description: string;
+  bgColor?: string;
+}
+const EventInfoCard: React.FC<EventInfoCardProps> = ({
+  icon,
+  title,
+  description,
+  bgColor = 'bg-gray-100',
+}) => {
+  return (
+    <div className={cn('p-4 rounded-lg flex items-start', bgColor)}>
+      <div className="mr-4 mt-1">{icon}</div>
+      <div>
+        <h4 className="font-medium text-gray-900">{title}</h4>
+        <p className="text-gray-600 mt-1">{description}</p>
+      </div>
+    </div>
+  );
+};
+export default EventInfoCard;
diff --git a/src/components/home/events/EventsCard.tsx b/src/components/home/events/EventsCard.tsx
new file mode 100644
index 0000000..8e95057
--- /dev/null
+++ b/src/components/home/events/EventsCard.tsx
@@ -0,0 +1,100 @@
+'use client';
+import { useEffect, useRef } from 'react';
+import { gsap } from 'gsap';
+import { ScrollTrigger } from 'gsap/ScrollTrigger';
+import { SplitText } from 'gsap/SplitText';
+import Image from 'next/image';
+import Link from 'next/link';
+import { Button } from '../../ui/button';
+interface EventsCardProps {
+  id: string;
+  heading: string;
+  title: string;
+  date: string;
+  description: string;
+  imageUrl: string;
+  cardBgColor?: string;
+}
+const EventsCard: React.FC<EventsCardProps> = ({
+  id,
+  heading,
+  title,
+  date,
+  description,
+  imageUrl,
+  cardBgColor = 'bg-white',
+}) => {
+  const descriptionRef = useRef<HTMLParagraphElement | null>(null);
+  useEffect(() => {
+    gsap.registerPlugin(ScrollTrigger, SplitText);
+
+    if (descriptionRef.current) {
+      const splitDesc = new SplitText(descriptionRef.current, {
+        type: 'lines',
+      });
+
+      const animation = gsap.from(splitDesc.lines, {
+        opacity: 0,
+        y: 20,
+        duration: 0.5,
+        ease: 'power1.out',
+        stagger: 0,
+        scrollTrigger: {
+          trigger: descriptionRef.current,
+          start: 'top 90%',
+          end: 'bottom 20%',
+          toggleActions: 'play none none reverse',
+        },
+      });
+
+      return () => {
+        if (splitDesc) splitDesc.revert();
+        animation.scrollTrigger?.kill();
+      };
+    }
+  }, []);
+
+  return (
+    <div className="w-full flex flex-col items-center font-productsans px-4 sm:px-6 lg:px-8">
+      {/* Header */}
+      <h2 className="text-3xl sm:text-5xl md:text-6xl font-bold mt-8 mb-6 text-center text-black">
+        {heading}
+      </h2>
+      {/* Image Section */}
+      <div className="relative w-full max-w-7xl aspect-[3/1.3] sm:aspect-[3/1.1] rounded-xl overflow-hidden shadow-lg">
+        <Image
+          src={imageUrl}
+          alt={`${title} Event`}
+          fill
+          className="object-cover"
+          priority
+        />
+      </div>
+      {/* Info Card */}
+      <div
+        className={`${cardBgColor} shadow-md shadow-gray-300 rounded-xl px-6 sm:px-10 lg:px-16 pt-10 pb-14 
+      mt-4 sm:-mt-20 lg:-mt-32 w-full max-w-4xl z-10 relative text-center tracking-wider`}
+      >
+        <h3 className="text-xl sm:text-2xl lg:text-3xl font-bold text-black">
+          Largest Student-run Hackathon: {title}
+        </h3>
+        <p className="text-blue-600 font-semibold text-base sm:text-lg mt-1">
+          Date: {date}
+        </p>
+        <p
+          ref={descriptionRef}
+          className="text-sm sm:text-base text-[#4A4A68] mt-4 leading-relaxed"
+        >
+          {description}
+        </p>
+        <Link href={`/events/${id}`}>
+          <Button className="bg-[#1B66F6] text-white mt-6 py-2 px-6 sm:py-3 sm:px-8 text-sm sm:text-base">
+            View Details
+          </Button>
+        </Link>
+      </div>
+    </div>
+  );
+};
+
+export default EventsCard;
diff --git a/src/components/shared/Circle.tsx b/src/components/shared/Circle.tsx
new file mode 100644
index 0000000..1941cdb
--- /dev/null
+++ b/src/components/shared/Circle.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+interface CircleProps {
+  bgColor: string;
+}
+const Circle: React.FC<CircleProps> = ({ bgColor }) => {
+  return (
+    <div
+      className="absolute w-[300px] h-[300px] sm:w-[400px] sm:h-[400px] md:w-[500px] md:h-[500px] lg:w-[600px] lg:h-[600px] rounded-full top-[300px] left-[-120px] z-0"
+      style={{ backgroundColor: bgColor }}
+    />
+  );
+};
+export default Circle;
diff --git a/src/config/events/index.ts b/src/config/events/index.ts
new file mode 100644
index 0000000..b1c933e
--- /dev/null
+++ b/src/config/events/index.ts
@@ -0,0 +1,35 @@
+export const events = [
+  {
+    id: '1',
+    heading: '#1 HackNITR',
+    title: 'HackNITR',
+    date: '29/02/2025',
+    description:
+      'Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet. Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet.Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet.',
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+    cardBgColor: 'bg-[#ECF3FE]',
+  },
+  {
+    id: '2',
+    heading: '#2 HackNITR',
+    title: 'HackNITR',
+    date: '29/02/2025',
+    description:
+      'Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet. Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet.Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet.',
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+    cardBgColor: 'bg-[#FDEDEB]',
+  },
+  {
+    id: '3',
+    heading: '#3 HackNITR',
+    title: 'HackNITR',
+    date: '29/02/2025',
+    description:
+      'Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet. Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet.Lorem ipsum dolor sit amet consectetur. Augue duis etiam pulvinar duis interdum accumsan tempor bibendum amet.',
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+    cardBgColor: 'bg-[#EBF7EE]',
+  },
+];
diff --git a/src/config/layout/index.tsx b/src/config/layout/index.tsx
new file mode 100644
index 0000000..b0cbd37
--- /dev/null
+++ b/src/config/layout/index.tsx
@@ -0,0 +1,68 @@
+import React from 'react';
+export const pageContent = {
+  '/events': {
+    bgColor: '#E8F5EE',
+    title: 'Our Events',
+    description: (
+      <>
+        At Vero Et Accusamus Et
+        <br />
+        Lusto Odio Dignissimos The.
+      </>
+    ),
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+  },
+  '/about-us': {
+    bgColor: '#FFF4EC',
+    title: 'About Us',
+    description: (
+      <>
+        At Vero Et Accusamus Et
+        <br />
+        Lusto Odio Dignissimos The.
+      </>
+    ),
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+  },
+  '/projects': {
+    bgColor: '#F0F4FF',
+    title: 'Our Projects',
+    description: (
+      <>
+        At Vero Et Accusamus Et
+        <br />
+        Lusto Odio Dignissimos The.
+      </>
+    ),
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+  },
+  '/resources': {
+    bgColor: '#FFF4EC',
+    title: 'Resources',
+    description: (
+      <>
+        At Vero Et Accusamus Et
+        <br />
+        Lusto Odio Dignissimos The.
+      </>
+    ),
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+  },
+  '/team': {
+    bgColor: '#E8F5EE',
+    title: 'Our Team',
+    description: (
+      <>
+        At Vero Et Accusamus Et
+        <br />
+        Lusto Odio Dignissimos The.
+      </>
+    ),
+    imageUrl:
+      'https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png',
+  },
+};
diff --git a/src/middleware.ts b/src/middleware.ts
index e7a1831..ad29ff9 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -11,9 +11,7 @@ export async function middleware(request) {
     return NextResponse.next();
   }
 
-  if (
-    request.nextUrl.pathname.startsWith('/admin')
-  ) {
+  if (request.nextUrl.pathname.startsWith('/admin')) {
     if (!session?.user) {
       return NextResponse.redirect(new URL('/login', request.url));
     }


Reviews:
user: login: ayussh-2
body: SUGGESTING SOME MINOR CHANGES IN REFACTORING REST LOOKS FINE
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-09T08:05:36Z
user: login: ayussh-2
body: LGTM!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-09T08:59:50Z

Review comments:
diff_hunk: @@ -1,10 +1,13 @@
 import type { Metadata } from 'next';
 import './globals.css';
-import { dmSans,
+import {
+  dmSans,
   geistMono,
-  geistSans, poppins,
-  productSansRegular,
-  productSansBlack,
+  geistSans,
+  poppins,
+  productSans,
+  // productSansRegular,
path: src/app/layout.tsx
user: login: ayussh-2
body: REMOVE COMMENTS
created_at: 2025-05-09T07:58:35Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+'use client';
+import React from 'react';
+import { usePathname } from 'next/navigation';
+import { Inter } from 'next/font/google';
+import Image from 'next/image';
+
+const inter = Inter({ subsets: ['latin'] });
path: src/app/(home)/(common)/layout.tsx
user: login: ayussh-2
body: REMOVE THIS
created_at: 2025-05-09T07:59:56Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+'use client';
+import React from 'react';
+import { usePathname } from 'next/navigation';
+import { Inter } from 'next/font/google';
+import Image from 'next/image';
+
+const inter = Inter({ subsets: ['latin'] });
+
+export default function PublicLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  const pathname = usePathname();
+  const content = pageContent[pathname as keyof typeof pageContent];
+
+  if (!content) return <>{children}</>;
+
+  return (
+    <div className="relative overflow-hidden bg-white">
+      {/* Background Circle */}
+      <div
+        className="absolute w-[300px] h-[300px] sm:w-[400px] sm:h-[400px] md:w-[500px] md:h-[500px] lg:w-[600px] lg:h-[600px] rounded-full top-[300px] left-[-120px] z-0"
+        style={{ backgroundColor: content.bgColor }}
+      />
+
+      {/* Hero Image */}
+      <div className="w-full max-w-7xl mx-auto pt-6 sm:pt-8 px-4 sm:px-6 lg:px-8">
+        <div className="relative w-full aspect-[3/1.4] sm:aspect-[3/1.2] md:aspect-[3/1.1] lg:aspect-[3/1.1] rounded-xl overflow-hidden shadow-md">
+          <Image
+            src="https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png"
path: src/app/(home)/(common)/layout.tsx
user: login: ayussh-2
body: EXPORT THIS FROM CONFIG FILE ALSO THIS WOULD BE DIFFRENT FOR EACH PAGE
created_at: 2025-05-09T08:00:23Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+'use client';
+import React from 'react';
+import { usePathname } from 'next/navigation';
+import { Inter } from 'next/font/google';
+import Image from 'next/image';
+
+const inter = Inter({ subsets: ['latin'] });
+
+export default function PublicLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  const pathname = usePathname();
+  const content = pageContent[pathname as keyof typeof pageContent];
+
+  if (!content) return <>{children}</>;
+
+  return (
+    <div className="relative overflow-hidden bg-white">
+      {/* Background Circle */}
+      <div
+        className="absolute w-[300px] h-[300px] sm:w-[400px] sm:h-[400px] md:w-[500px] md:h-[500px] lg:w-[600px] lg:h-[600px] rounded-full top-[300px] left-[-120px] z-0"
+        style={{ backgroundColor: content.bgColor }}
+      />
+
+      {/* Hero Image */}
+      <div className="w-full max-w-7xl mx-auto pt-6 sm:pt-8 px-4 sm:px-6 lg:px-8">
+        <div className="relative w-full aspect-[3/1.4] sm:aspect-[3/1.2] md:aspect-[3/1.1] lg:aspect-[3/1.1] rounded-xl overflow-hidden shadow-md">
+          <Image
+            src="https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png"
+            alt="Event Hero"
+            fill
+            className="object-cover rounded-xl"
+            priority
+          />
+          <div className="absolute inset-0 bg-gradient-to-t from-black/70 to-white/20 rounded-xl" />
+        </div>
+      </div>
+
+      {/* Heading + Subtext Block */}
+      <div className="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 sm:py-12 z-10 relative">
+        <div className="bg-white shadow-md px-4 sm:px-6 lg:px-10 py-6 sm:py-8 flex flex-col sm:flex-row justify-between items-center lg:items-center border-y-2 border-black font-productsans text-black gap-6 lg:gap-0">
+          <h2 className="text-3xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-bold text-[#313131]">
+            {content.title}
+          </h2>
+          <p className="text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl leading-relaxed sm:mt-2 lg:mt-0 max-w-xl text-left">
+            {content.description}
+          </p>
+        </div>
+      </div>
+
+      {/* Children */}
+      <div className={inter.className}>
+        <main className="px-4 sm:px-6 lg:px-8 relative z-20">{children}</main>
+      </div>
+    </div>
+  );
+}
+
+export const pageContent = {
path: src/app/(home)/(common)/layout.tsx
user: login: ayussh-2
body: MOVE THIS TO CONFIG FOLDER
created_at: 2025-05-09T08:01:10Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,63 @@
+'use client';
+import React from 'react';
+import EventsCard from '@/components/events/EventsCard';
+
+function page() {
+  return (
+    <div className="relative overflow-hidden ">
+      {/* Event Cards */}
+      <div className="w-full space-y-12 px-4 sm:px-8 max-w-7xl mx-auto pb-16">
+        {events.map((event, index) => (
+          <EventsCard
+            key={event.id}
+            id={event.id}
+            heading={event.heading}
+            title={event.title}
+            date={event.date}
+            description={event.description}
+            imageUrl={event.imageUrl}
+            cardBgColor={event.cardBgColor}
+          />
+        ))}
+      </div>
+    </div>
+  );
+}
+
+export default page;
+
+const events = [
path: src/app/(home)/(common)/events/page.tsx
user: login: ayussh-2
body: MOVE TO CONFIG
created_at: 2025-05-09T08:02:15Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+'use client';
+import React from 'react';
+import { usePathname } from 'next/navigation';
+import { Inter } from 'next/font/google';
+import Image from 'next/image';
+
+const inter = Inter({ subsets: ['latin'] });
+
+export default function PublicLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  const pathname = usePathname();
+  const content = pageContent[pathname as keyof typeof pageContent];
+
+  if (!content) return <>{children}</>;
+
+  return (
+    <div className="relative overflow-hidden bg-white">
+      {/* Background Circle */}
+      <div
path: src/app/(home)/(common)/layout.tsx
user: login: ayussh-2
body: MAKE THE CIRCLE AS A COMPONENT
created_at: 2025-05-09T08:02:49Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+'use client';
+import React from 'react';
+import { usePathname } from 'next/navigation';
+import { Inter } from 'next/font/google';
+import Image from 'next/image';
+
+const inter = Inter({ subsets: ['latin'] });
+
+export default function PublicLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  const pathname = usePathname();
+  const content = pageContent[pathname as keyof typeof pageContent];
+
+  if (!content) return <>{children}</>;
+
+  return (
+    <div className="relative overflow-hidden bg-white">
+      {/* Background Circle */}
+      <div
+        className="absolute w-[300px] h-[300px] sm:w-[400px] sm:h-[400px] md:w-[500px] md:h-[500px] lg:w-[600px] lg:h-[600px] rounded-full top-[300px] left-[-120px] z-0"
+        style={{ backgroundColor: content.bgColor }}
+      />
+
+      {/* Hero Image */}
+      <div className="w-full max-w-7xl mx-auto pt-6 sm:pt-8 px-4 sm:px-6 lg:px-8">
path: src/app/(home)/(common)/layout.tsx
user: login: ayussh-2
body: HERO IMAGE AND HEADING A COMPONENT
created_at: 2025-05-09T08:03:24Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+'use client';
+import React from 'react';
+import { usePathname } from 'next/navigation';
+import { Inter } from 'next/font/google';
+import Image from 'next/image';
+
+const inter = Inter({ subsets: ['latin'] });
+
+export default function PublicLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  const pathname = usePathname();
+  const content = pageContent[pathname as keyof typeof pageContent];
+
+  if (!content) return <>{children}</>;
+
+  return (
+    <div className="relative overflow-hidden bg-white">
+      {/* Background Circle */}
+      <div
+        className="absolute w-[300px] h-[300px] sm:w-[400px] sm:h-[400px] md:w-[500px] md:h-[500px] lg:w-[600px] lg:h-[600px] rounded-full top-[300px] left-[-120px] z-0"
+        style={{ backgroundColor: content.bgColor }}
+      />
+
+      {/* Hero Image */}
+      <div className="w-full max-w-7xl mx-auto pt-6 sm:pt-8 px-4 sm:px-6 lg:px-8">
+        <div className="relative w-full aspect-[3/1.4] sm:aspect-[3/1.2] md:aspect-[3/1.1] lg:aspect-[3/1.1] rounded-xl overflow-hidden shadow-md">
+          <Image
+            src="https://res.cloudinary.com/dpmlrxlzr/image/upload/v1746378087/hn_50_1_ru18tc.png"
+            alt="Event Hero"
+            fill
+            className="object-cover rounded-xl"
+            priority
+          />
+          <div className="absolute inset-0 bg-gradient-to-t from-black/70 to-white/20 rounded-xl" />
+        </div>
+      </div>
+
+      {/* Heading + Subtext Block */}
+      <div className="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 sm:py-12 z-10 relative">
+        <div className="bg-white shadow-md px-4 sm:px-6 lg:px-10 py-6 sm:py-8 flex flex-col sm:flex-row justify-between items-center lg:items-center border-y-2 border-black font-productsans text-black gap-6 lg:gap-0">
+          <h2 className="text-3xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-bold text-[#313131]">
+            {content.title}
+          </h2>
+          <p className="text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl leading-relaxed sm:mt-2 lg:mt-0 max-w-xl text-left">
+            {content.description}
+          </p>
+        </div>
+      </div>
+
+      {/* Children */}
+      <div className={inter.className}>
path: src/app/(home)/(common)/layout.tsx
user: login: ayussh-2
body: NO NEED OF INTER.CLASSNAME HERE

created_at: 2025-05-09T08:03:45Z
author_association: COLLABORATOR

PR comments:
user: login: netlify[bot]
created_at: 2025-05-09T05:06:34Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *gdsc-nitr* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 131a3efb928aa09a298e0177a0ee74373e58c75a |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/projects/gdsc-nitr/deploys/681dbfdcb64714000883aba0 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-49--gdsc-nitr.netlify.app](https://deploy-preview-49--gdsc-nitr.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTQ5LS1nZHNjLW5pdHIubmV0bGlmeS5hcHAifQ.r-JAq90TG7c61_GzHsyfuVROF6ktYBo7-g95nSdirDU)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [gdsc-nitr Preview](https://deploy-preview-49--gdsc-nitr.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify project configuration](https://app.netlify.com/projects/gdsc-nitr/configuration/notifications#deploy-notifications)._
author_association: NONE
user: login: ayussh-2
created_at: 2025-05-09T09:01:59Z
body: @all-contributors please add @BlessedAmrita for code

author_association: COLLABORATOR
user: login: allcontributors[bot]
created_at: 2025-05-09T09:02:09Z
body: @ayussh-2 

I've put up [a pull request](https://github.com/dscnitrourkela/project-huckleberry/pull/51) to add @BlessedAmrita! :tada:
author_association: CONTRIBUTOR