@@ -158,16 +164,9 @@ export function HeroSection({
>
diff --git a/app/src/lib/event-hero.ts b/app/src/lib/event-hero.ts
new file mode 100644
index 0000000..aab8213
--- /dev/null
+++ b/app/src/lib/event-hero.ts
@@ -0,0 +1,26 @@
+import type { Image } from "./events";
+
+export function getEventHeroImage(event: {
+ previewImage: Image | null;
+ images: Image[];
+ isHackathon: boolean;
+}): Image {
+ // The event loader supplies this generic preview when no cover is stored.
+ if (
+ event.previewImage &&
+ event.previewImage.url !== "/hero-image-rocket.png"
+ ) {
+ return event.previewImage;
+ }
+ if (event.images.length > 0) return event.images[0];
+ return {
+ url: event.isHackathon
+ ? "/hero-image-hackathon.png"
+ : "/hero-image-meetup.png",
+ alt: event.isHackathon
+ ? "Illustration of developers celebrating at a hackathon"
+ : "Illustration of developers chatting at a meetup",
+ width: 1200,
+ height: 1200,
+ };
+}
diff --git a/app/tests/event-hero.test.ts b/app/tests/event-hero.test.ts
new file mode 100644
index 0000000..9c56a6e
--- /dev/null
+++ b/app/tests/event-hero.test.ts
@@ -0,0 +1,38 @@
+import { expect, test } from "bun:test";
+import { getEventHeroImage } from "../src/lib/event-hero";
+const cover = {
+ url: "/cover.png",
+ alt: "Event poster",
+ width: 800,
+ height: 400,
+};
+const photo = { url: "/photo.png", alt: "People building together" };
+test("uses the event cover, retaining its description and dimensions", () => {
+ expect(
+ getEventHeroImage({
+ previewImage: cover,
+ images: [photo],
+ isHackathon: false,
+ }),
+ ).toEqual(cover);
+});
+test("uses an event photo when the cover is absent or the loader's generic placeholder", () => {
+ for (const previewImage of [
+ null,
+ { url: "/hero-image-rocket.png", alt: "Fallback" },
+ ]) {
+ expect(
+ getEventHeroImage({ previewImage, images: [photo], isHackathon: false }),
+ ).toEqual(photo);
+ }
+});
+test("retains distinct meetup and hackathon fallbacks without inventing event media", () => {
+ expect(
+ getEventHeroImage({ previewImage: null, images: [], isHackathon: false })
+ .url,
+ ).toBe("/hero-image-meetup.png");
+ expect(
+ getEventHeroImage({ previewImage: null, images: [], isHackathon: true })
+ .url,
+ ).toBe("/hero-image-hackathon.png");
+});