Skip to content
Chandan Kumar

Gatsby blog comments using firebase tutorial - part 1

gatsby, firebase1 min read

Tutorial on integrating firebase on client side, particularly Firestore.

  1. This is part 1 that covers the following
    • install firebase in existing Gatsby project
    • configure firestore connection
  2. Use local firebase emulator
To watch this on youtube: https://youtu.be/OSGj1hB6cCc

I hope to follow up with

  1. Firebase auth
  2. Allow users to actually comment.

This post is not a complete solution on firestore backed commenting system.

Following steps are required to get this working

Install Firebase to the project

1yarn add firebase

Add a new comment component

Add comment.tsx react component that fetches data from firestore. For react component to interact with firestore we need to initialize firebase and setup firestore configuration.

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

For local development instead of talking to production firestore we run local emulator. which is accessible at 8080

1if (process.env.NODE_ENV === "development") {
2 connectFirestoreEmulator(db, "localhost", 8080);
3}

Start local firebase emulator

Using firebase emulator makes development process faster in a long run. To use firebase emulator make sure that you have firebase cli installed.

1firebase emulators:start

Once done open http://localhost:4000/ add collection blogPosts

Update comment component to fetch data from firestore

Update comments.tsx to fetch data from firestore

comments.tsx
1const commentsCol = query(
2 collection(db, "blogPosts"),
3 where("slug", "==", slug)
4);
5const commentSnapshot = await getDocs(commentsCol);
6const commentList = commentSnapshot.docs.map((doc) => doc.data()) as Comment[];

Once you have comments from firestore we set it in state and render it.

1setComments(commentList);

To render it

1<ul>
2 {comments.map((comment) => (
3 <li key={comment.comment}>{comment.comment}</li>
4 ))}
5</ul>

The entire change set would be something like below

1diff --git a/package.json b/package.json
2index 29f4857..6b19348 100644
3--- a/package.json
4+++ b/package.json
5@@ -17,6 +17,7 @@
6 },
7 "dependencies": {
8 "@lekoarts/gatsby-theme-minimal-blog": "^2.2.2",
9+ "firebase": "^9.6.1",
10 "gatsby": "^2.13.3",
11 "gatsby-plugin-disqus": "^1.2.3",
12 "gatsby-plugin-google-analytics": "^2.1.4",
13diff --git a/src/@lekoarts/gatsby-theme-minimal-blog/components/comments.tsx b/src/@lekoarts/gatsby-theme-minimal-blog/components/comments.tsx
14index e69de29..0b775f9 100644
15--- a/src/@lekoarts/gatsby-theme-minimal-blog/components/comments.tsx
16+++ b/src/@lekoarts/gatsby-theme-minimal-blog/components/comments.tsx
17@@ -0,0 +1,66 @@
18+import React from "react";
19+
20+import { initializeApp } from "firebase/app";
21+import {
22+ collection,
23+ connectFirestoreEmulator,
24+ getDocs,
25+ getFirestore,
26+ query,
27+ where,
28+} from "firebase/firestore/lite";
29+
30+import { useEffect } from "react";
31+import { useState } from "react";
32+const firebaseConfig = {
33+ projectId: "chandankumar-com",
34+};
35+
36+type CommentProp = {
37+ slug: string;
38+};
39+
40+type Comment = {
41+ slug: string;
42+ comment: string;
43+};
44+
45+const Comment = (prop: CommentProp) => {
46+ const { slug } = prop;
47+ const [comments, setComments] = useState<Comment[]>(null);
48+
49+ async function getComments() {
50+ const app = initializeApp(firebaseConfig);
51+ const db = getFirestore(app);
52+ if (process.env.NODE_ENV === "development") {
53+ connectFirestoreEmulator(db, "localhost", 8080);
54+ }
55+ const commentsCol = query(
56+ collection(db, "blogPosts"),
57+ where("slug", "==", slug)
58+ );
59+ const commentSnapshot = await getDocs(commentsCol);
60+ const commentList = commentSnapshot.docs.map((doc) =>
61+ doc.data()
62+ ) as Comment[];
63+ setComments(commentList);
64+ }
65+
66+ useEffect(() => {
67+ getComments();
68+ }, []);
69+ return (
70+ <div>
71+ <h3>Comments</h3>
72+ {comments && (
73+ <ul>
74+ {comments.map((comment) => (
75+ <li key={comment.comment}>{comment.comment}</li>
76+ ))}
77+ </ul>
78+ )}
79+ </div>
80+ );
81+};
82+
83+export default Comment;
84diff --git a/src/@lekoarts/gatsby-theme-minimal-blog/components/post.tsx b/src/@lekoarts/gatsby-theme-minimal-blog/components/post.tsx
85index b4efeee..7bc706e 100755
86--- a/src/@lekoarts/gatsby-theme-minimal-blog/components/post.tsx
87+++ b/src/@lekoarts/gatsby-theme-minimal-blog/components/post.tsx
88@@ -5,7 +5,7 @@ import React from "react";
89 import Layout from "@lekoarts/gatsby-theme-minimal-blog/src/components/layout";
90 import ItemTags from "@lekoarts/gatsby-theme-minimal-blog/src/components/item-tags";
91 import SEO from "@lekoarts/gatsby-theme-minimal-blog/src/components/seo";
92+import Comment from "./comments";
93
94 type PostProps = {
95 data: {
96@@ -71,6 +71,7 @@ const Post = ({ data: { post } }: PostProps) => (
97 }}
98 >
99 <MDXRenderer>{post.body}</MDXRenderer>
100+ <Comment slug={post.slug} />
101 </section>
102 {/* <Disqus config={{ identifier: post.slug, title: post.title }} /> */}
103 </Layout>

Comments

Copyleft. WTH
Theme by LekoArts