From e2a2af8a6fb281ceaa1053036ec34bcc00b0e9d9 Mon Sep 17 00:00:00 2001 From: Sean Date: Mon, 30 Mar 2026 16:33:53 -0400 Subject: [PATCH] feat: add changelog/roadmap types, Sanity queries, and public route whitelist --- lib/sanity.ts | 16 ++++++++++++++++ middleware.ts | 4 ++++ types/changelog.ts | 24 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 types/changelog.ts diff --git a/lib/sanity.ts b/lib/sanity.ts index c1c9b3e..ad0e45e 100644 --- a/lib/sanity.ts +++ b/lib/sanity.ts @@ -55,3 +55,19 @@ export const postBySlugQuery = ` export const postSlugsQuery = ` *[_type == "post" && defined(slug.current)] { "slug": slug.current } ` + +/** All changelog entries — published, newest first */ +export const changelogEntriesQuery = ` + *[_type == "changelogEntry" && publishedAt <= now()] + | order(publishedAt desc) { + _id, title, version, publishedAt, tags, body + } +` + +/** Roadmap items — excludes shipped, sorted by manual order */ +export const roadmapItemsQuery = ` + *[_type == "roadmapItem" && status != "shipped"] + | order(order asc) { + _id, title, description, status, order + } +` diff --git a/middleware.ts b/middleware.ts index bc1dae2..9194df3 100644 --- a/middleware.ts +++ b/middleware.ts @@ -25,6 +25,10 @@ function isPublicPath(pathname: string) { if (pathname === "/guides") return true; if (pathname.startsWith("/guides/")) return true; + // Changelog and feedback — always public + if (pathname === "/changelog") return true; + if (pathname === "/feedback") return true; + // Static / framework assets if (pathname.startsWith("/_next")) return true; if (pathname === "/favicon.ico") return true; diff --git a/types/changelog.ts b/types/changelog.ts new file mode 100644 index 0000000..77cd23c --- /dev/null +++ b/types/changelog.ts @@ -0,0 +1,24 @@ +export type ChangelogEntry = { + _id: string + title: string + version: string + publishedAt: string + tags: string[] + body: unknown[] +} + +export type RoadmapItemData = { + _id: string + title: string + description: string + status: 'planned' | 'in-progress' + order: number +} + +export type Tab = 'whats-new' | 'whats-next' | 'give-feedback' + +export type VoteState = { + count: number + voted: boolean + loading: boolean +}