From 5bcd4a0e21556dd84935bfd725c2eabfe244b01f Mon Sep 17 00:00:00 2001 From: Zeeshan Adil Date: Sun, 1 Nov 2026 23:00:25 +0500 Subject: [PATCH 1/2] feat(feed): add an API for the latest member posts --- app/api/feed/latest/route.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 app/api/feed/latest/route.ts diff --git a/app/api/feed/latest/route.ts b/app/api/feed/latest/route.ts new file mode 100644 index 0000000..41bd3b9 --- /dev/null +++ b/app/api/feed/latest/route.ts @@ -0,0 +1,20 @@ +import { NextResponse } from 'next/server'; +import { getFeedPosts } from '@/lib/linkedin-feed'; +import { OFFICIAL_HANDLES } from '@/lib/linkedin-feed-shared'; + +// Read at request time (the build has no database), then cached at the edge. +export const dynamic = 'force-dynamic'; + +/** Posts shown in the feed rail on the homepage; the full wall is /feed */ +const RAIL_SIZE = 10; + +// GET: the latest member posts with an excerpt, for the feed rail under Fellow voices +export async function GET() { + const posts = await getFeedPosts(); + const latest = posts + .filter((post) => !OFFICIAL_HANDLES.has(post.handle) && post.excerpt.trim()) + .slice(0, RAIL_SIZE); + return NextResponse.json(latest, { + headers: { 'Cache-Control': 'public, s-maxage=600, stale-while-revalidate=86400' }, + }); +} From 0b6becd1de3631586edd87ea9783bf11381aa6cd Mon Sep 17 00:00:00 2001 From: Zeeshan Adil Date: Sun, 1 Nov 2026 23:00:26 +0500 Subject: [PATCH 2/2] feat(home): show community feed posts in a rail under Fellow voices --- components/home/feed-rail.tsx | 125 ++++++++++++++++++++++++++++ components/home/sections-bottom.tsx | 2 + 2 files changed, 127 insertions(+) create mode 100644 components/home/feed-rail.tsx diff --git a/components/home/feed-rail.tsx b/components/home/feed-rail.tsx new file mode 100644 index 0000000..543a265 --- /dev/null +++ b/components/home/feed-rail.tsx @@ -0,0 +1,125 @@ +"use client" + +import { useEffect, useRef, useState } from "react" +import Link from "next/link" +import { ArrowLeft, ArrowRight, ArrowUpRight } from "lucide-react" + +import { FEED_TOPICS, type FeedPost } from "@/lib/linkedin-feed-shared" + +const dateFormat = new Intl.DateTimeFormat("en-GB", { day: "numeric", month: "short", year: "numeric", timeZone: "UTC" }) + +function initials(name: string) { + return name + .split(" ") + .filter(Boolean) + .slice(0, 2) + .map((word) => word[0]) + .join("") + .toUpperCase() +} + +/** + * Feed rail: the latest member posts from the /feed wall, under Fellow voices. + * Each card opens the post on LinkedIn and the last card opens the full wall. + * Renders nothing until posts load, so the section never shows an empty rail. + */ +export function FeedRail() { + const rail = useRef(null) + const [posts, setPosts] = useState([]) + + useEffect(() => { + fetch("/api/feed/latest") + .then((res) => (res.ok ? res.json() : [])) + .then((data) => setPosts(Array.isArray(data) ? data : [])) + .catch(() => setPosts([])) + }, []) + + if (posts.length === 0) return null + + const scrollBy = (direction: 1 | -1) => { + const el = rail.current + if (!el) return + el.scrollBy({ left: direction * Math.max(320, el.clientWidth * 0.8), behavior: "smooth" }) + } + + return ( +
+
+
+

Community feed

+

Shared on LinkedIn with #DevWeekends.

+
+
+ + See all posts → + + + +
+
+ + +
+ ) +} diff --git a/components/home/sections-bottom.tsx b/components/home/sections-bottom.tsx index 64b33dc..97f0a85 100644 --- a/components/home/sections-bottom.tsx +++ b/components/home/sections-bottom.tsx @@ -2,6 +2,7 @@ import { ArrowUpRight } from "lucide-react" import { SmartLink } from "./smart-link" import { LogoMark } from "./logo-mark" +import { FeedRail } from "./feed-rail" import { VoicesRail } from "./voices" import { LINKS, @@ -190,6 +191,7 @@ export function Voices() { return (
+
) }