A customizable RSS/Atom aggregator with a calm reading dashboard. Built as a Frontend Mentor Product Challenge.
| URL | |
|---|---|
| Live site | https://frontpage-feed-reader-main-rho.vercel.app |
| Guest demo (submit this for instant access) | https://frontpage-feed-reader-main-rho.vercel.app/guest |
You can evaluate the full UX without creating an account via guest mode. Sign up only if you want to test persistence, onboarding, search, and saved articles.
- Open
/guest— 19 live RSS feeds across 5 categories. - Click a category in the sidebar (desktop) or open the menu (mobile).
- Mark items read/unread — state persists in
localStoragefor the session. - Open an article — in-app reader when
content_htmlis available; otherwise opens the source site. - Visit
/for the marketing landing (hero, features, how it works, footer).
- Sign up with email + password.
- Onboarding — pick starter categories (Frontend, Design, etc.) or skip to add feeds manually.
- Dashboard — filter by category, infinite scroll, unread indicators. Use the layout switcher (Compact / Standard / Cards) above the feed list.
- Search — header search or
/search?q=react; matches title + description with highlights. - Saved — bookmark from a list row or inside the reader →
/saved. - Feed management — add/remove/refresh feeds; rename, reorder, or delete categories (sidebar ⋮ menus).
| Spec area | Feature | Status | Try it |
|---|---|---|---|
| Core | Auth (sign up, login, email verify) | ✅ | /signup, /login |
| Core | Subscribe to RSS/Atom feeds | ✅ | Onboarding or “Add feed” dialog |
| Core | Organize feeds by category | ✅ | Sidebar + category management |
| Core | Article list with read/unread | ✅ | /dashboard, /category/[id] |
| Core | In-app reader | ✅ | Click any item with full HTML content |
| Core | Responsive layout | ✅ | Resize viewport; mobile drawer nav |
| Stretch | Search across library | ✅ | /search?q=… |
| Stretch | Bookmarks / Saved | ✅ | Bookmark icon → /saved |
| Stretch | OPML import/export | ❌ | Not implemented |
| Design Challenge | Onboarding / content discovery | ✅ | New account → /onboarding |
| Design Challenge | Digest view | ❌ | Deferred |
| Design Challenge | Layout customization | ✅ | Layout switcher on dashboard, category, feed, search, and saved views |
Marketing hero, feature grid, how-it-works steps, and footer. Scroll reveals use Intersection Observer + Framer Motion.
First-time users with no feeds land here. Select curated starter packs by category, import in one step, or skip to manual setup.
Dense list view with category sidebar, unread dots, and feed management. Sidebar collapses to icons on desktop.
Guest dashboard (
/guest) uses the same list/sidebar patterns with live-fetched sample feeds instead of Supabase data.
Dashboard — Linear-inspired density: sticky sidebar, bold unread titles, small accent dots. List rows animate on filter changes when < 50 items (AnimatePresence + motion.li as direct children).
Reader — Serif body (Georgia) on a calm background; HTML sanitized with lazy images. Bookmark control in the reader toolbar.
Onboarding — Dedicated route group without the app shell. Imports from sample-feeds.json via addFeed (max 4 concurrent). Skip sets a cookie so users aren’t redirected again.
Layout customization — Three global feed layouts (Compact / Standard / Cards) via a toolbar switcher. Preference stored in profiles.layout + localStorage. Cards show cover images from feed HTML when available; favicon gradient fallback otherwise. Global setting keeps the model simple; per-category layouts deferred.
Guest mode — Server-fetched live RSS (5‑min cache) so reviewers see real articles, not static placeholders. Read state in localStorage.
Landing — Section backgrounds blend with mask-image fades (same technique as the hero gradient). Product screenshot uses next/image with responsive sizes.
Next.js 15 (App Router) · Supabase (Postgres + Auth + RLS) · Vercel · Tailwind CSS v4 · Framer Motion · rss-parser · @tanstack/react-virtual
| Technique | Where |
|---|---|
| Route-level Suspense + skeletons | Dashboard, guest hydration, load-more |
| Virtualized lists | 50+ items (@tanstack/react-virtual) |
| Cursor pagination | 30 items/page + infinite scroll |
| Lazy images | Favicons, reader HTML, marketing assets |
| Guest RSS cache | 5-minute in-memory TTL |
| Image formats | AVIF/WebP via next.config.ts |
| Page | Perf | A11y | Best | SEO |
|---|---|---|---|---|
/ |
98 | 94 | 100 | 100 |
/guest |
97 | 79* | 96 | 73 |
*Guest a11y is lower because live RSS aggregation slows the SSR audit window — intentional trade-off for an authentic demo.
- OPML import/export not built
- No background cron for feed refresh (manual refresh per feed)
- Search uses
ilike(sufficient for personal libraries) - List exit animations disabled when virtualized (50+ items)
- Digest view not started
- Card layout does not virtualize long lists (use Compact for 100+ items)
- Optional polish: keyboard shortcuts, dark mode, PWA
git clone https://github.com/alexisdlr/frontpage-rss.git
cd frontpage-rss
pnpm install
cp .env.example .env.local # Supabase URL + publishable key
pnpm devOpen http://localhost:3000. Guest mode works without env vars. Auth, dashboard, search, saved, and onboarding need Supabase credentials.
| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
Supabase anon/publishable key |
Built as a Frontend Mentor Product Challenge. Spec and brand guidance from the challenge starter kit.


