# 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](https://flutter.dev/) to create our Web-based dashboard and a [Notion](https://www.notion.so/) database to manage persistence and save the list of our books. The final result can be found here: [My Reading List](https://myreadings.albertobonacina.com/)

The code for the application is available in this repo on GitHub: [myreadings-flutter](https://github.com/polilluminato/myreadings-flutter) licensed [Apache 2.0](https://github.com/polilluminato/myreadings-flutter/blob/main/LICENSE.md).

## Notion Database

A [Notion database](https://www.notion.so/help/category/databases) 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
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690404326857/8fba546e-b24d-406c-92da-747b2e7b9511.png align="center")

In order to access our Notion database from the outside via the API provided we must first create an [Integration](https://developers.notion.com/docs/create-a-notion-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](https://developers.notion.com/docs/working-with-databases), to access a Notion database via the API the call to make is this:

```bash
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](https://developers.notion.com/reference/post-database-query-sort), is made like this:

```json
"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](https://pub.dev/packages/http) package and displays the results in a grid, with the help of the very useful [flutter\_staggered\_grid\_view](https://pub.dev/packages/flutter_staggered_grid_view) package (about which I have already done an article [here](https://blog.albertobonacina.com/create-a-simple-responsive-gridview-with-flutter)). Other packages that were used in the project are:

* [riverpod](https://pub.dev/packages/riverpod) to manage the application state and HTTP call via a provider and its repository
    
* [go\_router](https://pub.dev/packages/go_router) for navigation and routing
    
* [percent\_indicator](https://pub.dev/packages/percent_indicator) for the loading bar indicating progress in reading
    
* [super\_banners](https://pub.dev/packages/super_banners) for the banner above the card for the status of planned and read
    
* [url\_launcher](https://pub.dev/packages/url_launcher) for opening the link to the Amazon page upon clicking the button
    

The end result is as shown in the figure:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690406268783/1986ab65-86ab-45b9-8769-2bb951b8d68c.png align="center")

## Insights

As reported in these two discussions on StackOverflow: [Notion API, Vanilla JS, Fetch does not work \[duplicate\]](https://stackoverflow.com/questions/68781041/notion-api-vanilla-js-fetch-does-not-work) and [Can I use fetch to call the Notion API?](https://stackoverflow.com/questions/68015381/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](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS); to solve this problem, a [Cloudflare Worker](https://workers.cloudflare.com/) 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](https://www.netlify.com/) that deploy the web app directly to [myreadings.albertobonacina.com](http://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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690625365564/4e8c1838-e52c-48c3-b996-6a79e9780d72.jpeg align="center")

### Conclusions

The final result can be viewed on this webpage: [myreadings.albertobonacina.com](https://myreadings.albertobonacina.com) and all the code can be found in this repo on GitHub: [myreadings-flutter](https://github.com/polilluminato/myreadings-flutter)

Code strong, Alberto
