A customizable content aggregator that pulls RSS/Atom feeds into one organized reading dashboard.
Live URL: Not deployed yet (local development build is working)
This project implements a Frontpage feed-reader experience with a polished UI and real dynamic feed loading through a server route.
The current build focuses on the frontend-heavy path:
- Real feed fetching and parsing (RSS + Atom)
- Dynamic list rendering in the dashboard
- Filtering by category/feed/search
- Saved items and read/unread state in UI
- Refresh flow with explicit status feedback
Authentication and database persistence are not yet implemented.
| Layer | Technology |
|---|---|
| Framework | Next.js 16.2.4 (App Router) |
| Database | Not implemented yet (frontend-focused current version) |
| Authentication | Not implemented yet |
| Hosting | Not deployed yet |
| Styling | Tailwind CSS v4 + custom design tokens |
| Other | TypeScript, server-side feed parsing via Next route handlers |
These are the product and design choices made where the spec left room for interpretation.
The problem I was solving: Users should not land on an empty app and wonder what to do.
My approach:
- Seeded the dashboard with curated sources from
data/sample-feeds.json - Added server-side fetching to populate the feed view with real items
- Kept UI structure familiar: top navigation + left sidebar + list-focused content pane
Why I chose this approach: It gives immediate value and mirrors how real feed readers are used (scan first, configure later).
What I'd do differently:
- Add a dedicated onboarding panel with feed packs by interest
- Add first-run tooltips for filter mechanics
The problem I was solving: Users need to quickly understand what changed since their last check.
My approach:
- Added refresh status messaging (loading/success/fallback)
- Added relative time labels for scannability
- Kept compact excerpts (truncated server-side) for fast triage
Why I chose this approach: It keeps attention on “what’s new” instead of long-form reading in the list view.
What I'd do differently:
- Add a dedicated digest mode (“Since last visit”) with ranking and grouping
The problem I was solving: Initial priority was matching the target visual layout and interaction expectations.
My approach:
- Implemented a focused single reading layout similar to the provided preview
- Prioritized hierarchy and clarity over mode complexity
Why I chose this approach: The reference look-and-feel was a strict requirement, so consistency came first.
What I'd do differently:
- Reintroduce optional density modes (comfortable/compact/cards) once baseline UX is stable
- Entire row is clickable for quick reading flow
- Explicit
Read moreCTA remains for clarity Mark all readis implemented as a toggle for the currently filtered set- Sidebar counts update from live item data
- Initial: Static prototype to lock visual structure against the preview.
- Final: Dynamic feed-driven dashboard via
app/api/feeds/route.ts, with robust fallback behavior.
- Oversized typography in an intermediate version was rolled back for readability.
- “Refresh” originally had ambiguous feedback; now it reports explicit result states.
- Sidebar actions were initially decorative; now all primary filters are wired.
- Real feeds often return inconsistent or overly long content bodies; excerpt normalization was essential.
- Distinguishing “readability polish” from “feature correctness” required multiple iteration passes.
| Session | Focus | What I Accomplished |
|---|---|---|
| 1 | Spec alignment + UI scaffold | Matched preview structure and visual hierarchy |
| 2 | Dynamic data layer | Added /api/feeds with RSS/Atom parsing and per-feed failure isolation |
| 3 | Interaction wiring | Connected sidebar filters, saved/read state, refresh messaging |
| 4 | UX polish | Added row click-through, Read more, truncated summaries, toggle bulk read |
- Used AI as a pair programmer for refactors, parser scaffolding, and rapid iteration.
- Verified behavior manually and corrected misaligned visual/interaction outputs.
- Breaking work into clear vertical slices (layout, data, interaction, polish).
- Tight feedback loops with visual comparison and small targeted patches.
- UI fidelity and feature correctness should be validated independently.
- Real-world feed data requires defensive parsing and strict excerpt control.
- Rejected non-matching typography/density decisions and reverted toward the reference style.
- Replaced ambiguous controls with explicit behavior and status feedback.
1. Accessibility-first interaction details (partial)
Why I chose this: Feed readers are reading-heavy products; keyboard and clarity matter.
How it enhances the product:
- Keyboard activation on clickable items (
Enter/Space) - Clear refresh status feedback
- Improved contrast for muted text
Implementation highlights:
- Semantic/interactive states on list items and controls
- Focus and hover affordances tuned for scanability
What I learned: Small accessibility and feedback details significantly improve perceived quality.
| Category | Rating | Notes |
|---|---|---|
| Works for real users — Deployed, functional end-to-end | 3/5 | Functional locally; not deployed yet |
| Feed parsing robustness — Handles format variations, errors, edge cases | 3/5 | RSS/Atom supported with graceful fallback; not fully hardened for all edge cases |
| Design-it-yourself features — Quality and thoughtfulness of onboarding, digest, and layout solutions | 3/5 | Strong feed view, partial onboarding/digest |
| Design quality — Typography, spacing, visual hierarchy, polish | 4/5 | Closely aligned to target preview and improved readability |
| Responsive design — Fully functional and well-designed across devices | 3/5 | Core responsiveness works; mobile optimization can go further |
| Performance — Fast load, smooth scrolling, efficient caching | 3/5 | Revalidation and server route in place; no advanced optimization yet |
| Accessibility — Keyboard nav, screen reader support, contrast | 3/5 | Improved contrast and keyboard interactions; full audit pending |
| Edge case handling — Empty states, errors, loading, large datasets | 4/5 | Loading/error/fallback states implemented |
| Code quality — Clean, maintainable, well-structured | 4/5 | Clear separation between API parsing and UI state |
| Landing page — Compelling, communicates value, visually polished | 2/5 | Current implementation prioritizes app view over landing-first flow |
| Guest experience — Immediately impressive, real content, full features | 4/5 | Live content and working interactions without auth |
| Category | Score |
|---|---|
| Performance | Not measured yet |
| Accessibility | Not measured yet |
| Best Practices | Not measured yet |
| SEO | Not measured yet |
- Dynamic feed ingestion and parsing without breaking UI flow
- Clean, reference-aligned feed-reader interface
- Working filter interactions and meaningful bulk actions
- Add persistence for saved/read/filter state
- Add auth + per-user data model
- Add richer digest mode and explicit sorting/reading workflows
- No user authentication or account-level persistence yet
- No DB-backed storage for feeds/preferences/read state
- Reader view for full in-app article rendering is not implemented
- OPML import/export is not implemented
- Some feed-specific formatting quirks may still appear depending on upstream content
# Clone your repo
git clone [your-repo-url]
cd frontpage
# Install dependencies
npm install
# Run dev server
npm run dev
# Optional checks
npm run lint
npm run buildOpen http://localhost:3000.
| Variable | Description |
|---|---|
| None required | Current implementation runs without env vars |
Built as a Frontend Mentor Product Challenge-style implementation using the provided project spec/templates.
