< Articles


Lessons Building A Blog From Scratch

**Update: I’ve since moved my blog to WordPress, realizing that there’s no such thing as the best technology for every scenario. Instead, I believe I need to choose the technology based on the key functionality of what I’m building. In this case, I wanted the ease that comes from using WordPress plugins, especially some of the SEO plugins like yoast. Still, this article is a great way to get familiar with React, Firebase, and good development principles. Enjoy!**

Firebase, React, and Lean Startup, Oh My! Building a tech blog from scratch has been a goal of mine for the last year. I finally got serious about it two months ago and was able to piece together enough free time to make it a reality. Here’s some of the big takeaways from this project:

Firebase: The Perfect Startup Tool

In May of last year, I had the opportunity to attend a meet-up at Google’s San Francisco office. At the time, I wasn’t particularly concerned about the topic. It could have been quilting for millennials and I probably still would have attended because uh, Google. Lucky enough for me, the topic was Firebase. Now, this wasn’t the first time I’d heard about this technology. Just weeks before, one of my roommates raved about the power of Firebase, having used it to build a live chat application for one of his coding challenges. My initial thought when learning that he had used an out-of-the-box solution for his backend was, “Isn’t that cheating?”. And you know what, it totally is. Firebase is literally a cheat code to build scalable applications quickly.

As we arrived at Google that morning, we were invited to sign up for a one-on-one with someone from the firebase engineering team. Not knowing who anybody was, I chose a random guy from the list. Just hours later, I was sitting across the table from the first engineer firebase ever hired. Among the many things we discussed, one particular quote rings true. He said, “Firebase allows you to put all of your resources on the front end”. In creating this initial iteration of my blog, I can echo what he said. My CRUD operations are nearly instant, I’m confident in my security rules and authentication, and I’ve never had a more enjoyable experience deploying my production code.

Among the many niceties Firebase provisions developers, perhaps my favorite is how intuitive they’ve made their public api. I’ll give you an example of their deployment api, which I use to deploy my production code as well as my security rules. It’s a simple four step process. The first step is to connect your machine to your Firebase account. This gives you access to any firebase project that you’ve created through the firebase console.

firebase login

After connecting to your Firebase account, navigate to the root of your application and run the second command. This create a firebase.json file at the top level of your application which we’ll use in our next step:

firebase init

Third, we’ll add some configuration to the firebase.json file. Here, we’re specifying that our public folder (the folder we’d like to deploy) is going to be in the ‘build’ folder. Additionally, we’re adding in a little route handler for React. In adding the ‘rewrites’ section, we’re telling Firebase, “No matter what URL the user tries to navigate to, still use the index.html file. React Router will handle it from there.” After all is said and done, our file will look like this:

{
    "hosting": {
        "public": "build",
        "rewrites": [
            {
                "source": "**",
                "destination": "/index.html"
            }
        ]
    }
}

And finally, we run the deploy command.

firebase deploy

With just four steps, we’ve deployed our production code. And now that all this is set up, additional deployment is only one step. After creating my production build, I simply run the last command (firebase deploy) and everything is handled for me.

Awesome With An Asterisk

While Firebase is amazing, it should be noted that it has certain quirks. One in particular had me ready to throw my computer at the wall: firebase security rules. While these have become more manageable (they added a simulator to test your rules with fake requests), the security rules still don’t provide the type of errors you would expect from a product with this much traction. With no solid error messaging, I ended up wasting an entire day looking for a needle in a haystack. Check out this code and see if you can find the two bugs:

function isSameUser(uid) {
	return request.auth.uid == uid;
}

function hasRole(role) {
	return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles[role] == true;
}

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid} {
      allow read: if isSameUser(uid);
      allow write: if hasRole('anAmazingAdminRole');
    }

    match /posts/{postId} {
      allow read: if true;
      allow write: if hasRole('anAmazingAdminRole');
    }
  }
}

There are two slight nuances with this code that compromise its success. First, the functions have to be declared in the correct context. Second, you can’t have any semicolons. While I don’t mind the no semicolon syntax, it would be nice if the Firebase error message said, “Semicolons are not allowed.” A simple error for the function could be “database not defined in this context” or even “hasRole not defined in correct context.” With security being one of the main concerns for every app, I’m hopeful this is on their radar. Here’s the code that actually works:

service cloud.firestore {
	match /databases/{database}/documents {
    	function isSameUser(uid) {
      		return request.auth.uid == uid
    	}

    	function hasRole(role) {
      		return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.roles[role] == true
    	}

    	match /users/{uid} {
      		allow read: if isSameUser(uid)
      		allow write: if hasRole('anAmazingAdminRole')
    	}

    	match /posts/{postId} {
      		allow read: if true
      		allow write: if hasRole('anAmazingAdminRole')
    	}
  	}
}

React With Typescript is Powerful

Moving on from Firebase, I have to mention how powerful React is. For a little over a year, I’ve been working with Angular. While the Angular community seems to be moving in the right direction (Redux, Observables, Typescript), I still think React is winning on the simplicity front. My experience has given me an interesting perspective in this regard. While at App Academy, I focused mainly on React and Redux. I then took a position at Xactware where I’m working with Typescript, Angular 5, and RXJS. While I’m still working at Xactware (and loving every second of it – we’re hiring), my tech stack has come full circle with this project where I’m using React, Redux, Typescript, and Firebase for the backend / hosting.

While both React and Angular ensure my app runs crazy fast, most of the React APIs beat their Angular counterparts. I’ll give you just one example. In Angular, I declare a component by adding the appropriate decorator to a class, and then add that component to the declarations array of the correct module. The declaration for the component looks like this:

// contact-dialog.component.ts

@Component({
    selector: "app-contact-dialog",
    templateUrl: "./contact-dialog.component.html",
    styleUrls: ["./contact-dialog.component.scss"],
})
export class ContactDialogComponent {}

We then include that in the declarations for a particular module (not accounting for lazy loading here):

// app.module.ts

@NgModule({
    declarations: [ContactDialogComponent],
})
export class AppModule {}

And at long last, we can include our component’s selector in another component’s template file:

<!-- app.component.html -->

<app-contact-dialog></app-contact-dialog>

Now, let’s run it back using the same scenario for React. The component declaration file looks like this:

// contactDialog.tsx

export class ContactDialogComponent extends React.Component {}

And now, we use that component in another component’s template:

// useContactDialog.tsx

export class UseContactDialogComponent extends React.Component {
    render() {
        return <ContactDialog />;
    }
}

With React, we’re given a simple API to do almost anything you can do it Angular and we can typically do it in less steps. From what I’ve seen, this means faster features and less bugs. I’m going to hold off going more in depth on this one because I’ll be diving back into it with a future post. But man, I love React (and Angular, just a little less).

Lean Startup: Only Build Features That Test Assumptions

I’ll end on a business side note because at the end of the day, I’m a businessman turned developer. After contracting out the initial UX work and settling on the final design, I felt like I was on the road to creating the next big app in tech. From the actual designs, I planned on implementing a plethora of cool features including the option to filter by tags, a nice nav bar with links to four other pages (which I would have had to create), ‘share’ buttons to share my article on various social media platforms, a related articles section, call to action buttons, and a search bar in case you couldn’t find the correct post from the ten thousand posts I’ve created to date. And being the naive programmer I am, I thought, “Yeah I’ll have this done in a couple of weeks.”

Wrong. Wrong. Wrong. As I got into the project, I quickly realized that my lifestyle (working a 40 hour per week job, golfing for 20+ hours a week – kidding, but I do golf way too much) wasn’t going to allow me to build things out as quickly as I would like to. The lack of resources caused me to ponder, “Why am I building this? What am I trying to accomplish?”. In considering this, I realized that the assumption determines the feature.

Don’t Deviate From The Assumption

Before building a feature, we should always begin with the assumption. The assumption is what we’re trying to prove with this feature. In my case, the assumption was always, “Will people value the content I create?” With that assumption in mind, I decided that the bare minimum feature needed to test that assumption was to create a simple posts page and a clean single post page with the ability to add code snippets. And you know which features didn’t contribute at all to my assumption? Pretty much everything that was originally designed. Now that’s not to say that these other features won’t have an impact on my app at some point down the road, but you have to test things one feature at a time, especially while you’re in the “This is too small to even hire myself” startup phase.

Well, that’s it folks. If you liked the post and want to subscribe to my future posts, go ahead and smash that subscribe button. Oh wait, I haven’t implemented that feature yet. Better get back to work.