Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions app/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,44 @@
.border-brand-orange {
border-color: var(--brand-orange);
}

/* Masonry scroll animations */
@keyframes scroll-up {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-50%);
}
}

.animate-scroll-slow {
animation: scroll-up 80s linear infinite;
}

.animate-scroll-medium {
animation: scroll-up 70s linear infinite;
}

.animate-scroll-fast {
animation: scroll-up 60s linear infinite;
}

.animate-scroll-slower {
animation: scroll-up 90s linear infinite;
}

.animate-scroll-faster {
animation: scroll-up 50s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
.animate-scroll-slow,
.animate-scroll-medium,
.animate-scroll-fast,
.animate-scroll-slower,
.animate-scroll-faster {
animation: none;
}
}
}
214 changes: 182 additions & 32 deletions app/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,40 +251,190 @@ export default async function HomePage() {
}

function LandingHero({ images }: { images: Image[] }) {
// Distribute images across columns for masonry effect
const distributeImagesAcrossColumns = (images: Image[], columnCount: number) => {
const columns: Image[][] = Array.from({ length: columnCount }, () => []);

images.forEach((image, index) => {
const columnIndex = index % columnCount;
columns[columnIndex].push(image);
});

return columns;
};

// Create different column counts for different screen sizes
// We'll use CSS to show/hide columns based on screen size
const desktopColumns = distributeImagesAcrossColumns(images, 4);
const tabletColumns = distributeImagesAcrossColumns(images, 3);
const mobileColumns = distributeImagesAcrossColumns(images, 2);

// Animation speed classes for each column
const animationSpeeds = [
'animate-scroll-slow',
'animate-scroll-medium',
'animate-scroll-fast',
'animate-scroll-slower'
];

return (
<section className="w-full h-[80vh] overflow-hidden grid [&>*]:col-[1] [&>*]:row-[1]">
<div className="w-full h-full grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-1">
{images.map((image, index) => (
<div
key={image.url + index}
className="relative w-full aspect-square overflow-hidden"
>
<NextImage
src={image.url}
placeholder={image.placeholder ? "blur" : undefined}
blurDataURL={image.placeholder || undefined}
fill
className="object-cover"
priority
alt={image.alt || `Event image ${index + 1}`}
sizes="(max-width: 768px) 50vw, (max-width: 1024px) 33vw, (max-width: 1280px) 25vw, 20vw"
/>
</div>
))}
</div>
<section className="relative w-full h-[80vh] overflow-hidden">
{/* Desktop Layout - 4 columns */}
<div className="absolute inset-0 hidden lg:grid grid-cols-4 gap-1">
{desktopColumns.map((columnImages, columnIndex) => (
<div
key={`desktop-column-${columnIndex}`}
className={`flex flex-col gap-1 ${animationSpeeds[columnIndex]}`}
>
{/* First set of images */}
{columnImages.map((image, index) => (
<div
key={`${image.url}-${index}-1`}
className="relative w-full"
style={{ aspectRatio: `${image.width}/${image.height}` }}
>
<NextImage
src={image.url}
placeholder={image.placeholder ? "blur" : undefined}
blurDataURL={image.placeholder || undefined}
fill
className="object-cover"
priority={index < 5}
alt={image.alt || `Event image ${index + 1}`}
Comment on lines +324 to +325
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Excessive Next/Image priority preloads (up to ~20 on desktop).

This will tank LCP and bandwidth. Only one (or none) should be priority.

- priority={index < 5}
+ priority={columnIndex === 0 && index === 0}

Consider making all background images non‑priority if text is LCP.

Also applies to: 350-351, 398-399

🤖 Prompt for AI Agents
In app/src/app/page.tsx around lines 302-303 (and similarly at 350-351,
398-399), multiple Next/Image components are being marked priority causing
excessive preloads; change the logic so only a single image (e.g., the first
hero or index === 0) has priority (or remove priority entirely for background
images when text is expected to be LCP). Update the conditional from index < 5
to something like index === 0 (or false for background images), and apply the
same change at the other listed locations so only one image is priority and
background images are non-priority.

sizes="25vw"
/>
</div>
))}
{/* Duplicate set for seamless loop */}
{columnImages.map((image, index) => (
<div
key={`${image.url}-${index}-2`}
className="relative w-full"
style={{ aspectRatio: `${image.width}/${image.height}` }}
>
<NextImage
src={image.url}
placeholder={image.placeholder ? "blur" : undefined}
blurDataURL={image.placeholder || undefined}
fill
className="object-cover"
alt={image.alt || `Event image ${index + 1}`}
sizes="25vw"
/>
</div>
))}
</div>
))}
</div>

{/* Content */}
<div className="z-20 bg-gradient-to-b from-black/70 to-black/30 flex flex-col items-center pt-[30vh] text-center text-white px-4">
<h1 className="mb-4 text-4xl sm:text-5xl md:text-6xl font-bold tracking-tight">
All Things Web 🚀
</h1>
<p className="max-w-2xl text-lg sm:text-xl">
Discover exciting web development events in the Bay Area and San
Francisco. Join us for hackathons, hangouts, and meetups to connect
with fellow developers and web enthusiasts.
</p>
</div>
</section>
{/* Tablet Layout - 3 columns */}
<div className="absolute inset-0 hidden md:grid lg:hidden grid-cols-3 gap-1">
{tabletColumns.map((columnImages, columnIndex) => (
<div
key={`tablet-column-${columnIndex}`}
className={`flex flex-col gap-1 ${animationSpeeds[columnIndex]}`}
>
{/* First set of images */}
{columnImages.map((image, index) => (
<div
key={`${image.url}-${index}-1`}
className="relative w-full"
style={{ aspectRatio: `${image.width}/${image.height}` }}
>
<NextImage
src={image.url}
placeholder={image.placeholder ? "blur" : undefined}
blurDataURL={image.placeholder || undefined}
fill
className="object-cover"
priority={index < 3}
alt={image.alt || `Event image ${index + 1}`}
sizes="33vw"
/>
</div>
))}
{/* Duplicate set for seamless loop */}
{columnImages.map((image, index) => (
<div
key={`${image.url}-${index}-2`}
className="relative w-full"
style={{ aspectRatio: `${image.width}/${image.height}` }}
>
<NextImage
src={image.url}
placeholder={image.placeholder ? "blur" : undefined}
blurDataURL={image.placeholder || undefined}
fill
className="object-cover"
alt={image.alt || `Event image ${index + 1}`}
sizes="33vw"
/>
</div>
))}
</div>
))}
</div>

{/* Mobile Layout - 2 columns */}
<div className="absolute inset-0 grid md:hidden grid-cols-2 gap-1">
{mobileColumns.map((columnImages, columnIndex) => (
<div
key={`mobile-column-${columnIndex}`}
className={`flex flex-col gap-1 ${animationSpeeds[columnIndex]}`}
>
{/* First set of images */}
{columnImages.map((image, index) => (
<div
key={`${image.url}-${index}-1`}
className="relative w-full"
style={{ aspectRatio: `${image.width}/${image.height}` }}
>
<NextImage
src={image.url}
placeholder={image.placeholder ? "blur" : undefined}
blurDataURL={image.placeholder || undefined}
fill
className="object-cover"
priority={index < 2}
alt={image.alt || `Event image ${index + 1}`}
sizes="50vw"
/>
</div>
))}
{/* Duplicate set for seamless loop */}
{columnImages.map((image, index) => (
<div
key={`${image.url}-${index}-2`}
className="relative w-full"
style={{ aspectRatio: `${image.width}/${image.height}` }}
>
<NextImage
src={image.url}
placeholder={image.placeholder ? "blur" : undefined}
blurDataURL={image.placeholder || undefined}
fill
className="object-cover"
alt={image.alt || `Event image ${index + 1}`}
sizes="50vw"
/>
</div>
))}
</div>
))}
</div>

{/* Content Overlay */}
<div className="absolute inset-0 z-20 bg-gradient-to-b from-black/70 to-black/30 flex flex-col items-center justify-center text-center text-white px-4">
<h1 className="mb-4 text-4xl sm:text-5xl md:text-6xl font-bold tracking-tight">
All Things Web 🚀
</h1>
<p className="max-w-2xl text-lg sm:text-xl">
Discover exciting web development events in the Bay Area and San
Francisco. Join us for hackathons, hangouts, and meetups to connect
with fellow developers and web enthusiasts.
</p>
</div>
</section>
);
}

Expand Down