Boosting Productivity: A Guide to Building a Reading List App with Notion and Flutter Web

Boosting Productivity: A Guide to Building a Reading List App with Notion and Flutter Web

ยท

4 min read

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

Did you find this article valuable?

Support Alberto Bonacina by becoming a sponsor. Any amount is appreciated!