Why Use Firebase Server Time?

"use client";
import { useEffect, useState } from 'react';
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, setDoc, getDoc, serverTimestamp } from 'firebase/firestore';


const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};


const app = initializeApp(firebaseConfig);
const db = getFirestore(app);


export default function ServerTime() {
  const [serverTime, setServerTime] = useState('Loading...');


  useEffect(() => {
    const fetchServerTime = async () => {
      const timeRef = doc(db, 'system', 'serverTime');
      await setDoc(timeRef, { timestamp: serverTimestamp() });
      const docSnap = await getDoc(timeRef);
      if (docSnap.exists()) {
        setServerTime(docSnap.data().timestamp.toDate().toISOString());
      }
    };
    fetchServerTime();
  }, []);


  return <div>Firebase Server Time: {serverTime}</div>;
}

Let’s break down the provided Next.js code that displays the Firebase server time using Firestore’s serverTimestamp. The code is a client-side React component that fetches and displays the current server time from Firebase Firestore. Below is a simple, step-by-step explanation of how it works.

"use client";

This directive marks the component as a Client Component in Next.js. It runs on the client side (browser), allowing the use of browser-specific features like useState and useEffect. This is necessary because Firebase’s client-side SDK and React hooks don’t work in Next.js Server Components.

import { useEffect, useState } from 'react';
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, setDoc, getDoc, serverTimestamp } from 'firebase/firestore';

React Imports:

  • useEffect: A React hook to run side effects (e.g., fetching data) after the component mounts.
  • useState: A React hook to manage the component’s state (in this case, the server time).

Firebase Imports:

  • initializeApp: Initializes the Firebase app with your project configuration.
  • getFirestore: Gets the Firestore instance for database operations.
  • doc: References a specific document in Firestore.
  • setDoc: Writes data to a Firestore document.
  • getDoc: Reads data from a Firestore document.
  • serverTimestamp: A Firebase function that generates a server-side timestamp when data is written.

const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};

This is the Firebase configuration object, which holds your project’s credentials (API key, project ID, etc.).

The credentials are stored in environment variables (e.g., NEXT_PUBLIC_FIREBASE_API_KEY) in a .env.local file. The NEXT_PUBLIC_ prefix makes them available to client-side code in Next.js.

Example .env.local: 

NEXT_PUBLIC_FIREBASE_API_KEY=your-api-key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-auth-domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-storage-bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
NEXT_PUBLIC_FIREBASE_APP_ID=your-app-id

Note: You get these values from the Firebase Console when you create a project.

const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

  • initializeApp(firebaseConfig): Initializes the Firebase app with the provided configuration.
  • getFirestore(app): Creates a Firestore instance (db) for interacting with the Firestore database.
export default function ServerTime() {
  const [serverTime, setServerTime] = useState('Loading...');

Defines a React functional component named ServerTime.

Uses useState to create a state variable serverTime, initialized to ‘Loading…’. This will store and display the Firebase server time.

setServerTime is the function to update the serverTime state.  useEffect(() => {
    const fetchServerTime = async () => {
      const timeRef = doc(db, 'system', 'serverTime');
      await setDoc(timeRef, { timestamp: serverTimestamp() });
      const docSnap = await getDoc(timeRef);
      if (docSnap.exists()) {
        setServerTime(docSnap.data().timestamp.toDate().toISOString());
      }
    };
    fetchServerTime();
  }, []);

Purpose: This useEffect hook runs once when the component mounts (due to the empty dependency array []) to fetch the server time.

Steps:

  1. Define Async Function:
  • fetchServerTime is an async function because Firestore operations (setDoc, getDoc) are asynchronous and return promises.
  1. Create Document Reference:
  • const timeRef = doc(db, ‘system’, ‘serverTime’): Creates a reference to a Firestore document at the path system/serverTime. This document will store the timestamp.
  • Firestore organizes data in collections and documents. Here, system is the collection, and serverTime is the document ID.
  1. Write Server Timestamp:
  • await setDoc(timeRef, { timestamp: serverTimestamp() }): Writes a document to Firestore with a field timestamp set to Firebase’s server time (using serverTimestamp()).
  • serverTimestamp() ensures the timestamp is generated by the Firebase server, not the client’s clock.
  1. Read the Timestamp:
  • const docSnap = await getDoc(timeRef): Reads the document we just wrote.
  • docSnap.exists(): Checks if the document exists.
  • docSnap.data().timestamp: Gets the timestamp field, which is a Firestore Timestamp object.
  • .toDate(): Converts the Firestore Timestamp to a JavaScript Date object.
  • .toISOString(): Converts the Date to a string in ISO format (e.g., 2025-07-31T05:57:00.000Z).
  1. Update State:
  • setServerTime(…): Updates the serverTime state with the ISO string, triggering a re-render to display the time.
  1. Run the Function:
  • fetchServerTime(): Calls the async function inside useEffect to execute the logic when the component mounts.
  return <div>Firebase Server Time: {serverTime}</div>;
}

Render: The component renders a <div> displaying the text “Firebase Server Time:” followed by the serverTime state.

Initially, it shows “Loading…” until the Firestore operation completes and updates serverTime with the actual timestamp.

Leave a comment

Your email address will not be published. Required fields are marked *