Sure, writing HTML is easy—but letting users log in, save data, search, and purchase is much harder. Most people who try just give up.
Luckily, new tools are making it a lot easier. I made a boilerplate with everything I've learned about React and Firebase so I could ship my own projects faster, and it's made creating new projects incredibly fast. That's Firefly.
Philosophy
- Low cognitive overhead - There's not much code in Firefly. It has no server to monitor, no database instance to host, and no REST API to maintain, no containers, no password salts, no webpack config, no CSS framework, no ORM, no forms library, no Redux, and no SQL. It's just JavaScript.
- Built for learners - Everything about Firefly was made to help developers learn to make apps as quickly as possible. The codebase is readable, and includes helpful comments and readmes throughout. This page includes videos and guides that will walk you through it every step of the way.
- Production worthy - It’s a real app, including CRUD, full text search, SSO auth, payments, and relational data. Firefly has real security built in, is easily extensible, and has separate dev, staging, and live environments. It's even 12 factor complete.
- Forward leaning - Firefly embraces modern JavaScript, the large NPM ecosystem, single-page front-end applications, serverless backends, schemaless databases, and using 3rd-party APIs for things like auth and search. It's primarily based on Create React App and Firebase, Google's beginner-friendly cloud platform suite.
- Reasonably stable - There are very few Firefly dependencies, and most are used by large tech companies in production, are popular in the community, and will likely be supported for years to come.

Does your team need some design help?
I'm an experienced startup designer who helps companies untangle problems and make products people love. Hire me or learn more.
Getting Started
This section will show you how to create a new app, customize it, and ship it live. Once you get the hang of it, making a new app only takes a few minutes.
Firefly isn't a framework or library—it's just a boilerplate. Once you copy the Firefly code, you can change it to do whatever you want.
Before you begin
Make sure you have git and Node JS installed.
Run npm install -g firebase-tools
to install the Firebase command line tools. After it installs, run firebase login
. You only need to do this once per computer.
Installing the React extension for Chrome DevTools is also a good idea.
Creating your app
We're going to clone the Firefly repo onto your computer, create Firebase projects in the Firebase console, and then add keys from the console to your code.
Get the code
Because Firefly is a boilerplate, we start new Firefly projects simply by making a copy of Firefly.
- In your terminal,
cd
to the folder where you want your project to live - Clone this repo by running
git clone https://github.com/sampl/firefly
- Move into the folder you just created with
cd firefly
(you can also safely rename thefirefly
folder to the name of your project) - Run
npm install
in the main project folder to install all the JavaScript packages Firefly needs. Runnpm install
in the/functions
and/scripts
folders, too.
To make the project your own, simply find-and-replace all the instaces of "Firefly" and "posts" to match your own project.
Connect to the database
Firefly projects only have one codebase, but use three Firebase projects. Each project has its own URL and its own separate copy of the database. This lets you develop and stage your app without affecting the live version.
- Go to the Firebase console and sign in with your Google account
- Create three new projects, and name them something like
MyProject Dev
,MyProject Stage
, andMyProject LIVE
Now let's connect our app to the databases by adding the database keys to our app's environment files. You should not commit keys like this to version control, so first we'll rename our environment files to match the names in our .gitignore
.
- First, rename
.firebaserc.example
to.firebaserc
- Rename
.env.dev.example
to.env.dev
, and do the same thing for the stage and live.env
files - Now back on the Firebase website, click "Add Firebase to your web app" for each new project
- You'll see a block of code with info like "project id" and "API key"—add these values to your
.firebaserc
and your the respective dev, stage and live.env
files
Set up your Firebase projects
Before you can add any posts, you'll have to allow sign-in with Google. Firebase makes this very easy.
- Back in the Firebase console, click on "Authentication" in the sidebar on the left
- Click "Set up sign-in method"
- Click "Google", toggle the "Enable" switch, and hit "Save"
The Firestore database is still in beta, so you'll have to enable it for each of your projects:
- In the Firebase console, click on "Database" in the sidebar on the left
- Under "Cloud Firestore Beta", click "Get Started"
- Choose "Start in test mode" and hit "Enable"
Firebase Cloud Functions only work if your project is on a paid plan, so upgrade your Firebase project to "Blaze". This should still be free to use (unless you get a lot of traffic), but you will need to add a credit card.
Firefly comes with a search powered by Algolia. If you don't need search, you can simply remove all files that contain the name "Search". To enable search, create an account, configure your functions credentials. See the readme file in the functions folder for full instructions.
Running the app
When you're finished setting things up, start your app by running npm start
in your terminal. You should see a basic web app appear in your browser!
Try logging in, then make sure you can create, like, edit, and delete posts.
Now go back to your text editor and try editing some files. When you save, the changes should automatically appear in the browser without refreshing.
Now is probably a good time to CTRL-F for all the instances of "Firefly" in the codebase and rename them to the name of your project. You should also probably do this for "post", too.
Going live
First, you'll probably want to buy a domain and connect it to your project on the Firebase console hosting page before going live.
Before going live, secure your app by writing rules in the firestore.rules
file.
You can deploy your project to your test stage URL by running npm run stage
.
When it's time to ship, run npm run live
. You just shipped a fully-functional web app!
🎉 🎉 🎉
Don't forget to checkout the Next Steps section to see all Firefly features.
How it works
By default, a Firefly project shows a list of "posts". Users can read individual posts or search for posts. Once they log in, they can like posts or create and edit their own posts. They can even buy a subscription to the site. Try the live demo to see it in action.
Views
Most of Firefly is built with React. If you're not used to React, start by reading the excellent official React guide.
The main UI of a firebase app is a bunch of React components in the /views
folder. Think of them almost like templates—their job is mostly to show HTML. These are mostly written in the simple functional React style.
Styles
Firefly uses styled-components
to add CSS to your components. These are React components written with CSS, and they live in the /styles
folder.
Routing
The router is the part of the app that shows different React components based on the browser URL. React has no built-in router, so we use the popular React Router. Our app's routes live in the Routes.js
file.
Data
Firefly uses Firebase's NoSQL Firestore database for saving data. Firestore organizes your data into collections (kind of like SQL tables) which have documents (kind of like SQL rows). Before you go much further, you should read the Firestore docs.
Queries
In Firefly, your views query the database right from the browser. Firefly uses react-firestore
components to listen for changes from the database and pass the data down to the views using the render prop pattern.
Actions
So how do you let users change data? The answer in Firefly is "actions", normal JavaScript functions that live in the /actions
folder. You import these files into your views and call them when a user clicks a button or submits a form, etc.
For example, when the user wants to add a post, the PostNew
view will call the addPost
action, which will send the new post to the database. When the database gets the new post, React will automatically update our list of posts.
Actions use JavaScript promises to make async requests and error handling easier. This means you can show success or error messages in your views using .then()
and .catch()
.
Security
Because any browser can write data directly into your database, you need some rules to keep hackers from deleting data or seeing private data. Firefly comes with a default set of rules that you can use (this article explains how they work).
Relational data
Handling data that "relates" to other data is one of the trickier parts of web development. Most sites use backends that run SQL joins on their database—but because Firestore is a NoSQL database, you'll need to handle this differently.
Most of the time, you can just save the ID of a document on another document.
For example, each "post" includes the ID of the user who wrote it. To decide if a user can edit a post, Firefly checks if the post's createdBy
value matches the logged in user's ID.
To handle things like sorting, Firefly uses another trick: some documents have attributes that are automatically updated by the backend. These attributes have an underscore at the beginning of their name.
For example: when you "like" a post in Firefly, the Firebase client adds a new "like" to postLikes
in the database. Then, a Firebase function watching that collection finds the post you liked and updates the post's _likeCount
attribute. Now the browser can query and sort posts by _likeCount
(but users can't edit other users' likes).
Authentication
Firefly uses Firebase Authentication for logging users in.
It also includes a FirebaseAuth
component that listens for auth changes and updates views. This means you can call the logIn
action anywhere and the rest of the app will automatically update.
Other stuff
Firefly uses Create React App to take care of transpiling, bundling, linting, and running tests. You don't have to write or manage any configuration for this to work, just run npm start
.
The deployment scripts use Firebase hosting to host your app when you're ready to go live. Firebase hosting comes with HTTPS for free, and it's the same price as Google Cloud Platform object storage (cheap), and works well with the other Firebase services like backend functions and your database.
Next Steps
If you want to charge users, there's also a sample Stripe integration for creating subscriptions. If you're not asking users for money, you can get rid of the files with "subscription" in the name. If you are, add your Stripe keys to the .env
files and your Firebase functions config.
You'll eventually need to Create a Service Account before you run the scripts in the Firefly "scripts" folder.
Firefly also comes with Google Analytics for tracking page views and Sentry for monitoring errors. To use them, just create an account and project on each site, then add your tracking codes to your .env
files.
Because Firefly is just a boilerplate, there are plenty of other ways to extend your app:
- Firefly is just a JavaScript app, so adding JavaScript packages is as simple as running an
npm install foo
and addingimport Foo from 'foo'
in your code. - The Create React App user guide has a ton of great guides for adding things like CSS Preprocessors, unit testing, and more.
- This Awesome Static Website Services has a lot of examples of things that you can integrate with a Firefly-style app.
- Firebase has a large repo of Firebase functions samples for common backend tasks like sending emails.
That's it!
If you're having trouble, remember that learning web development is hard. Take small bites, Google what you don't understand, and keep at it. Eventually you'll build something amazing 😎.
Did I miss something? Was something confusing? I'd love to hear from you; submit an issue or pull request.
Thanks to Luke Persola, Chris Schneider, Andrew Walton, Brett Warner, and Aaron Fifer for thoughts and help with this project.