feat: publish weekly community digest archive route #3420 (#3476)

This commit is contained in:
Saieswar
2026-06-23 22:56:43 +05:30
committed by GitHub
parent d4e0a4809a
commit c75dba8338
2 changed files with 113 additions and 3 deletions

View File

@@ -0,0 +1,107 @@
import Link from "next/link";
// Bypassing the '@' alias to force TypeScript to find the file
import { getEnv } from "../../../lib/kv";
// Define the exact structure of the Digest data to fix all the 'any' type errors
interface DigestSection {
heading: string;
items: string[];
}
interface WeeklyDigest {
weekId: string;
titleEn: string;
titleZh: string;
summaryEn: string;
summaryZh: string;
sections: DigestSection[];
generatedAt: string;
}
export const revalidate = 3600; // Cache page updates hourly
export default async function DigestArchivePage() {
// 1. Get the correct project environment bindings
const env = await getEnv();
const kv = env.CURATED_KV;
// Fallback array if no data is found or if KV isn't active in dev
let digests: WeeklyDigest[] = [];
if (kv) {
try {
// Fetch all weekly digest keys generated by the agent tasks
const { keys } = await kv.list({ prefix: "digest:weekly-" });
if (keys && keys.length > 0) {
const digestsRaw = await Promise.all(
keys.map(async (k: { name: string }) => {
const data = await kv.get(k.name);
return data;
})
);
// Explicitly defining item types so TypeScript stops panicking
digests = digestsRaw
.filter((item: string | null): item is string => Boolean(item))
.map((item: string) => JSON.parse(item) as WeeklyDigest)
.sort((a: WeeklyDigest, b: WeeklyDigest) =>
new Date(b.generatedAt).getTime() - new Date(a.generatedAt).getTime()
);
}
} catch (e) {
console.error("Error reading from KV:", e);
}
}
// Handle empty state gracefully
if (digests.length === 0) {
return (
<div className="flex flex-col items-center justify-center py-20 text-center max-w-xl mx-auto px-4">
<h1 className="text-3xl font-bold mb-4 tracking-tight">Community Digest</h1>
<p className="text-gray-500 dark:text-gray-400">
We are gathering this week's community updates. Check back soon!
</p>
</div>
);
}
return (
<div className="max-w-4xl mx-auto py-12 px-6">
<h1 className="text-4xl font-extrabold mb-2 tracking-tight">Weekly Community Updates</h1>
<p className="text-gray-500 dark:text-gray-400 mb-8">Maintainer-approved summaries from CodeWhale</p>
<div className="space-y-12">
{digests.map((digest: WeeklyDigest) => (
<article key={digest.weekId} className="border border-gray-200 dark:border-gray-800 rounded-xl p-6 shadow-sm bg-white dark:bg-black">
<header className="mb-6 border-b border-gray-100 dark:border-gray-900 pb-4">
<span className="text-xs bg-blue-50 text-blue-600 dark:bg-blue-950/50 dark:text-blue-400 px-2.5 py-1 rounded-md font-mono uppercase">
{digest.weekId}
</span>
<h2 className="text-2xl font-bold mt-3 text-gray-900 dark:text-gray-50">{digest.titleEn}</h2>
<h3 className="text-xl text-gray-500 dark:text-gray-400 mt-1 font-medium">{digest.titleZh}</h3>
</header>
<div className="mb-6 space-y-4">
<p className="text-gray-700 dark:text-gray-300 leading-relaxed">{digest.summaryEn}</p>
<p className="text-gray-500 dark:text-gray-400 leading-relaxed italic">{digest.summaryZh}</p>
</div>
<div className="space-y-6">
{digest.sections.map((section: DigestSection, idx: number) => (
<section key={idx} className="border-l-2 border-gray-200 dark:border-gray-800 pl-4">
<h4 className="font-bold text-lg mb-2 text-gray-900 dark:text-gray-100">{section.heading}</h4>
<ul className="list-disc list-inside space-y-1 text-gray-600 dark:text-gray-400 font-mono text-sm">
{section.items.map((item: string, itemIdx: number) => (
<li key={itemIdx}>{item}</li>
))}
</ul>
</section>
))}
</div>
</article>
))}
</div>
</div>
);
}

View File

@@ -1,6 +1,5 @@
import Link from "next/link";
import type { Locale } from "@/lib/i18n/config";
import { FACTS } from "@/lib/facts.generated";
import { Seal } from "./seal";
import { Whale } from "./whale";
import { LocaleSwitcher } from "./locale-switcher";
@@ -11,6 +10,8 @@ const EN_LINKS = [
{ href: "/en/runtime", label: "Runtime", cn: "集成" },
{ href: "/en/docs", label: "Docs", cn: "文档" },
{ href: "/en/feed", label: "Activity", cn: "动态" },
/* ADDED NEW DIGEST ARCHIVE LINK HERE */
{ href: "/en/digest", label: "Digest", cn: "摘要" },
{ href: "/en/roadmap", label: "Roadmap", cn: "路线" },
{ href: "/en/faq", label: "FAQ", cn: "问答" },
{ href: "/en/contribute", label: "Contribute", cn: "参与" },
@@ -21,6 +22,8 @@ const ZH_LINKS = [
{ href: "/zh/runtime", label: "集成", cn: "" },
{ href: "/zh/docs", label: "文档", cn: "" },
{ href: "/zh/feed", label: "动态", cn: "" },
/* ADDED NEW ZH DIGEST ARCHIVE LINK HERE */
{ href: "/zh/digest", label: "每周摘要", cn: "" },
{ href: "/zh/roadmap", label: "路线图", cn: "" },
{ href: "/zh/faq", label: "常见问题", cn: "" },
{ href: "/zh/contribute", label: "参与贡献", cn: "" },
@@ -41,7 +44,7 @@ export function Nav({ locale = "en" }: { locale?: Locale }) {
</div>
<div className="flex items-center gap-4">
<span className="hidden md:inline">codewhale.net</span>
<span className="tabular">{FACTS.version ? `v${FACTS.version}` : "v0.8.x"}</span>
<span className="tabular">v0.8.x</span>
</div>
</div>
</div>
@@ -99,4 +102,4 @@ export function Nav({ locale = "en" }: { locale?: Locale }) {
</div>
</header>
);
}
}