From 9d0eb40554271b6b99b120b6ad230ceb996cf3fc Mon Sep 17 00:00:00 2001 From: Sean Date: Mon, 30 Mar 2026 10:57:36 -0400 Subject: [PATCH] docs: add changelog, roadmap, and feedback design spec --- .../2026-03-30-changelog-feedback-design.md | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 docs/superpowers/specs/2026-03-30-changelog-feedback-design.md diff --git a/docs/superpowers/specs/2026-03-30-changelog-feedback-design.md b/docs/superpowers/specs/2026-03-30-changelog-feedback-design.md new file mode 100644 index 0000000..dd41fcc --- /dev/null +++ b/docs/superpowers/specs/2026-03-30-changelog-feedback-design.md @@ -0,0 +1,205 @@ +# Changelog, Roadmap & Feedback Design Spec + +**Date:** 2026-03-30 +**Status:** Approved + +--- + +## Overview + +Add a public `/changelog` page with three tabs (What's New, What's Next, Give Feedback), auth-gated upvoting on roadmap items, a shared feedback form available as a standalone page and a modal triggered from the nav/footer, and an admin view for reviewing submissions. + +--- + +## Goals + +- Publicly share release notes (changelog) and upcoming work (roadmap) +- Let authenticated users upvote roadmap items to signal priority +- Collect structured user feedback (bug / feature / general) with optional email +- Store feedback in Spring Boot DB, reviewable in the admin panel +- Add "Send Feedback" entry point to TopNav and homepage footer + +--- + +## Routes + +| Route | Description | +|---|---| +| `/changelog` | Three-tab page: What's New / What's Next / Give Feedback | +| `/feedback` | Standalone feedback page — full-width `FeedbackForm` | +| `/admin/feedback` | Admin table of feedback submissions | + +Tab state on `/changelog` is driven by URL hash (`#whats-new`, `#whats-next`, `#give-feedback`) so tabs are deep-linkable. The "Don't see what you need? Give us feedback →" nudge on the roadmap tab links to `#give-feedback`. + +--- + +## Sanity Schema (two new document types) + +### `changelogEntry` + +| Field | Type | Notes | +|---|---|---| +| `title` | string | Display title of the release | +| `version` | string | e.g. `v0.4` | +| `publishedAt` | datetime | Controls ordering and display date | +| `tags` | array of string | Values: `feature`, `fix`, `improvement` | +| `body` | Portable Text | Rich text body | + +### `roadmapItem` + +| Field | Type | Notes | +|---|---|---| +| `title` | string | Short item title | +| `description` | text | Plain-text description | +| `status` | string enum | `planned` \| `in-progress` \| `shipped` | +| `order` | number | Manual sort order within each status group | + +Both use the existing Sanity project (`zal102rv`, dataset `production`). GROQ queries added to `lib/sanity.ts` alongside existing `postsQuery`. Pages use `revalidate = 60` ISR, consistent with guides. + +The Sanity `_id` of each `roadmapItem` serves as the foreign key in Spring Boot's votes table — no additional ID field required. + +--- + +## Spring Boot Backend + +### New Tables + +**`feedback`** + +| Column | Type | Notes | +|---|---|---| +| `id` | UUID, PK | | +| `category` | enum | `BUG`, `FEATURE_REQUEST`, `GENERAL` | +| `message` | text | Max 1000 chars, enforced at API level | +| `email` | varchar, nullable | Optional follow-up email | +| `ip_address` | varchar | Captured server-side for spam visibility | +| `user_agent` | varchar | Captured server-side for spam visibility | +| `reviewed` | boolean, default false | Admin marks reviewed | +| `created_at` | timestamp | | + +**`roadmap_votes`** + +| Column | Type | Notes | +|---|---|---| +| `user_id` | UUID, FK → users | | +| `sanity_item_id` | varchar | Sanity `_id` of the roadmap item | +| `created_at` | timestamp | | +| | UNIQUE(user_id, sanity_item_id) | DB-enforced one vote per user per item | + +### New API Endpoints (Spring Boot) + +| Method | Path | Auth | Notes | +|---|---|---|---| +| `POST` | `/api/v1/feedback` | None | Creates feedback record; captures IP + user agent server-side | +| `GET` | `/api/v1/roadmap/votes?ids=...` | Optional | Returns vote counts + current user's voted state for a list of Sanity IDs | +| `POST` | `/api/v1/roadmap/{sanityId}/vote` | Required | Toggles vote on/off; returns new count and voted state | + +### Next.js Proxy Routes + +All three endpoints are proxied via `app/api/` — client code never calls Spring Boot directly, consistent with the existing proxy pattern. + +| Next.js route | Proxies to | +|---|---| +| `POST /api/feedback` | `POST /api/v1/feedback` | +| `GET /api/roadmap/votes` | `GET /api/v1/roadmap/votes` | +| `POST /api/roadmap/[sanityId]/vote` | `POST /api/v1/roadmap/:id/vote` | + +--- + +## Frontend Components + +### New Files + +| File | Type | Responsibility | +|---|---|---| +| `app/(app)/changelog/page.tsx` | RSC | Fetches Sanity changelog + roadmap data, renders tab shell | +| `components/ChangelogTabs.tsx` | `"use client"` | Hash-based tab switcher, renders all three tab panels | +| `components/RoadmapItem.tsx` | `"use client"` | Single roadmap item with optimistic upvote toggle | +| `components/FeedbackForm.tsx` | `"use client"` | Shared form (category + message + email), posts to `/api/feedback` | +| `components/FeedbackModal.tsx` | `"use client"` | Backdrop + dialog wrapper around `FeedbackForm` | +| `app/(app)/feedback/page.tsx` | RSC | Standalone page rendering `FeedbackForm` full-width | +| `app/admin/feedback/page.tsx` | RSC | Admin table of submissions, sortable + filterable | +| `app/api/feedback/route.ts` | API route | Proxy to Spring Boot | +| `app/api/roadmap/votes/route.ts` | API route | Proxy to Spring Boot | +| `app/api/roadmap/[sanityId]/vote/route.ts` | API route | Proxy to Spring Boot | + +### Modified Files + +| File | Change | +|---|---| +| `lib/sanity.ts` | Add `changelogEntriesQuery` and `roadmapItemsQuery` | +| `components/TopNav.tsx` | Add "Send Feedback" ghost button that opens `FeedbackModal` | +| `app/page.tsx` | Add "Send Feedback" link to footer alongside Privacy / Terms | + +--- + +## UI Design + +### `/changelog` Page Header + +``` +BATTL BUILDERS (small caps label) +Updates (h1) +What we've shipped and what's coming next. (subhead) + +[ What's New ] [ What's Next ] [ Give Feedback ] (tab bar, amber underline on active) +``` + +### What's New Tab + +Two-column entry layout: left column is version + date (120px fixed), right column is tags + title + body. Entries separated by bottom border, ordered newest first. + +Tag values rendered as small pill badges: +- `feature` → amber +- `fix` → green +- `improvement` → blue + +### What's Next Tab + +Items grouped under "In Progress" and "Planned" headings (Shipped items not shown — they migrate to the changelog). Each item is a card with: +- **Left:** upvote button (chevron up + count) — bordered pill, amber when voted +- **Center:** title + description +- **Right:** status badge (In Progress = amber, Planned = muted) + +Unauthenticated users clicking upvote are prompted to sign in (toast or redirect). Voted state is toggled optimistically — rolls back on error. + +Footer nudge: *"Don't see what you need? Give us feedback →"* links to `#give-feedback`. + +### Give Feedback Tab & `/feedback` Page + +Full-width form: +- Category + email in a two-column row +- Message textarea (full width, 1000 char limit with counter) +- Submit button bottom-right, privacy note bottom-left + +### Feedback Modal + +Triggered by "Send Feedback" in TopNav and homepage footer. Same fields as the tab form. Full-width submit button inside the modal. + +--- + +## Admin View (`/admin/feedback`) + +Table with columns: Date, Category, Message (truncated), Email, Reviewed. Sortable by date. Filterable by category (Bug / Feature / General) and reviewed status. Follows existing admin page patterns. + +--- + +## Feedback Form Fields + +| Field | Required | Validation | +|---|---|---| +| Category | Yes | One of: Bug report, Feature request, General feedback | +| Message | Yes | 1–1000 characters | +| Email | No | Valid email format if provided | + +`ip_address` and `user_agent` are captured server-side in the Next.js proxy route — never sent from the client form. + +--- + +## Out of Scope + +- Email notifications when feedback is submitted (separate task) +- Sorting roadmap items by vote count (manual `order` field only for now) +- Public display of vote counts on the changelog tab +- Sanity Studio schema deployment (handled separately via Sanity CLI) +- Spring Boot entity/migration code (lives in `ballistic-builder-spring` repo, tracked separately)