Boosting Productivity: A Guide to Building a Reading List App with Notion and Flutter Web
This post will demonstrate how to use Flutter Web to create a dashboard displaying our reading list. The dashboard will show the books we are reading, those we have already read, and the ones we plan to read.
For the development of our application, we will use Flutter to create our Web-based dashboard and a Notion database to manage persistence and save the list of our books. The final result can be found here: My Reading List
The code for the application is available in this repo on GitHub: myreadings-flutter licensed Apache 2.0.
Notion Database
A Notion database is nothing more than a table that can have columns characterizing the data and can be sorted according to different sorting criteria. For this project, the columns that have been created have this meaning:
Finished: indicates whether or not the book has been completed
Cover: link to the image of the book cover taken from Amazon
Title: title of the book, in my case in Italian
Author: author(s) of the book. In this case, the value is put directly into the cell and there is no relation to external master tables
Date: the date on which the book was finished and which is used later for sorting
Progress: number representing the percentage progress of pages read compared to total pages read
Link: sponsored link to Amazon
In order to access our Notion database from the outside via the API provided we must first create an Integration to which we must give read privileges to our database. Once the application is created we will be given a secret in the form secret_XXX
which we must use to authenticate ourselves in our calls to the Notion API. Following the documentation, to access a Notion database via the API the call to make is this:
curl --location 'https://api.notion.com/v1/databases/${NOTION_DB}/query' \
--header 'Authorization: Bearer ${NOTION_SECRET}' \
--header 'Content-Type: application/json' \
--header 'Notion-Version: 2022-06-28' \
--data '{
"page_size": 100,
"sorts": [
...
]
}'
Where two variables are present:
NOTION_DB: which can be found in the URL of the page that corresponds to the database
NOTION_SECRET: is returned to us when we have created the integration to use the API
In my case, I also set up a particular sorting in which the sorts
array where the call, as stated in the documentation for Sort database entries, is made like this:
"sorts": [
{
"property": "Finished",
"direction": "ascending"
},
{
"property": "Progress",
"direction": "descending"
},
{
"property": "Date",
"direction": "descending"
}
]
Because I want the books I haven't finished yet to be there first and then the ones that are completed, the ones that are being read to be sorted by the progress field, and finally the ones that have been read I want to have sorted from the one I finished most recently to the one I read first.
This way I can modify the Notion database as I want, adding books, editing information, and automatically the results will be displayed within the dashboard.
Flutter Web App
The Flutter application is very simple because it only cares to make a call to the Notion API via the http package and displays the results in a grid, with the help of the very useful flutter_staggered_grid_view package (about which I have already done an article here). Other packages that were used in the project are:
riverpod to manage the application state and HTTP call via a provider and its repository
go_router for navigation and routing
percent_indicator for the loading bar indicating progress in reading
super_banners for the banner above the card for the status of planned and read
url_launcher for opening the link to the Amazon page upon clicking the button
The end result is as shown in the figure:
Insights
As reported in these two discussions on StackOverflow: Notion API, Vanilla JS, Fetch does not work [duplicate] and Can I use fetch to call the Notion API?, it is not possible to call the Notion API directly from a web page due to a problem with CORS; to solve this problem, a Cloudflare Worker was used that acts as middleware between the web page and the Notion API allowing for a result that then returns to the web page.
To improve the development experience, a much-simplified version of CI/CD has been implemented that allows each push on the main branch of the repository to automatically start a build on Netlify that deploy the web app directly to myreadings.albertobonacina.com
The architecture is in the figure and more details on configurations on environment variables, code for deployment, and release can be found directly in the repository on GitHub:
Conclusions
The final result can be viewed on this webpage: myreadings.albertobonacina.com and all the code can be found in this repo on GitHub: myreadings-flutter
Code strong, Alberto