Build an asynchronous nutrition app on Streamlit

Gustav Collin Rasmussen
3 min readAug 13, 2022

--

In this blog you will be guided through how Streamlit can be used to share a web app which consumes data from the Nutritionix API asynchronously using the httpx package in order to break down a meal into it’s key macro ingredients (protein, fat and carbohydrate).

Generated by DALL-E 2

Firstly, enjoy a demo of what we will be building:

Prerequisites: sign up for a free profile on Streamlit:

as well as on Nutritionix:

Obtain your free API keys from Nutritionix, they will be needed shortly.

Create a new Python module, named streamlit_app.py

and add it to a new GitHub repository named nutrition-planner

On streamlit.io, deploy a new App that points to the URL of streamlit_app.py. Next, visit the App Settings and go to Secrets where you will be storing the nutritionix API keys obtained in the previous step:

Returning to the streamlit_app.py, insert (after installing) the necessary package imports:

In order for Streamlit to use these imports, you will need to add some of them to a requirements.txt file:

Back to streamlit_app.py, set a Streamlit title and description, adding your name:

Prompt your users for the number of key ingredients in the meal they wish to analyze:

Setting up a dictionary placeholder for the meal ingredients, looping over each of them in order to prompt their details (name, amount, unit) from your user, storing them back to the placeholder and validating that their datatypes are correct:

Set up the Nutritionix URL and load in your API keys as Streamlit secrets,

as part of the request header:

Prepare another dictionary placeholder, this time for the macro nutrient data:

nutrition = {"protein": 0, "fat": 0, "carbs": 0}

Now define an asynchronous function get_nutritionix that for a given amount of a certain food ingredient will perform a HTTP post to lookup macro nutritional info in nutritionix and store it back to the nutrition dictionary:

This will then get created as a task inside our next async function main for every key ingredient. main will be using the AsyncClient from the httpx package as a context manager named client , allowing us to use a lower level API and only needing to send the headers once. The body sent will contain the user-provided ingredient info and a timezone. Finally, all tasks are gathered.

Set up timing with the time package: start_time = time.time()

Then execute the main function asynchronously: asyncio.run(main())

Render the total meal macros as well as the total time spent on calling Nutritionix:

Finally, render a barplot with the macro results:

Giving a barplot such as the following:

200g of brown rice, 150g of broccoli & 120g of chicken

You now have a fully functional nutrition app hosted on Streamlit!

The complete source code can be found here:

Try out the app here:

https://thenewthinktank-nutrition-planner-streamlit-app-sunft6.streamlitapp.com/

Considerations

The free plan on Nutritionix grants you a few hundred API calls per day,

so in case you would wish to scale your app further, there are also paid plans available.

--

--

Gustav Collin Rasmussen

Gustav is Tech Lead in R&ED (Research & Early Development) at Novo Nordisk in Denmark, holds a MSc in Physics and really likes Cloud and Platform Engineering