I wanted a blog where I could write on a text editor, that had saving functionality and that was capable of controlling whether I wanted to post these to the public.
If you're a person that comes from a CS background like me you'd probably familiar with backend frameworks like Express, Django. I had prior experience with Express.js, NestJS, Django in the past building simple backend APIs. So I could have gone with just these to really do what I wanted. But honestly I recently started learning go and wanted to try building backend APIs with golang.
Since I didn't really have that much experience I thought it could take longer to actually work on this since I already had a full-time job where I had to code all day. So I decided to just develop fast and refactor, or migrate later to golang.
I have worked with firebase in the past, like 4 years ago and at that time, it was kind of hard to still grasp everything but this time, setting up the whole firestore and auth didn't even take 3 hours.
My blog CMS application was really simple and I tried to have the simplest functionalities on it as possible. Solving simple problems one by one turned out to be more productive than most cases I've developed.
There are many ways to set up firebase app inside your React application. For me I wanted to call these "service"s and created related business logic inside the services folder.
// service/service.ts
class Service {
private static instance: Service;
private static firebaseapp: FirebaseApp;
constructor() {
Service.firebaseapp = initializeApp(firebaseConfig);
}
getService() {
if (!Service.instance) {
Service.instance = new Service();
}
return Service.instance;
}
getFirebaseApp() {
if (!Service.firebaseapp) {
Service.firebaseapp = initializeApp(firebaseConfig);
}
return Service.firebaseapp;
}
}
As seen above we'll first create a Service class that returns a firebaseApp instance that has been initialized.
We use something called a "singleton" pattern here to use only one initialized instance.
The service
instance accepts a firebaseConfig parameter so we'll have to add the next piece of code in the top.
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_APIKEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTHDOMAIN,
projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_APP_ID,
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID,
};
For these configuration variables you would need to login to your firebase console and find the values and include them inside your .env
file.
Lastly we'd export an instance of our service class.
const serviceInstance = new Service();
export default serviceInstance;
This would allow us to work with firebase from now on.
Next, we'd need to create two additional services which are
Image service is used for registering thumbnail images for the posts we're going to write in the future. The Blog service is a simple CRUD service that allows us to read, write, update, delete posts that inside our database(which in our case is firestore).
class ImageService {
constructor() {
}
}
For storing images we'll use a storage. Normally if this was done through an AWS, probably we'd be storing our images inside Amazon S3 bucket. Probably we'll be doing that in the future.
class ImageService {
storage: FirebaseStorage;
constructor() {
const app = serviceInstance.getFirebaseApp();
this.storage = getStorage(
app,
process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET_URL
);
}
async uploadImage() {
// write uploadImage logic here
}
}
We'll get our initialized firebaseApp using our getFirebaseApp()
method from our service instance and we'll get our Firebase storage instance using getStorage
which is a method from firebase module.
First we can assume that an image file will come in through change event that's from an input element.
<input type="file" onChange={} />
And when that happens that will be passed into our uploadImage()
method.
import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
const blogRef = ref(this.storage, `blog/${imageFile?.name}`);
const snapShot = await uploadBytes(blogRef, imageFile, {
contentType: "image/jpeg",
});
const downloadUrl = await getDownloadURL(snapShot.ref);
const imageData: uploadImageData = {
imageUrl: downloadUrl,
contentType: snapShot.metadata.contentType ?? "image/png",
contentDisposition:
snapShot.metadata.contentDisposition ?? "inline; filename*=utf-8",
name: snapShot.metadata.name,
bucket: snapShot.metadata.bucket,
};
return imageData;
We retrieve reference of the storage point where we want to store the data and by using uploadBytes
we upload our image file to the remote storage.
After that we get a downloadUrl or somekind of URL endpoint for the image so that we can store it with the data we need to use in the future.
That is it for this post, we covered how to set up a simple firebase instance and upload image from the client side to remote storage.
Next time, we'll look into creating our Blog service and start creating UIs for the frontend as well, Thank you for taking your time to read!