mono/packages/ui/docs/feed.md
2026-02-08 15:09:32 +01:00

4.4 KiB

Instagram-like Feed Implementation Plan

Objective

Create a responsive, immersive feed experience that adapts to device size:

  • Desktop/Large Screens: Retain the current PhotoGrid (grid view).
  • Mobile: Implement a new Feed view (vertical list) similar to Instagram.
  • Carousel: Support horizontal swiping (left/right) through multiple pictures within a single post.
  • Performance: Implement "load ahead" strategy (buffer ~5 posts) to ensure smooth scrolling without loading the entire database.

Architecture & Components

1. Data Layer Enhancements

Current PhotoGrid logic fetches posts and selects a single "cover" image. We need to modify the data transformation to pass all visible pictures to the UI components.

  • Query: Keep fetching posts with pictures.
  • Transformation: Instead of flattening to a single MediaItem, we need a structure that preserves the list of pictures for each post.
    interface FeedPost {
      id: string; // Post ID
      user_id: string; // Author
      pictures: MediaItemType[]; // Array of pictures in the post
      // ... other post metadata (title, description, etc.)
    }
    

2. New Feed Component (Mobile)

A new component src/components/Feed.tsx will be created for the mobile view.

  • Layout: Vertical list of full-width cards.
  • Virtualization: Use react-window or simpler intersection observer-based rendering to only render posts in (and slightly outside) the viewport.
  • Preloading: Ensure the next 5 image/video assets are preloaded.

3. Updated MediaCard / New FeedCard

MediaCard currently handles a single media item. We have two options:

  1. Refactor MediaCard: Add support for an array of media and internal carousel logic.
  2. Create FeedCard: A specialized card for the Feed view that wraps MediaCard or implements its own carousel.
    • Decision: Use FeedCard (or PostCard) to encapsulate the carousel logic (Embla Carousel or similar) and use MediaCard for individual slides if needed, or implement a lighter slide view.
    • Carousel: Must support touch gestures for left/right swiping.

4. PhotoGrid Updates

  • Logic Separation: Extract the data fetching hook (e.g., useFeedMedia) so both PhotoGrid and Feed can share the same data source and state (likes, etc.).
  • Responsive Switch: In Index.tsx, conditionally render PhotoGrid (desktop) or Feed (mobile). Or render both and hide via CSS (better for SSR/hydration matching, but heavier on DOM). Better to use a valid hook for isMobile.

Implementation Steps

Phase 1: Data & Hooks

  1. Create useFeedQuery hook to fetch posts + pictures.
  2. Implement pagination (infinite scroll) logic (load 10, load next 10 when bottom reached).
  3. Preloading utility: Function to preload images n indexes ahead of the current viewport item.
  1. Implement a Swipe/Carousel component (using embla-carousel-react or purely custom CSS scroll-snap).
  2. Ensure it handles image aspect ratios gracefully (Instagram usually restricts to 4:5 or square, but we might support flexible).

Phase 3: MobileFeed Component

  1. Create the vertical list layout.
  2. Implement the "Load 5 ahead" logic (prefetching images for the next 5 cards).
  3. Integrate the Carousel for multi-image posts.

Phase 4: Integration

  1. Update Index.tsx to switch between PhotoGrid and MobileFeed.
  2. Ensure shared state (Likes, Comments) works in both views.

Technical Details

"Load 5 Ahead" Strategy

  • Intersection Observer: Watch the last rendered element to trigger fetching the next page.
  • Image Preloading: Watch the currently visible post index. Automatically create Link rel="preload" or new Image() for the cover images of the next 5 posts.
  • Carousel Preloading: If a user stops on a post, prioritize loading the next slide of that specific post.

Swiping Interaction

  • Carousel (Inner): Swiping horizontally moves between pictures of the same post.
  • Feed (Outer): Scrolling vertically moves between different posts.

Proposed File Structure

  • src/components/feed/Feed.tsx
  • src/components/feed/FeedCard.tsx (Handles the carousel)
  • src/components/feed/FeedCarousel.tsx (The actual swiper)
  • src/hooks/useFeed.ts (Data fetching logic)