Historical planning artifact for the original MVP. See README.md for current behavior and DESIGN.md for the active visual rules.
MorningStack is a next-generation news aggregation service for tech professionals. Delivers curated news twice daily (morning/evening editions) from multiple sources including HackerNews, GitHub, Reddit, Bluesky, YouTube, and world news. Built with Next.js App Router, TypeScript, Tailwind CSS, shadcn/ui, Drizzle ORM, Supabase, Upstash Redis, and Redux Toolkit.
Tech Stack: Next.js 15 (App Router), React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Redux Toolkit, Drizzle ORM, Supabase (PostgreSQL), Upstash (Redis), NextAuth.js (Auth.js v5), Vercel
Design: Dark-first theme (#0D0D0D bg), accent #FF6B35, responsive 1-4 column grid, Inter + Noto Sans JP fonts
These commands must pass for every user story:
pnpm run typecheck- Type checkingpnpm run lint- Lintingpnpm run build- Production build
As a developer I want a fully configured Next.js project with all dependencies installed So that I can start building features on a solid foundation
Priority: P0
Acceptance Criteria:
- Initialize Next.js 15 project with App Router, TypeScript, Tailwind CSS v4 using
pnpm create next-app@latest - Install and configure shadcn/ui with dark theme as default
- Install core dependencies:
@reduxjs/toolkit react-redux drizzle-orm @neondatabase/serverless next-auth@beta @upstash/redis - Configure Tailwind design tokens from PRD color palette: bg-primary (#0D0D0D), bg-secondary (#1A1A1A), bg-tertiary (#262626), text-primary (#FFFFFF), text-secondary (#A0A0A0), text-muted (#666666), accent (#FF6B35), border (#333333)
- Configure fonts: Inter (latin) + Noto Sans JP (japanese) via next/font
- Set up ESLint + Prettier with TypeScript rules
- Create base directory structure:
src/app/,src/components/,src/lib/,src/types/,supabase/,tests/ - Add
CLAUDE.mdto.gitignore - Verify
pnpm run devstarts without errors
As a developer I want a complete database schema for all MorningStack entities So that data can be persisted and queried efficiently
Priority: P0 Depends on: US-001
Acceptance Criteria:
- Set up Drizzle ORM with PostgreSQL (Supabase) adapter in
src/lib/db/ - Create
userstable: id (uuid, pk), email, name, avatarUrl, provider (google/github), createdAt, updatedAt - Create
editionstable: id (uuid, pk), type (enum: morning/evening), date, publishedAt, status (enum: draft/published) - Create
articlestable: id (uuid, pk), editionId (fk), source (enum: hackernews/github/reddit/producthunt/tech_rss/hatena/bluesky/youtube/world_news), title, url, thumbnailUrl, excerpt, score, externalId, metadata (jsonb), createdAt - Create
bookmarkstable: id (uuid, pk), userId (fk), articleId (fk), createdAt with unique constraint on (userId, articleId) - Create
hidden_itemstable: id (uuid, pk), userId (fk), targetType (enum: article/source/topic), targetId, createdAt - Create
weather_cachetable: id, location, data (jsonb), fetchedAt - Create
stock_cachetable: id, symbol, data (jsonb), fetchedAt - Create Drizzle migration files in
supabase/migrations/ - Export typed schema and relations from
src/lib/db/schema.ts
As a user I want to log in with Google or GitHub So that I can save bookmarks and personalize my news feed
Priority: P0 Depends on: US-002
Acceptance Criteria:
- Configure Auth.js v5 (NextAuth) with Google and GitHub OAuth providers in
src/lib/auth.ts - Set up Drizzle adapter for Auth.js session persistence
- Create
/loginpage with Google and GitHub OAuth buttons styled with shadcn/ui - Add auth middleware in
src/middleware.tsto protect/bookmarksand/settingsroutes - Create
SessionProviderwrapper in root layout - Display user avatar and name in header when logged in, "Login" button when not
- Implement sign-out functionality
As a developer I want a centralized state management store So that client-side state like UI preferences and edition selection is managed consistently
Priority: P0 Depends on: US-001
Acceptance Criteria:
- Create Redux store in
src/lib/store.tswith TypeScript-typed hooks (useAppDispatch,useAppSelector) - Create
editionSlice: manages current edition type (morning/evening), current edition date - Create
uiSlice: manages theme (dark/light), sidebar open state, share menu expansion state - Create
StoreProvidercomponent wrapping the app in root layout - Ensure store works with Next.js App Router (client component boundary)
As a user I want to see top HackerNews stories So that I stay updated on tech community discussions
Priority: P0 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/hackernews.tswith typed fetch function - Fetch top 5 stories from HN Algolia API (
hn.algolia.com/api/v1/search?tags=front_page&hitsPerPage=5) - Map API response to
Articletype: title, url, score (points), externalId, metadata (comments count, author) - Add Upstash Redis caching with 1-hour TTL in
src/lib/cache.ts - Handle API errors gracefully with fallback to cached data
- Add JSDoc documentation to exported functions
As a user I want to see trending GitHub repositories So that I discover popular open source projects
Priority: P0 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/github.tswith typed fetch function - Fetch trending repositories using GitHub REST API search endpoint (sort by stars, created in last 7 days)
- Extract top 5 repos with: name, full_name, description, stargazers_count, language, html_url
- Map to
Articletype with metadata (stars, language, description) - Add Upstash Redis caching with 1-hour TTL
- Handle rate limiting (60 req/hour unauthenticated) with exponential backoff
As a user I want to see popular Reddit posts from tech-related subreddits So that I see what the community is discussing
Priority: P0 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/reddit.tswith typed fetch function - Fetch top 5 hot posts from subreddits: r/programming, r/webdev, r/javascript, r/typescript (combine and sort by score)
- Use Reddit JSON API (
reddit.com/r/{subreddit}/hot.json) to avoid OAuth complexity for MVP - Map to
Articletype with metadata (subreddit, upvotes, comments, author) - Add Upstash Redis caching with 1-hour TTL
- Filter out NSFW and removed posts
As a user I want to see curated tech news from major outlets So that I get industry news beyond community discussions
Priority: P0 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/rss.tswith typed fetch function usingrss-parserpackage - Aggregate RSS feeds from: The Verge (
theverge.com/rss/index.xml), Ars Technica, TechCrunch - Extract top 5 articles sorted by publish date
- Map to
Articletype with metadata (source name, publish date, author) - Add Upstash Redis caching with 1-hour TTL
- Handle XML parsing errors gracefully
As a user I want to see popular Hatena Bookmark entries So that I see what's trending in the Japanese tech community
Priority: P1 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/hatena.tswith typed fetch function - Fetch hot entries from Hatena Bookmark API (category: technology)
- Extract top 5 entries with: title, url, bookmark count, description
- Map to
Articletype with metadata (bookmark count, category) - Add Upstash Redis caching with 1-hour TTL
As a user I want to see trending Bluesky posts So that I see discussions from the decentralized social network
Priority: P1 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/bluesky.tswith typed fetch function - Use AT Protocol API to fetch popular/trending posts
- Extract top 3 posts with: text, author handle, like count, repost count, url
- Map to
Articletype with metadata (author, likes, reposts) - Add Upstash Redis caching with 1-hour TTL
As a user I want to see trending YouTube tech videos So that I discover popular tech content
Priority: P1 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/youtube.tswith typed fetch function - Use YouTube Data API v3 to fetch trending videos in tech/science category
- Extract top 3 videos with: title, channel name, view count, thumbnail URL, video URL
- Map to
Articletype with metadata (channel, views, duration) - Add Upstash Redis caching with 1-hour TTL
- Handle API quota limits (10,000 units/day)
As a user I want to see today's top ProductHunt launches So that I discover new products and tools
Priority: P1 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/producthunt.tswith typed fetch function - Fetch today's top 5 products using ProductHunt API (GraphQL)
- Extract: name, tagline, votesCount, thumbnail, url, topics
- Map to
Articletype with metadata (votes, tagline, topics) - Add Upstash Redis caching with 1-hour TTL
As a user I want to see current weather for my location So that I can plan my day at a glance
Priority: P0 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/weather.tswith typed fetch function - Use OpenWeatherMap API to fetch current weather by city name (default: Tokyo)
- Extract: temperature (Celsius), weather condition, icon code, city name
- Cache weather data in
weather_cachetable and Upstash Redis (TTL: 30 minutes) - Return typed
WeatherDatainterface
As a user I want to see major stock index summaries So that I get a quick financial overview
Priority: P1 Depends on: US-002
Acceptance Criteria:
- Create
src/lib/sources/stocks.tswith typed fetch function - Fetch data for: Nikkei 225, S&P 500, NASDAQ using Alpha Vantage or Yahoo Finance API
- Extract: symbol, current price, change amount, change percentage
- Cache in
stock_cachetable and Upstash Redis (TTL: 15 minutes during market hours, 6 hours after close) - Return typed
StockData[]interface
As a system I want automated data collection at scheduled times So that morning and evening editions are ready for users
Priority: P0 Depends on: US-005, US-006, US-007, US-008, US-013
Acceptance Criteria:
- Create
/api/cron/collectAPI route handler for data collection - Configure Vercel Cron in
vercel.json:06:00 Asia/Tokyo(morning) and17:00 Asia/Tokyo(evening) - Implement parallel data fetching from all sources using
Promise.allSettled() - Create edition record in database with type (morning/evening) and date
- Save collected articles to database linked to the edition
- Apply scoring normalization: convert each source's native score to 0-100 scale
- Select top N articles per section based on normalized scores
- Mark edition as published after all data is collected
- Log collection results (success/failure per source) for monitoring
As a user I want to see news articles in visually consistent cards So that I can quickly scan and identify interesting content
Priority: P0 Depends on: US-001
Acceptance Criteria:
- Create
src/components/cards/article-card.tsxas a reusable component - Display: thumbnail image (with fallback placeholder), title (2-line clamp with ellipsis), source icon + source name, relative time ("2h ago"), score/engagement metric
- Show action buttons on hover: bookmark (star icon), share (arrow icon), hide (x icon)
- Props:
article: Article,onBookmark,onShare,onHidecallbacks - Responsive: full-width on mobile, card grid on desktop
- Follow dark theme: bg-secondary (#1A1A1A) card, bg-tertiary (#262626) on hover
- Accessible: keyboard focusable, aria labels on action buttons, proper heading hierarchy
- Add source brand color indicator bar or badge per source type
As a user I want a navigation header with morning/evening edition toggle So that I can switch between editions and access key features
Priority: P0 Depends on: US-004
Acceptance Criteria:
- Create
src/components/layout/header.tsxcomponent - Display: MorningStack logo (left), morning/evening tab switcher (center), bookmark icon, settings icon, login/avatar (right)
- Morning/evening tabs dispatch to Redux
editionSliceon click - Active tab styled with accent color (#FF6B35) underline
- Sticky header on scroll with backdrop blur
- Mobile: hamburger menu for settings/bookmarks/login
- Display current edition date (e.g., "Feb 6, 2026 - Morning Edition")
As a user I want to see the top featured stories prominently So that the most important news catches my attention immediately
Priority: P0 Depends on: US-016
Acceptance Criteria:
- Create
src/components/sections/hero-section.tsxcomponent - Display 1 main featured article (large card, 3/4 width on desktop) with 3 sub-articles below
- Main article: large thumbnail, headline, excerpt (3-line clamp), source, time
- Sub-articles: smaller cards in 3-column grid below the main card
- Select hero articles from the highest-scored articles across all sources
- Responsive: stack vertically on mobile (1 column)
As a user I want to see weather and stock info at a glance beside the hero section So that I get essential daily info without leaving the page
Priority: P0 Depends on: US-013, US-014
Acceptance Criteria:
- Create
src/components/widgets/weather-widget.tsx: weather icon, temperature in Celsius, city name, condition text - Create
src/components/widgets/stock-widget.tsx: list of indices with name, price, change % (green for up, red for down) - Position: right sidebar on desktop (1/4 width, beside hero), full-width cards above hero on mobile
- Use shadcn/ui Card component for consistent styling
- Loading state: skeleton placeholders while data fetches
As a user I want to see categorized news sections (Tech, GitHub, HN, Reddit, etc.) So that I can browse content by source/category
Priority: P0 Depends on: US-016
Acceptance Criteria:
- Create section components in
src/components/sections/:tech-section.tsx,github-section.tsx,hackernews-section.tsx,reddit-section.tsx - Each section: section header (icon + title), 5 article cards in responsive grid
- Section header component
src/components/sections/section-header.tsx: emoji/icon, title, optional "View All" link - Desktop layout: 4-column grid for Tech/GitHub/HN/Reddit row
- Tablet: 2-column grid
- Mobile: single column, horizontal scroll for cards within each section
As a user I want to see trending content from Bluesky, YouTube, Hatena Bookmark, and world news So that I get a comprehensive view beyond tech-only sources
Priority: P1 Depends on: US-009, US-010, US-011, US-016
Acceptance Criteria:
- Create
src/components/sections/sns-section.tsx: Bluesky (3 posts), YouTube (3 videos) - Create
src/components/sections/hatena-section.tsx: 5 entries - Create
src/components/sections/world-news-section.tsx: 5 general news articles (politics minimized) - YouTube cards: display video thumbnail with play button overlay, view count
- Bluesky cards: display post text snippet, author handle, like count
- Desktop: Bluesky + Hatena + World News in 3-column row
- Source-specific styling: brand colors for each source badge
As a user I want a single home page that displays all sections in the correct layout So that I get my complete morning/evening briefing on one page
Priority: P0 Depends on: US-015, US-017, US-018, US-019, US-020
Acceptance Criteria:
- Create
src/app/page.tsxas an async Server Component - Fetch current edition data from database based on Redux edition type (morning/evening) and current date
- Layout order: Header → Hero + Widgets → Tech/GitHub/HN/Reddit → SNS → Hatena/World News
- Use
Suspenseboundaries with skeleton loading states for each section - Pass edition articles to respective section components grouped by source
- Handle "no edition available" state with fallback message
- Add page metadata: title "MorningStack - Your morning briefing, curated", OGP tags
As a logged-in user I want to save articles to my bookmarks So that I can read them later
Priority: P0 Depends on: US-003, US-016
Acceptance Criteria:
- Create Server Action
src/app/actions/bookmarks.ts: addBookmark, removeBookmark, getBookmarks - Toggle bookmark on article card star icon click (optimistic UI with Redux)
- Create
/bookmarkspage listing all saved articles in a grid - Show filled star icon for bookmarked articles, empty star for unbookmarked
- If not logged in, clicking bookmark redirects to
/loginwith return URL - Sort bookmarks by most recently saved
As a logged-in user I want to hide articles, sources, or topics I'm not interested in So that my feed becomes more personalized over time
Priority: P0 Depends on: US-003, US-016
Acceptance Criteria:
- Create Server Action
src/app/actions/hidden.ts: hideItem, unhideItem, getHiddenItems - On article card X icon click, show dropdown: "Hide this article", "Hide from [source]", "Hide topic: [keyword]"
- Hidden articles are filtered out from the home page feed
- Hidden sources exclude all articles from that source
- Store hidden items in
hidden_itemstable with targetType and targetId - Apply filters in the edition data query (server-side filtering)
As a user I want to share articles to X, Bluesky, or copy the link So that I can share interesting content with others
Priority: P1 Depends on: US-016
Acceptance Criteria:
- Create
src/components/cards/share-menu.tsxexpandable component - Default state: single share icon button on article card
- Expanded state: X icon, Bluesky icon, Copy Link icon (animate expand left-to-right)
- X share: open
twitter.com/intent/tweet?text={title}&url={url}in new tab - Bluesky share: open
bsky.app/intent/compose?text={title} {url}in new tab - Copy Link: copy article URL to clipboard, show "Copied!" toast notification
- Close expanded menu when clicking outside
As a user I want to switch between dark and light themes So that I can read comfortably in any lighting condition
Priority: P1 Depends on: US-001
Acceptance Criteria:
- Install and configure
next-themespackage - Default theme: dark (as specified in PRD)
- Add theme toggle button in header (sun/moon icon)
- Define light theme tokens: bg-primary (#FAFAFA), bg-secondary (#FFFFFF), text-primary (#111111), text-secondary (#555555), accent (#FF6B35)
- Theme persists across sessions via localStorage
- Respect
prefers-color-schemesystem preference on first visit
As a user I want the app to work well on mobile, tablet, and desktop So that I can read on any device
Priority: P0 Depends on: US-022
Acceptance Criteria:
- Mobile (<640px): 1 column, horizontal scroll for section cards, hamburger menu
- Tablet (640-1024px): 2 column grid for sections
- Desktop (1024-1440px): 3-4 column grid, sidebar widgets
- Wide (>1440px): 4 column grid, max-width container (1440px centered)
- Touch targets: minimum 44x44px for all interactive elements
- Test on Chrome DevTools responsive mode at each breakpoint
As a logged-in user I want a settings page to manage my account and preferences So that I can control my MorningStack experience
Priority: P1 Depends on: US-003, US-024
Acceptance Criteria:
- Create
/settingspage with sections: Account, Hidden Items Management, Display Preferences - Account section: display user info (name, email, avatar), sign out button
- Hidden Items section: list all hidden articles/sources/topics with "unhide" button for each
- Display Preferences: theme toggle, default edition (morning/evening)
- Use shadcn/ui Tabs component for section navigation
- Redirect to
/loginif not authenticated
As a visitor I want to learn about MorningStack So that I understand the service before signing up
Priority: P1
Acceptance Criteria:
- Create
/aboutpage with: product vision, key features, data sources list, team info placeholder - Clean typographic layout using Inter font
- Include CTA button to sign up / go to home page
- Responsive design consistent with main app
As a developer I want end-to-end tests for critical user flows So that regressions are caught before deployment
Priority: P0 Depends on: US-022, US-023, US-024
Acceptance Criteria:
- Set up Playwright with
pnpm create playwright - Test: home page loads with all sections visible
- Test: morning/evening tab switching changes displayed content
- Test: clicking article card navigates to external URL
- Test: bookmark toggle works for logged-in user (mock auth)
- Test: hide article removes it from the feed
- Test: share menu expands and copy link works
- Test: responsive layout at mobile/tablet/desktop breakpoints
- Add Playwright to CI/CD pipeline
- All tests pass in headless Chrome
As a developer I want the app deployed to Vercel with optimized performance So that users have a fast, reliable experience
Priority: P0 Depends on: US-030
Acceptance Criteria:
- Configure
vercel.jsonwith cron schedules and environment variables - Set environment variables in Vercel dashboard: SUPABASE_URL, SUPABASE_KEY, UPSTASH_REDIS_URL, NEXTAUTH_SECRET, OAuth credentials
- Lighthouse score: LCP < 2.5s, CLS < 0.1, Performance > 90
- Configure Next.js Image optimization for article thumbnails
- Enable Vercel Analytics and Web Vitals monitoring
- Set up OGP meta tags for social sharing (title, description, image)
- Configure proper cache headers for static assets and API responses
- Deploy to Vercel under
Laststanceorganization