August 22, 2020

Building a React App to Visualize Habits as Growing Plants

Using Firebase, and SVG animation

I started this project while looking for an excuse to build something using the React framework. I had played with dynamic apps using only Javascript previously, and I knew that React handled many of the more annoying aspects of state management somewhat automatically.  

I knew that to-do list apps were very common starter apps for teaching yourself a new framework. At the same time, I was also very interested in habit tracking apps. I had even paid for a few premium versions, but had sadly found myself abandoning them one after another. 

These experiences had left me with many ideas swimming around in my head related to what I liked and hated about habit tracking. Knowing that a habit tracker app was essentially just a daily recurring to-do list, I decided that I would design and prototype my dream habit tracker app.

Don’t wanna wait? Jump to the end to find the demo link.

The Problems with Habit Trackers

After using several habit trackers, my gripes mostly fell into 2 main recurring problems.

 1) They tended to have UIs that ‘looked empty’ unless you created a lot of habits. I felt the existence of this empty space encouraged me to try to tackle a lot of things at once instead of focusing on growing one solid habit at a time. 

2) They had heavy emphasis on not missing a day to create a habit chain. I found this unnecessarily demotivational when I did miss days and I often would not bother to restart a chain once broken.

The Idea

I wanted to focus on 1 – 3 important new habits at a time and watch them progress. However, I also wanted to motivate myself to keep up with the habits without feeling like I had lost everything if I missed a day. 

I thought back to digital pets I had been motivated to check in on and even ‘walk’ as part of other apps and games. I knew I wanted to get rid of the lifeless chain of checkboxes, so why not replace it with a cute, growing plant? I drew out a rough, blurry sketch using my tablet.

Rough sketch with the idea of a ‘to-do list as a garden’ in mind.

Each habit would be represented by a unique randomly generated plant. Each time a habit was completed, the little plant would grow a little bit to celebrate.

To prevent habits from being ignored, plants could become browner or even lose leaves if they were neglected for several days.

The overall feel of the UI should encourage growing 1 or 2 plants at a time before adding more. It should be mobile friendly first since that was the primary device I used habit tracker apps from. However, I liked the idea of a desktop friendly habit tracker too and had it noted as a ‘nice to have’.

Tightening the Design

With the idea somewhat taking shape, I moved to Sketch to mock up exactly what I would need to build. At this stage I just wanted to identify the basic views and functions I would need to make the app. Normally I might not go past a quick sketch, but as I was planning to learn React during this project I wanted a very clear idea of what I was trying to accomplish.

I used clipart as a stand-in for the randomly generated plants, which I wasn’t sure how I was going to create yet. In a bit of foreshadowing, I naively assumed I would figure the plants out easily later. Here’s what the final file looked like:

Homepage, create, view, and edit screens for Habit Garden.

I imported these files into InVision to quickly roughly prototype how the views would link up and identify any missing navigation or options. 

View the Interactive Prototype for Habit Garden.

Beginning Development

With a clear idea of what I was building, I was ready to dive into React. I used this React portfolio tutorial to get started, but you could follow any guide that includes steps on setting up a React project.

Note: I won’t go through each line of code in this guide. Instead it will be an outline of steps and a rundown of my thinking at the time.

  • Create a new project directory, navigate to it, and initialize a github repository with git init
  • Create a new react app using the create-react-app command
  • Optionally, install react-bootstrap and node-sass to have access to Bootstrap classes and SASS stylesheets while building the front-end. 

Deciding on a Database

I wasn’t sure how far I wanted to take this prototype, but I did want to use a web-based database in case I decided to take it pretty far. I was imaging something that would allow several friends to create accounts, log in, and grow their habit gardens.

⦸ What Didn’t Work

Google Sheets
After coming across this blog post (https://blog.usejournal.com/how-to-use-google-sheets-as-a-cms-or-a-database-f9d8e736fdce), I I initially opted to use a google sheets as a database. However, I couldn’t get google’s node.js api and my version of python to get along. After trudging through a lot of reinstalling and errors, I decided that using google sheets as a database might be more trouble than it was worth. This was supposed to be the simple/quick option!

Finding Firebase

I briefly looked at MongoDB before stumbling onto Firebase. Unlike MongoDB, Firebase is a database-as-a-service. This means there is a 3rd party handling data and that any app that becomes popular will need to pay to cover resources. However, for the purposes of a quick prototype it saves us a lot of work. It also makes real-time updates a breeze.

    I knew I needed to set up and start reading/writing data between my Firebase database and the React app. To help me implement the basic CRUD functions I’d need, I found and followed this great tutorial on Youtube . Many of the basic things I needed to do, like letting a user input data into a form and then updating that value on the database, are covered in some form in this video.

Study Break / Back filling Knowledge on React Basics using FreeCodeCamp

    I began to hit blocks where tutorials failed to tell me exactly how to proceed. I was learning a lot about React, but I began to notice that lack of knowledge of some fundamentals was causing me to spend long amounts of time solving simple problems. Now that I had a project to give me an idea of the specific tasks I wanted to do,  I spent some time filling in some knowledge by completing exercises related to the tasks I needed to do at FreeCodeCamp.

It’s Finally the Fun Part! Developing the Plants

With this info in mind, and using the Youtube tutorial above as a guide, I wrote the functions to create, edit, and delete habits. I also added functions to track and modify how many times a habit checkbox had been checked. The generic skeleton of the app was coming together, but I hadn’t really figured out how I would generate the plants yet.

I knew I wanted to create custom SVGs for each habit plant. I knew I wanted these SVGs to be generated from a few basic pieces of data – like plant type, color, and # of times a habit has been completed. 

I just needed to scour the internet for a solution for generating the plants.

⦸ What Didn’t Work

Hand illustrated Plants
My very first idea was to use existing plant art and simply reveal a piece each time a habit was completed. However, I quickly realized this wasn’t truly generating anything and would require a huge variety of plant art to be created by hand. I wasn’t satisfied that this solution satisfied the original idea.

L-System Fractals
The next idea I came across were Lindenmayer systems, or l-systems. This is a type of fractal that creates plant like shapes. After reading about them in the ‘Cartesian Faith’ blog, I was very excited to learn that, once implemented, all you needed to do is feed the algorithm a number to generate a plant. Surely I could simply provide the count of times the habit had been completed and we’d be off and running. 

Examples using L-systems to create an image of stems and leaves.

So, why are L-systems under the ‘didn’t work’ section? There were several downsides to L-systems that finally led me to abandon the idea. The plants generated were not only alien looking and tough to customize, it was difficult to ‘grow’ the plant in small steps. Each time I increased the # the algorithm was given, another iteration of plant growth was added. This meant lots of new branches and leaves each time instead of just 1 or 2 new leaves. 

Although I still think they could have been a cool solution, it was looking like l-systems were going to take a lot more adaptation than first thought. I decided to look elsewhere. 

Eureka! SVG Plants from an Old Flash Function

The next thing I found was much more promising: An svg plant generator based on some old flash code looked and moved in a way that was close to what I was initially imagining. It also had few dependencies: just .svg art files and Greensock, a popular animation library. 

A view of the commented plant creation function in Codepen

After studying the sample above on codepen and commenting up a copy for reference, I was ready to begin adding plants to my project. Specifically I needed to:

  • Install dependencies, Lodash and GSAP (Greensock Animation)
  • Create some SVG art of different pots for plants to sit in
  • Adapt the sample from the website in several important ways:
    • Randomize the color, shape, and size of the leaves, and planter that plants sit in. 
    • Draw the length of the plant stem and number of leaves based on a single numerical value representing the number of times we’ve completed our habit.
    • Animate plants between REACT state changes

Generating Random Plants with Character

To accomplish the custom plants and display the same plant each time a user visited, we would need to store the plant’s ‘blueprint’ in the database as a series of values. Whenever a new habit was created, a corresponding plant blueprint would be generated from a function that randomly chose a pot and a leaf shape from lists of options. Plants would also get a unique RGB color value so that leaf hue would differ from plant to plant.

Leaf shape, planter pot, and plant colors being randomly determined for a new habit.

It took some fiddling to ensure that randomly generated leaves did not outpace their stem or stray too far away from touching it. It was also unwieldy to grow plants upward forever, so I designed the algorithm to slow growth as the habit gets to the higher numbers, and then stop growth altogether.

Note: During this section I referred to Greensock’s documentation many times, especially their React documentation.

After a lot of tinkering, the app could successfully generate a unique, happy potted plant for each new habit! 

This lil’ guy could not be more excited to track your meditation habit.

Deploying the App

Initially Habit Garden was designed with a checkbox that could be checked once a day for credit towards a growing habit. This would require the firebase server to run a cron job once a day to reset the checkboxes. 

However, implementing these jobs on the Firebase has associated costs. Although they were minor (in range of 10 cents a day), I wanted to avoid paying for services for a prototype. Needing to wait a day between increasing the habit counter would also make it more difficult to test the prototype and see the various random plants take shape.

Bringing the app to a ‘full-featured’ state would require not only the cron job, but user creation and account management as well. These features offered nothing unique or experimental however. 

For these reasons I opted to deploy the app in its current state as a fun test of the habit visualization idea. I followed a guide on Firebase to deploy the app to the web quickly and easily.

The finished application

Try out the demo and make your own Habit Garden now!

Note: Everyone shares the same demo, so others will see the habits you create.

Future Improvement Ideas

There is still a lot that could be added to this idea. Ideally I would like to create a ‘flowering’ function that would start to draw blooms on plants once they had matured a certain number of days. It would also be nice to implement a function to make the plant hue browner according to the number of consecutive days gone by without completing a habit.

Thinking further into the future, allowing users to unlock more exotic plants would be a fun way to reward sticking with habits before starting new ones.

Thank you for reading!

I’d like to hear your questions and comments about this project. Feel free to contact me.