The name was suggested to me after announcing that I was designing this tool which was “cool enough to slice through the cake of life”. The X at the end was more so for domain naming and IP reasons.
LifeKnifeX aims to cover the “slices” of life that pertain to goal-setting, personal performance metrics, continuous improvement of oneself, and discipline in areas one could call “classic offenders”, such as diet and habit.
The above screenshot of the home page is where users land, giving them a high-level overview of what possible areas the site provides assistance with in one’s life. As of these screenshots, this includes Nutrition and Goals.
The idea between these two modules, designed as equally applicable to the other planned modules on the home page, is about regular check-ins, and being rewarded for consistency of attention paid to these areas. Such reward would take place through the Score function, though Score will not be covered in this post.
The Nutrition card provides both direct access and shortcuts to deeper functions within the module itself. When a user first decides to Visit nutrition, they’re likely meet with a notice that they’ve yet to log something they consumed.
The app is intelligent enough to display a different message if the user hasn’t logged any food to begin with. In this situation, the Food Library button disappears, and the message changes to inform them that they must first add a food they wish to log.
Upon navigating to the Food Library itself in this situation, an appropriate and similar message is shown there, too.
The form to add a new food allows a subjective determination of whether it’s of good or bad quality along a Likert scale. This food can also have an image assigned to it for quick reference, and to be easy on the eyes.
Once the food is added, a confirmation toast is shown as such:
It will then appear in the Food Library, replacing the previous guidance message.
Since Django is used for the back end, it makes for easy management of
Food and any other model in the app:
One can then log a nutrition (or consumption) record against that food. In doing so, one can specify the food they ate , when they consumed it (because ice cream sounds good for lunch), and how much they had.
The When field is generalised to hour groups of the current day no later than the current hour. This is to dissuade users from allowing a backlog of consumption records to build up either in their head or on paper; by logging it at the source as soon as possible, the app works to encourage a general philosophy of consistency and discipline.
The intrinsic benefit and purpose of the Quantity field is to have a more complex version of
Quantity • Quality to categorically rate a user’s health in each consumption, and then generate statistics across days or any arbitrary time period.
Saving a consumption record shows a similar toast to before:
This consumption then appears in the list, once again replacing the previous empty message on the corresponding page:
Similar to before, this can be seen and managed in the admin:
When visiting the Goals section of the site, one is met with a similar guidance screen to before:
Adding a goal is performed through a similar procedure, clicking on the big pink button to bring up a form:
The Question, Style, and Start Date fields should be familiar and self-explanatory to many, behaving as intuition would have you guess. However, the Test field is slightly nuanced.
The idea, following on from the precedent set by a
Goal, is to allocate accountability to users to ensure continued contribution; this then helps the app help them. By choosing one of At least every or No more than every options, the user gets to define both the sentiment, and the priority of the goal in question; this effectively says whether the goal is intrinsically good or bad.
The final Test option, Never provides no penalty or action taken on the user not contributing answers.
Goal shows a similar toast message, and then redirects to the Goals page to show the newly saved item:
This can then be viewed in the admin:
The admin can also edit a
Goal, much like other models:
When a goal hasn’t been answered on the current day, an exclamation mark will appear in its card. A user can then answer that goal by clicking on the pink Log Answer button, bringing up the answer form:
Considerably simple, this page shows one goal at a time, allowing the user to choose an answer defined by the Style of the goal as seen the previous form.
Once answered, the previous warning message will change to show success against answered goals, depending on the Test:
Following the now-classic admin pattern, an administrator can edit any answer:
The application is broken down into a React front-end and a Django back-end. The Django back-end uses the standard PostgreSQL database without any frills, and exercises Django REST framework for communication from the front-end.
This was created with (and still technically uses) create-react-app, but the project was initially created some time ago; as a result, it uses the older method of
npm install in place of
yarn and other similar commands.
It uses Redux Toolkit to make Redux marginally bearable (more on that story later) for state management, and the wonderful and stunning Semantic UI React integration to make things look pretty. Icons are provided via React Icons, which we will see in action shortly.
Aside from the aforementioned PostgreSQL and Django REST framework, this Django application doesn’t do anything particularly out of the ordinary. Django’s incredibly convenient model and migration management (alliteration not intended) make for a humorously fast development experience, especially when there are no views to be configured.
This site could have been made using the standard MERN stack, and while there’s nothing wrong with that intrinsically, I was curious (at the time of this application’s development) to see what Django was like when communicating with another stack for the front-end.
Similar to the previous Stopclutch app, both the front-end and back-end use GitHub Actions for testing and deployment checks:
Once all checks pass on a merged pull request to
main, Heroku will detect this and automatically the appropriate app to the staging
environment. After manual inspection to ensure
staging works as expected, this can be promoted to
Contrary to what it may seem, this was a big project, especially to take on alone. I have a fair number of such small app concepts that I like to try out, often in new languages; this gives me a good idea of how much time and effort an idea will usually take, and as a result I tend to have a good idea of project feasibility.
Here, however, I discovered so much about the front-end from the back-end, and vice-versa. The work increased dramatically as a result; it was here that I had newfound respect for full-stack developers out there in industry. Ironically I’m one of them in a professional capacity, and yet still this took me by surprise.
The lesson learned here was to start small; it’s easy to know when something is too small, but often times your internal alarm as a developer won’t go off when your idea isn’t quite bite-sized enough.
The front-end uses Semantic UI for theming, and more recently I started a branch to see what it would look like if I shifted everything to Bootstrap. The working copy looks like this:
I very quickly realised that the app would have been considerably more valuable had I stuck with contributing to the core internals and mechanics of the app, instead of playing around with theming. Being both the developer and the user of the app, I could quickly imagine myself complaining at the developer (if the poor soul weren’t me) about not putting effort where they should.
CRA is a good example here).
After this experience, it has made me think twice before starting up a React app as a knee-jerk reaction, and instead viewing slower-moving (or perhaps more mature) stacks with greater respect and temptation.
This has been an incredibly educational experience that has given me newfound respect for both developers and stacks. This isn’t a project I feel particularly compelled to continue however, for the main reason that I discovered how it adds more work to my day to contribute such diet and goal logs than it does give back.
This is really something I had to implement to truly understand, and so this has by no means been a waste of time. All in all, thank you for reading through to the end!
Until next time, all the best!