Preact + Firestore + MobX = ❤️

If you haven’t been living in a cave for the last couple of month you’ve probably heard of Preact, a 3kb alternative to Facebook’s React. But do you actually know how easy it is to build a PWA (Progressive Web App) with all the bells and whistles like sign in, realtime database, etc. just with a bit of Firebase and MobX?

What are we making?

For the sake of this tutorial we’ll be building a small Chat App. A live demo can be found here and I have also uploaded the code to GitHub.
The approach we’re using is to store all messages in Firebase’s Firestore and to listen for changes to update the UI in realtime as new messages arrive.

How are we making it?

The way we are implementing the chat app is that we will have a representation of the database in our local app in MobX, a great alternative to Redux and Flux by the way. Then when data changes in the database (e.g. a new chat message), the state in MobX gets updated which then updates the user interface.

Initialize Firebase

Now that you hopefully know what and how we’re making our own chat app you should go to console.firebase.google.com and create a project.
Then open it in the web interface and click on the small gear icon at the top left corner. Then click on “Add Firebase to your web app”

Install Preact and MobX

Getting started is pretty straightforward: Install Preact CLI if you haven’t already and create a new PWA with preact create material <name> .
After you’ve enjoyed the awesome loading spinner, go ahead and install Firebase and MobX: npm i firebase mobx preact-mobx --save .

By now you should be able to spin up a development server on localhost by typing npm run start . Nice!

Initialize Firebase

Now that you hopefully know what and how we’re making our own chat app you should go to console.firebase.google.com and create a project.
Then open it in the web interface and click on the small gear icon at the top left corner. Then click on “Add Firebase to your web app”. Copy the config, create src/state/firebase.js and paste it into the file. By the way it is not a security concern to publish your config, all the keys are public. Then require Firebase and Firestore so the file looks like this:

src/state/firebase.js

Great! Let’s start coding!

Now delete src/routes/profile, remove the profile component from src/components/app.js and import preact-mobx so it should looks like this:

src/component/app.js

Get started with MobX

Then create a file called chatStore.js in src/state . In there we will use MobX to manage the state of the app and respond to changes in the database. First we will define our two classes, ChatStore and Message .
ChatStore stores an array of the Message class. This class on the other hand stores the id (generated by Firestore), the content of the message and a timestamp.

src/state/chatStore.js

But we can’t use the new classes yet, we have to add an action to our ChatStore so we can add a new message to the messages array (don’t forget to import ‘action’):

part of src/state/chatStore.js

Set up Firestore

Now that we can add messages to our state we need to actually get the messages from the database. For that we head back to the Firebase Console and go to Database > Try Firestore Beta > Start in test mode.

Then after everything got set up we create a new collection named messages with a document with an auto-id and two fields:

If you want you can add a few more documents with an automatically generated ID following the same scheme.

Listening for changes

After that is done we only have to listen for changes in the database and fire the addMessage() function for each new message. We’ll do that in a new file that we call initState.js also inside src/state . The onSnapshot function also gets fired on the initial render, so we don’t have to worry about getting all the messages on first load:

src/state/initState.js

Bringing everything together

The final step is now to get the state from MobX into our Preact component. Luckily that is very simple. We need to import the ChatStore from src/state/chatStore.js intosrc/index.js and then pass it as a prop to src/components/app.js so we can call initState() to get the actual data from the Firestore. We also pass the chatStore to the home component to render the messages there. Remember to add @observer from preact-mobx to every component using the ChatStore . Otherwise the component won’t re-render on state change.

src/index.js

Now we can get the messages in src/routes/home/index.js and map through all the messages. I know that the design isn’t that nice. But it’s not about design today 😉.

src/routes/home/index.js

Sending Messages…

… is really easy now. We only need to add one small function to the Home component which gets the value of an input element and tells Firebase to create a new document with an auto-generated ID:

src/routes/home/index.js

Bonus: Deploy to Firebase hosting

Now that we have a working chat app we also want to have it only, don’t we?
And, again, thanks to Firebase that’s very easy too. Just install Firebase CLI globally like this: npm install firebase-tools -g and initialize the project like this:

firebase login
firebase init
preact build
preact serve --server config

Copy the output of that function into firebase.json and finally upload the build files with firebase deploy to Firebase Hosting!

Wasn’t hard at all, was it?

So what’s next?

By now you probably should go over the code again and make sure you really understand what the code is doing and maybe add some styles to the components to make it look a bit more exciting.

You could also think of implementing a sign in method with Firebase Auth or first just making sure that the messages are ordered correctly (They aren’t). Or read the docs about Firestore security rules to ensure no one can abuse the database :)