# PRD for RSS Reader PWA
> [!warning] This document is deprecated
> This PRD has been superseded by a newer version at:
> `/Users/shayon/DevProjects/rss-news-reader/docs/product/PRD.md`
>
> **Deprecated on:** 2025-01-16
> **Reason:** Updated requirements and architecture decisions
---
# Original PRD Content
## Product Overview
### Product Name
**Shayon's News**
### Description
A Progressive Web Application (PWA) for aggregating and summarizing news articles synchronized from the user's Inoreader account. The system emphasizes clean readability, AI-powered summarization, and efficient feed management. Designed for a single user on a local network, it supports PWA features like offline access and responsive UI.
## Goals & Key Features
1. **Feed Management**:
- Synchronize feeds using the user's Inoreader account
- Feed management (add, rename, remove feeds) handled through Inoreader
- Automatic (daily) and manual synchronization options
2. **Article Handling**:
- Parse and store articles with readability-enhanced content
- Automatic content detection for partial vs. full articles
- AI-powered summarization of articles using Perplexity API
- Deduplication by URL matching
3. **UI/UX**:
- Responsive and accessible design
- Dark/light mode support
- Simple navigation using Lucide React icons
- Human-readable date formats
4. **Data Retention**:
- Store up to 500 articles, pruning daily at midnight
- Remove oldest articles first during pruning
5. **Filtering**:
- Filter articles by read/unread status
- Filter articles by feed source
## Target Environment
- Runs on a local system (e.g., M2 Mac Mini), accessed via local IP on iPhone/iPad as a PWA
- Single user, no authentication needed beyond Inoreader login
- MongoDB Atlas for storage, free tier is sufficient
## Detailed Feature Requirements
### Feed Management
#### Inoreader Synchronization
- User authenticates with their Inoreader account
- System synchronizes feeds from Inoreader automatically
- Fetches up to 10 recent articles per feed initially
- Synchronization occurs once daily (before pruning)
- Manual synchronization option available
- Feed additions, deletions, and renaming must be performed within Inoreader
#### Feed Refresh
- Automatic daily synchronization of all feeds
- Manual refresh option for all feeds
- Only fetches articles published after last synchronization
- Articles are deduplicated by URL
- Updates feed metadata on successful refresh
### Article Management
#### Content Detection
The system uses these rules to determine if an article has partial content:
1. **Empty Content Check**:
- Articles with no content are considered partial
- Articles where content equals summary are considered partial
2. **Length-based Rules**:
- Articles with less than 100 words that contain HTML links are considered partial
3. **HTML Markers**:
- Content containing specific HTML comments (`<!-- truncate -->`, `<!-- more -->`, `<!--more-->`)
4. **Text Markers**:
- Ellipsis variations (`…`, `…`, `[…]`)
- "Continue reading" variations
- "Read more" variations
- Other common truncation indicators
#### Fetching & Processing
- Initial fetch of ~10 recent articles per feed
- For partial content, system fetches full article from source URL
- Uses Mozilla Readability to extract clean content
- Stores both original and processed content
- On refresh, fetches only articles published after last known date
#### Data Retention
- Daily pruning at midnight to keep 500 most recent articles
- Removes oldest articles first, including read articles
- Cached articles and summaries are pruned if the user has read them
#### Article Status
- Default status is 'unread' when article is first added
- User can mark articles as 'read' or 'unread'
#### Summarization
- AI-powered summarization using Perplexity API
- Summary length up to 80 words
- Summarize button for articles without summary
- Option to retry summarization if quality is poor
- System fetches full content for partial articles before summarization
### UI/UX
#### Navigation
- Article list view with filter options (read/unread, feed source)
- Article detail view with full content
- Pagination displays 30 articles per page with lazy loading
#### Loading States
- Loading indicators for feed synchronization
- Loading states for article summarization
- Lazy loading for pagination
#### Error Feedback
- Clear error notifications for feed fetch failures
- Error messages for summarization failures
#### Offline Capabilities
- View cached articles and summaries while offline
- Disable network-dependent features when offline (refresh, summarize)
## Backend Workflows
### Inoreader Synchronization Process
1. User authenticates with Inoreader account
2. System fetches feed list from Inoreader
3. For each feed, fetches up to 10 recent articles
4. Processes and stores articles in the database
5. Updates synchronization timestamp
### Content Detection Process
1. System checks article content against detection rules
2. For partial content, fetches full article from source URL
3. Uses Readability to extract clean content
4. Stores both original and processed content
### Article Summarization
1. User clicks "Summarize" on an article
2. For partial content articles, system fetches full content
3. Sends article content to Perplexity API
4. Generates summary up to 80 words
5. Saves and displays the summary
### Pruning Process
1. Runs daily at midnight
2. Identifies articles exceeding the 500 limit
3. Removes oldest articles first
4. Updates database
## API Limits and Quotas
### Inoreader API
- Free tier: 1,000 API calls per hour
- Paid plans available for higher limits
### Perplexity AI API
- 50 requests per minute per model
- Default: 4,000 tokens per query
- Fixed pricing: $5 per 1000 requests (all Sonar models)
### MongoDB Atlas (Free Tier - M0)
- 512 MB fixed storage
- Maximum document size: 16 MB
- 100 databases and 500 collections total
- 500 concurrent connections
- 100 CRUD requests per second
## Tech Stack
### Frontend
- Next.js 14 (React 18)
- TailwindCSS with typography plugins
- Lucide React for icons
- Framer Motion for animations
- React Markdown for content rendering
- Next-themes for dark/light mode
### Backend
- Next.js API Routes
- Node.js runtime
- Inoreader API integration
- Mozilla Readability for content extraction
- Node-cron for scheduled tasks
- Axios for HTTP requests
- TypeScript for type safety
### Database
- MongoDB with Mongoose 8 ODM
- Schema validation and indexing
### AI Integration
- Perplexity API for summarization
- Model: llama-3.1-sonar-small-128k-online
## Error Handling
- Logging of feed parsing failures
- Disabling feeds with repeated failures
- User-friendly error notifications
- Descriptive error messages for all failure scenarios
## Logging
- Feed parsing failures with timestamps
- API errors with detailed messages
- Database issues with context
## Testing Strategy
- Unit tests for individual components and functions
- Integration tests for API routes and database operations
- End-to-end tests for complete user workflows
## Wireframes
The application will include:
- Homepage with article listing and synchronize option
- Article detail view with summarization option
- Settings page for Inoreader authentication
- Filter options for read/unread status and feed source
<iframe style="border: 1px solid rgba(0, 0, 0, 0.1);" width="800" height="450" src="https://embed.figma.com/design/uQjp8xLxxYqZrkPf0dh2eJ/RSS-Reader-App?node-id=0-1&embed-host=share" allowfullscreen></iframe>
## User Stories
|Story ID|User Story|Story Details|Acceptance Criteria|
|---|---|---|---|
|US-001|As a user, I want to authenticate with my Inoreader account so that I can access my feeds.|User needs to be able to connect the app with their Inoreader account to synchronize feeds.|• User can enter Inoreader credentials<br>• System successfully authenticates with Inoreader API<br>• User's authentication status is displayed<br>• User can log out if needed|
|US-002|As a user, I want the app to synchronize my Inoreader feeds automatically so I don't have to manage feeds in multiple places.|System should automatically fetch and update the feed list from Inoreader once per day.|• App automatically synchronizes with Inoreader daily<br>• All feed additions, removals, and renames in Inoreader are reflected in the app<br>• Synchronization timestamp is displayed<br>• Failed synchronizations are clearly reported|
|US-003|As a user, I want to manually trigger a feed synchronization so I can get the latest articles immediately.|User needs a way to refresh feeds without waiting for the daily automatic synchronization.|• Synchronize button is available and functional<br>• Synchronization process shows clear loading state<br>• Completion status is displayed with count of new articles<br>• Any errors during synchronization are clearly reported|
|US-004|As a user, I want to view the latest articles from my feeds in a clean, readable format.|System displays articles in a list with clear formatting and pagination.|• Articles are displayed in reverse chronological order<br>• Each article shows title, source, and publication date<br>• Article list supports pagination with 30 articles per page<br>• Lazy loading is implemented for smooth scrolling|
|US-005|As a user, I want the system to detect and fetch full content for partial articles so I can read the complete article.|System should identify partial content and fetch the full article automatically.|• System correctly identifies partial vs. full content<br>• Full content is fetched for partial articles<br>• Readability processing produces clean, formatted content<br>• Original URL is preserved for reference|
|US-006|As a user, I want to get AI-generated summaries of articles to quickly understand their content.|User can request AI summaries of articles using Perplexity API.|• Summarize button is available for articles without summaries<br>• Summaries are limited to 80 words<br>• Loading state is displayed during summarization<br>• Option to retry summarization is available if quality is poor|
|US-007|As a user, I want to mark articles as read or unread to track what I've already viewed.|System maintains read/unread status for all articles.|• Articles have clear read/unread indicators<br>• User can toggle between read/unread states<br>• Read/unread status persists across sessions<br>• Status changes are immediately reflected in the UI|
|US-008|As a user, I want to filter articles by read/unread status so I can focus on new content.|System provides filtering options for article list.|• Filter controls for read/unread status are available<br>• Filtered results update immediately<br>• Filter state persists during session<br>• Filter can be combined with feed source filter|
|US-009|As a user, I want to filter articles by feed source so I can focus on specific topics.|System allows filtering articles to show only those from selected feeds.|• Feed source filter controls are available<br>• Filtered results update immediately<br>• Filter state persists during session<br>• Filter can be combined with read/unread filter|
|US-010|As a user, I want the app to work offline so I can read cached articles without an internet connection.|System caches articles for offline reading.|• Previously loaded articles are accessible offline<br>• Cached summaries are available offline<br>• Network-dependent features are appropriately disabled<br>• Clear indication of offline status is displayed|
|US-011|As a user, I want the system to automatically prune old articles to manage storage efficiently.|System maintains a limit of 500 articles by removing the oldest first.|• Automatic pruning runs daily at midnight<br>• System retains the 500 most recent articles<br>• Pruning process does not affect user experience<br>• Pruning activity is logged for reference|
|US-012|As a user, I want the app to support dark mode so I can read comfortably in different lighting conditions.|System adapts UI based on device theme settings.|• App automatically detects device theme settings<br>• UI elements adapt appropriately to dark/light modes<br>• Text remains readable in both modes<br>• Theme transitions are smooth if mode changes|
|US-013|As a user, I want clear error messages when things go wrong so I know what happened and what to do.|System provides informative error messages for all failure scenarios.|• Error messages are clear and descriptive<br>• Suggested actions are provided when applicable<br>• Critical errors are prominently displayed<br>• Non-critical errors use non-intrusive notifications|
|US-014|As a user, I want to view the full content of an article with proper formatting.|System displays the complete article content with clean formatting.|• Article detail view shows full content<br>• Formatting is preserved where appropriate<br>• Images are displayed if present<br>• Source attribution and publication date are clearly shown|
|US-015|As a user, I want the system to deduplicate articles so I don't see the same content multiple times.|System identifies and removes duplicate articles based on URL.|• Duplicate articles with identical URLs are detected<br>• Only one instance of each article is displayed<br>• Deduplication occurs during synchronization process<br>• No visible artifacts from deduplication process|
|US-016|As a user, I want the app to work as a PWA so I can install it on my devices.|System functions as a Progressive Web Application with offline capabilities.|• App can be installed on supported devices<br>• App icon appears on home screen after installation<br>• App launches in standalone mode when installed<br>• Basic functionality works without network connection|
|US-017|As a user, I want a responsive design so I can use the app on different devices.|UI adapts to different screen sizes and orientations.|• Layout adjusts appropriately for mobile, tablet, and desktop<br>• Content remains readable at all screen sizes<br>• Navigation elements are accessible on all devices<br>• Touch interactions work properly on mobile devices|
|US-018|As a user, I want loading states to be clearly indicated so I know when the system is processing.|System displays appropriate loading indicators for all async operations.|• Loading indicators for synchronization process<br>• Loading states for summarization requests<br>• Loading indicators for pagination/lazy loading<br>• Loading states do not block UI unnecessarily|
|US-019|As a user, I want to see when feeds are disabled due to repeated failures so I can address the issue.|System disables feeds after repeated failures and notifies the user.|• Feeds with repeated failures are visibly marked as disabled<br>• Reason for disabling is clearly communicated<br>• Option to manually re-enable is provided<br>• Failure count is reset upon successful refresh|
|US-020|As a user, I want human-readable date formats so I can easily understand when articles were published.|System displays dates in a clear, human-readable format.|• Publication dates show in relative format when recent (e.g., "2 hours ago")<br>• Older dates show in standard format (e.g., "Apr 10, 2025")<br>• Date formats are consistent throughout the app<br>• Full date/time available on hover or in article detail|
|US-021|As a user, I want to see the source of each article so I know where it originated from.|System displays the feed source for each article.|• Each article listing shows associated feed name<br>• Feed icon/favicon is displayed when available<br>• Feed name links to filter by that feed<br>• Original domain is displayed in article detail view|
|US-022|As a user, I want to navigate back to the article list from an article detail view.|System provides intuitive navigation between views.|• Back button/gesture is available in article detail view<br>• Navigation preserves scroll position in article list<br>• Navigation maintains current filter settings<br>• Transition between views is smooth|
|US-023|As a user, I want the app to remember my last session state so I can continue where I left off.|System persists user session state across visits.|• Last active filters are remembered<br>• Scroll position is maintained when possible<br>• Read/unread status persists across sessions<br>• Last viewed article is highlighted if visible|
|US-024|As a user, I want to see a loading animation when feeds are being refreshed.|System indicates feed refresh activity.|• Visible animation during feed synchronization<br>• Animation stops when synchronization completes<br>• Loading state does not block UI interaction<br>• Clear indication of completion status|
|US-025|As a user, I want pagination controls so I can navigate through large sets of articles.|System implements pagination for the article list.|• Pagination controls are clearly visible<br>• User can navigate to next/previous page<br>• Current page number is displayed<br>• Lazy loading enhances scrolling experience|
|US-026|As a user, I want to re-attempt summarization if the initial result is poor.|System allows multiple summarization attempts.|• Re-summarize button is available<br>• New summary replaces previous one<br>• Loading state is displayed during re-summarization<br>• User can attempt summarization multiple times|
|US-027|As a user, I want to see the app adapt to my device's orientation changes.|System responds appropriately to orientation changes.|• Layout adjusts when orientation changes<br>• Content remains readable in both orientations<br>• No UI elements are cut off after orientation change<br>• Scroll position is maintained when possible|
|US-028|As a user, I want to manually re-enable a disabled feed.|System allows re-enabling of disabled feeds.|• Re-enable option is available for disabled feeds<br>• Re-enabling triggers immediate refresh attempt<br>• Success/failure status is clearly reported<br>• Failure count is reset upon manual re-enable|
|US-029|As a user, I want animations and transitions to be smooth and unobtrusive.|System implements appropriate animations for state changes.|• Transition animations are smooth<br>• Animations don't interfere with usability<br>• Animation duration is appropriate<br>• Reduced motion settings are respected|
|US-030|As a user, I want to see the app icon and name on my device home screen when installed as a PWA.|System provides proper PWA metadata.|• App has distinctive icon<br>• App name is displayed correctly<br>• Icon appears at appropriate resolution<br>• Splash screen shows on launch where supported|
|US-031|As a user, I want clear indication of which articles I've already read.|System visually distinguishes read vs. unread articles.|• Read articles have distinct visual styling<br>• Unread articles are prominently highlighted<br>• Status change is immediately reflected in UI<br>• Read/unread count is displayed when filtering|
|US-032|As a user, I want to view images included in articles.|System displays images within article content.|• Images are displayed at appropriate sizes<br>• Image loading does not block text display<br>• Alt text is shown if image fails to load<br>• Images maintain proper aspect ratios|
|US-033|As a user, I want to know when my feeds were last synchronized.|System displays the timestamp of the last synchronization.|• Last sync time is clearly displayed<br>• Format is human-readable<br>• Updates automatically after each sync<br>• Indicates if sync is currently in progress|
|US-034|As a user, I want to be notified of errors during API calls.|System provides feedback for API failures.|• Error notifications for failed API calls<br>• Distinction between network vs. API errors<br>• Retry options where appropriate<br>• Clear description of what went wrong|
|US-035|As a user, I want the content extraction to handle various article formats correctly.|System adapts content extraction to different site layouts.|• Readability processing works across diverse sources<br>• Extraneous content (ads, sidebars) is removed<br>• Article text is properly formatted<br>• Essential content is preserved|
|US-036|As a user, I want to know the character count of article summaries.|System displays summary length information.|• Character or word count displayed with summary<br>• Visual indication if summary is at length limit<br>• Count updates if summary is regenerated<br>• Format is unobtrusive|
|US-037|As a user, I want to know when the app is working in offline mode.|System indicates offline status clearly.|• Visible offline indicator when network unavailable<br>• Disabled state for network-dependent features<br>• Clear messaging about limited functionality<br>• Automatic reconnection when network returns|
|US-038|As a user, I want to be able to refresh the page without losing my place.|System maintains state across page refreshes.|• Session state persists across page reloads<br>• Current filters are maintained<br>• Scroll position is restored when possible<br>• Current article selection is preserved|
|US-039|As a user, I want the app to efficiently use network bandwidth.|System implements bandwidth optimization strategies.|• Content is cached appropriately<br>• Images are lazy-loaded<br>• Network requests are batched when possible<br>• Synchronization process respects data usage|
|US-040|As a user, I want the app to render article content correctly on all devices.|System ensures responsive content rendering.|• Article text scales appropriately for device size<br>• Images resize to fit viewport<br>• Tables and other complex elements adapt to screen width<br>• Font size is readable across devices|
|US-041|As a user, I want the app to handle network interruptions gracefully.|System manages network state changes appropriately.|• Handles transitions between online/offline states<br>• Provides clear feedback when network is lost<br>• Retries failed requests when network returns<br>• Preserves user data during network issues|
|US-042|As a user, I want to see empty states when no articles match my filters.|System displays appropriate empty states.|• Empty state messaging is informative<br>• Suggestions for modifying filters are provided<br>• Visual design is consistent with overall UI<br>• No error messages for valid empty results|
|US-043|As a user, I want the app to respect my device's accessibility settings.|System adheres to accessibility standards.|• Text scales according to device settings<br>• Color contrast meets WCAG standards<br>• Screen readers can navigate content<br>• Focus states are clearly visible|
|US-044|As a user, I want to see my progress when scrolling through a long list of articles.|System provides scroll position feedback.|• Scroll position indicator for long lists<br>• Visual indication of current position in list<br>• Smooth scrolling behavior<br>• Easy return to top functionality|
|US-045|As a user, I want to see appropriate error states when content cannot be loaded.|System displays error states for content loading failures.|• Clear error messages for failed content loads<br>• Fallback to original content if available<br>• Retry options where appropriate<br>• Consistent error state styling|
|US-046|As a user, I want the app to handle intermittent API service disruptions.|System implements robust error handling for API calls.|• Retry logic for transient failures<br>• Exponential backoff for repeated failures<br>• Graceful degradation when services unavailable<br>• Informative error messages for persistent issues|
|US-047|As a user, I want the app to preserve battery life on mobile devices.|System optimizes for battery efficiency.|• Minimizes background processing<br>• Reduces unnecessary animations<br>• Optimizes network requests<br>• Respects device battery saver mode|
|US-048|As a user, I want fast initial page load times.|System optimizes for performance.|• Critical content loads first<br>• Initial load time under 3 seconds<br>• Progressive enhancement of features<br>• Appropriate use of code splitting|
|US-049|As a user, I want to know when the Inoreader API has rate-limiting issues.|System provides specific feedback for API limits.|• Clear messaging for rate limit errors<br>• Estimation of when limits will reset<br>• Suggestion for reduced request frequency<br>• Alternative actions during limit periods|
|US-050|As a user, I want summarization to handle articles in different languages.|System adapts summarization to content language.|• Summarization works with multiple languages<br>• Language detection for appropriate processing<br>• Preserves non-English characters correctly<br>• Maintains language-specific formatting|