SSR + Paginated Home Page Feed Render a feed of the latest posts with a collectionGroup query

This lesson is available for PRO members or as a single course purchase. Sign-in and choose a plan below.
Get Unlimited PRO Access


*Enrollment provides full access to this course (and updates) for life.

Firebase Lib

Use this function to convert a Firestore timestamp to a number.

file_type_js_official lib/firebase.js
export const fromMillis = firebase.firestore.Timestamp.fromMillis;

Home Page Post Feed

The first batch is rendered on the server, while all subsequent queries are executed clientside.

file_type_js_official pages/index.js
import PostFeed from '../components/PostFeed';
import Loader from '../components/Loader';
import { firestore, fromMillis, postToJSON } from '../lib/firebase';

import { useState } from 'react';

// Max post to query per page
const LIMIT = 1;

export async function getServerSideProps(context) {
  const postsQuery = firestore
    .where('published', '==', true)
    .orderBy('createdAt', 'desc')

  const posts = (await postsQuery.get());

  return {
    props: { posts }, // will be passed to the page component as props

export default function Home(props) {
  const [posts, setPosts] = useState(props.posts);
  const [loading, setLoading] = useState(false);

  const [postsEnd, setPostsEnd] = useState(false);

  const getMorePosts = async () => {
    const last = posts[posts.length - 1];

    const cursor = typeof last.createdAt === 'number' ? fromMillis(last.createdAt) : last.createdAt;

    const query = firestore
      .where('published', '==', true)
      .orderBy('createdAt', 'desc')

    const newPosts = (await query.get()) =>;


    if (newPosts.length < LIMIT) {

  return (
        <PostFeed posts={posts} />

        {!loading && !postsEnd && <button onClick={getMorePosts}>Load more</button>}

        <Loader show={loading} />

        {postsEnd && 'You have reached the end!'}


Ask questions via GitHub below OR chat on Slack #questions