DEV Community

Cover image for Building Hacker News 2026: A Modern Take on a Classic
Harish Kotra (he/him)
Harish Kotra (he/him)

Posted on

Building Hacker News 2026: A Modern Take on a Classic

Hacker News is a staple for developers, but its minimalist design hasn't evolved much over the years. As a developer who spends hours reading tech news, I decided to build Hacker News 2026—a modern, high-performance client that prioritizes UX without sacrificing the original's speed.

In this post, I'll walk you through the technical architecture, the challenges of real-time data, and how I built a robust theme system.

The Architecture: Component-Driven and Hook-Heavy

I chose React 18 and Vite for the foundation. React's component-based architecture is perfect for managing the complex comment trees and story lists that Hacker News requires.

1. Data Fetching: The Service Layer

Instead of scattering fetch calls across components, I built a dedicated service layer (hnApi.ts) that interacts with the Hacker News Firebase API. This layer handles:

  • Fetching story IDs for different categories (Top, New, Best, etc.).
  • Batch fetching items (stories, comments, users) to minimize network overhead.
  • Domain extraction for cleaner story cards.
// src/services/hnApi.ts
export const fetchItems = async (ids: number[]): Promise<HNItem[]> => {
  return Promise.all(ids.map(id => fetchItem(id)));
};
Enter fullscreen mode Exit fullscreen mode

2. Real-Time Polling: The "Live" Feel

One of the coolest features of HN 2026 is the real-time polling. In StoryDetail, I implemented an intelligent polling mechanism that adjusts its frequency based on activity.

// src/components/StoryDetail.tsx
useEffect(() => {
  const loadStory = async (isUpdate = false) => {
    const item = await fetchItem(id);
    // If comment count changed, reset poll interval to aggressive
    if (item.descendants !== story?.descendants) {
      setPollInterval(30000);
    } else {
      // Back off if no changes are detected
      setPollInterval(prev => Math.min(prev * 1.5, 300000));
    }
    setStory(item);
  };
  // ... polling logic
}, [id, pollInterval]);
Enter fullscreen mode Exit fullscreen mode

3. The Global Theme System

I wanted users to have full control over their reading environment. I built a ThemeContext that manages both color themes (Light, Dark, Sepia, High Contrast) and typography (Sans, Serif, Outfit).

By injecting CSS variables into the root element, I can switch the entire app's look instantly without re-rendering the whole tree.

/* src/index.css */
[data-theme='sepia'] {
  --color-theme-bg: #f4ecd8;
  --color-theme-text: #5b4636;
  --color-theme-muted: #8c7b6e;
}
Enter fullscreen mode Exit fullscreen mode

4. Keyboard-First UX

For power users, I implemented keyboard shortcuts (J/K for navigation, Enter to open, B to bookmark). This required careful management of a selectedIndex state and ensuring the selected item is always scrolled into view.

// src/components/StoryList.tsx
useEffect(() => {
  const handleKeyDown = (e: KeyboardEvent) => {
    switch (e.key.toLowerCase()) {
      case 'j': setSelectedIndex(prev => Math.min(prev + 1, stories.length - 1)); break;
      case 'k': setSelectedIndex(prev => Math.max(prev - 1, 0)); break;
      // ... other keys
    }
  };
  window.addEventListener('keydown', handleKeyDown);
  return () => window.removeEventListener('keydown', handleKeyDown);
}, [stories, selectedIndex]);
Enter fullscreen mode Exit fullscreen mode

Challenges and Solutions

Challenge: Deeply Nested Comments

Hacker News comment threads can be incredibly deep.
Solution: I used a recursive Comment component with a depth prop to manage indentation and visual hierarchy. I also added a "Collapse All" feature to help users navigate massive threads.

Challenge: Performance with Infinite Scroll

Rendering hundreds of complex story cards can slow down the UI.
Solution: I implemented a simple but effective infinite scroll using IntersectionObserver and batch-fetched items to keep the main thread free.

Looking Ahead

Hacker News 2026 is just the beginning. I'm planning to add:

  • Algolia Search: For finding historical discussions.
  • PWA Support: For a native-like experience on mobile.
  • User Mentions: To highlight relevant conversations.

Building this has been a journey in balancing minimalism with modern power. I hope you enjoy reading it as much as I enjoyed building it!

HN 2026-1

HN 2026-2

HN 2026-3

HN 2026-4

HN 2026-5

HN 2026-6

HN 2026-7


Check out the project on GitHub.

Inspired by https://x.com/MakerThrive/status/2035533184176144475

Top comments (0)