import Link from "next/link"; import type { Metadata } from "next"; import { getAllPosts } from "@/lib/devblog"; import { games as gameRegistry } from "@/lib/games"; import { Newsletter } from "../components/Newsletter"; export const metadata: Metadata = { title: "Devblog", description: "Behind-the-scenes updates, design decisions, and milestones from Highland Games Studio.", }; const PAGE_SIZE = 10; function formatDate(date: string) { return new Date(date).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", }); } function buildHref(params: { game?: string; page?: number }) { const search = new URLSearchParams(); if (params.game) search.set("game", params.game); if (params.page && params.page > 1) search.set("page", String(params.page)); const qs = search.toString(); return qs ? `/devblog?${qs}` : "/devblog"; } type Props = { searchParams: Promise<{ game?: string; page?: string }>; }; export default async function DevblogPage({ searchParams }: Props) { const { game, page } = await searchParams; const allPosts = getAllPosts(); const usedGameSlugs = Array.from( new Set(allPosts.map((p) => p.game).filter((g): g is string => Boolean(g))), ); const gameOptions = usedGameSlugs .map((slug) => ({ slug, title: gameRegistry.find((g) => g.slug === slug)?.title ?? slug, })) .sort((a, b) => a.title.localeCompare(b.title)); const filtered = allPosts.filter((p) => { if (game && p.game !== game) return false; return true; }); const currentPage = Math.max(1, parseInt(page ?? "1", 10) || 1); const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE)); const safePage = Math.min(currentPage, totalPages); const visible = filtered.slice( (safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE, ); return (
— DEVBLOG
Honest updates from the studio. Design decisions, prototypes, art milestones everything that goes into building our worlds.
{gameOptions.length > 0 && ({game ? "No posts match these filters yet." : "No posts yet. Check back soon."}
) : ({post.excerpt}
)} {postGame && (— NEWSLETTER
Subscribe to get devblog highlights and release news in your inbox.