"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:
- Define Async Function:
- fetchServerTime is an async function because Firestore operations (setDoc, getDoc) are asynchronous and return promises.
- 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.
- 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.
- 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).
- Update State:
- setServerTime(…): Updates the serverTime state with the ISO string, triggering a re-render to display the time.
- 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.