
Daniel Locatelli
Website built with Astro + Notion as CMS
About
This website was developed using the Astro framework and Notion as a CMS.
Credits
Special credit to Hiroki Toyokawa for making the astro-notion-blog open source.
Although our repos now diverged significantly, it all started there.
Concept
I have been using Notion both professionally and on my personal stuff for a while. So, keeping it all organized on the same platform felt like a no-brainer. Also, this was a great opportunity to learn the Astro framework, Tailwind, and how to work with APIs.
Tech stack
- Astro web framework
- Tailwind CSS framework
- Notion as a content management service
- Cloudflare to deploy and host the website
- Figma to sketch layout ideas and prepare SVG files
- Rhino to generate drawings
Workflow
- Notion as a CMS: I have an opinionated set of databases on Notion, where I create all the pages and subpages.
- A custom Astro integration queries these databases at the beginning of every build using Notion API. Then it automatically downloads the files, saves them at
src/assets/notion, and saves a jpg version of the database cover atpublic/mediato be used as og-image. The download only happens if the file does not yet exist. And the requests follow Notion API request limits. - Astro builds the static website, taking full advantage of the image optimization features.
- The website is hosted on Cloudflare.
Notion structure
Notion API already comes with some basic data, like page ID, page cover, and page icon. These were extended using an interface so I could have my own opinionated types.
1. Pages as Notion databases
This database contains the pages' information. For example, the 'Projects' item refers to the page https://daniellocatelli.com/projects. The only exception is the "Homepage," which refers to the root https://daniellocatelli.com/
1.1. Pages Schema
| Name | CoverAlt | Local | Description_en | Description_de | Description_pt | Status | DatabaseRef | FullName | ShortDescription_en | Tags |
|---|---|---|---|---|---|---|---|---|---|---|
| string | string | string | string | string | string | status | SelectProperty[] | string | string | SelectProperty[] |
Pages: Homepage, Projects, Teaching, Strategies, Publications (In progress), Blog (Not started)
-
Name: The name of the page will be used to generate the slug for the page. Except for the homepage. -
CoverAlt: This will be the alt text used for the cover image, both on OG (shareable links) and on the Homepage. -
Local: Is still not in use. The issue of internationalization isn't clear. -
Description_en: this is the OG description of the page. -
Description_de: This is the German OG description of the page. The issue of internationalization isn't clear. -
Description_pt: this is the Portuguese OG description of the page. The issue of internationalization isn't clear. -
Status: column defines whether the page is online (Live) or not (In progress / Not started). -
DatabaseRef: The items listed here point to the subpage databases. They are used to create full-screen cards linking to the subpages. -
FullName: This column was created to have a longer name for the page. It is used in the head and footer links. -
ShortDescription_en: It was necessary to have a really short description for the Homepage. And because I wanted to keep the OG description, I created this new one. -
Tags: The idea for the tags is to recommend other similar content at the end of the pages. Not yet implemented.
The SelectProperty is a Notion type for tags with id: string; name: string; color: string;
2. Subpages as Notion databases
As mentioned above, the DatabaseRef connects to subpage databases.
For example, the page 'Strategies' has in the DatabaseRef 'Computational Design Strategies,' while the page 'Research' has in the DatabaseRef 'Research' and 'Publications.'
This way, I can organize each category in their own databases with a unique schema. Something similar to what we would do with an SQL database.
Think of a notion database just as a SQL table.
2.1. Computational Design Strategies schema
| Apps | CoverAlt | Description_en | Description_de | Description_pt | Name_de | Name_pt | References | Status | Tags |
|---|---|---|---|---|---|---|---|---|---|
| SelectProperty[] | string | string | string | string | string | string | string | status | SelectProperty[] |
-
Name: The name of the page will be used to generate the slug for the page. -
CoverAlt: This will be the alt text used for the cover image of OG and on the page. -
Description_en: this is the OG description of the page. -
Description_de: this is the German OG description of the page. The issue of internationalization isn't clear. -
Description_pt: this is the Portuguese OG description of the page. The issue of internationalization isn't clear. -
Name_de: this is the German OG title. The issue of internationalization isn't clear. -
Name_pt: this is the Portuguese OG title. The issue of internationalization isn't clear. -
Status: column defines whether the page is online (Live) or not (In progress / Not started). -
Tags: The idea for the tags is to recommend other similar content at the end of the pages. Not yet implemented.
2.2. Projects schema
| Category | City | CoverAlt | Date | Description_en | Description_de | Description_pt | Disclosed | Link | Client | Authors | Director | Manager | Development | Place | Status | Team | Files | Tags |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| string | SelectProperty[] | string | string | string | string | string | boolean | RichText[] | string | SelectProperty[] | SelectProperty[] | SelectProperty[] | SelectProperty[] | string | status | SelectProperty[] | file | SelectProperty[] |
-
Category: same as tags, but to have a unique general category. It's still not implemented. -
City: project metadata. -
CoverAlt: This will be the alt text used for the cover image of OG and on the page. -
Date: project metadata. -
Description_en: this is the OG description of the page. -
Description_de: this is the German OG description of the page. The issue of internationalization isn't clear. -
Description_pt: this is the Portuguese OG description of the page. The issue of internationalization isn't clear. -
Disclosed: whether the project can display sensitive information. This way, I can also store undisclosed projects on the same database. -
Link: project metadata, an official or relevant link to the project. -
Client: project metadata. -
Authors: project metadata. -
Director: project metadata. -
Manager: project metadata. -
Development: project metadata, who was the developer. -
Place: project metadata. -
Status: column defines whether the page is online (Live) or not (In progress / Not started). -
Team: project metadata. -
Files: the idea is to have some files in the project metadata at the beginning. Not yet implemented. -
Tags: The idea for the tags is to recommend other similar content at the end of the pages. Not yet implemented.
2.3. Publications schema
| City | CoverAlt | Date | Description_en | Description_de | Description_pt | Link | Authors | Place | Status | Language | Tags | Name_de | Name_pt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| SelectProperty[] | string | string | string | string | string | RichText[] | SelectProperty[] | string | status | SelectProperty[] | string | string | string |
-
City: publication metadata. -
CoverAlt: This will be the alt text used for the cover image of OG and on the page. -
Date: publication metadata. -
Description_en: this is the OG description of the page. -
Description_de: this is the German OG description of the page. The issue of internationalization isn't clear. -
Description_pt: this is the Portuguese OG description of the page. The issue of internationalization isn't clear. -
Link: publication metadata, an official or relevant link to the project. -
Authors: publication metadata. -
Place: publication metadata. -
Status: column defines whether the page is online (Live) or not (In progress / Not started). -
Language: publication metadata. -
Tags: The idea for the tags is to recommend other similar content at the end of the pages. Not yet implemented. -
Name_de: this is the German OG title. The issue of internationalization isn't clear. -
Name_pt: this is the Portuguese OG title. The issue of internationalization isn't clear.
2.4. Research schema
| CoverAlt | Date | Description_en | Description_de | Description_pt | Link | Authors | Place | Status | Tags |
|---|---|---|---|---|---|---|---|---|---|
| string | string | string | string | string | RichText[] | SelectProperty[] | string | status | SelectProperty[] |
-
CoverAlt: This will be the alt text used for the cover image of OG and on the page. -
Date: research metadata. -
Description_en: this is the OG description of the page. -
Description_de: this is the German OG description of the page. The issue of internationalization isn't clear. -
Description_pt: this is the Portuguese OG description of the page. The issue of internationalization isn't clear. -
Link: research metadata, an official or relevant link to the project. -
Authors: research metadata. -
Place: research metadata. -
Status: column defines whether the page is online (Live) or not (In progress / Not started). -
Tags: The idea for the tags is to recommend other similar content at the end of the pages. Not yet implemented.
2.5. Teaching schema
| CoverAlt | Date | Description_en | Description_de | Description_pt | Link | Team | Place | Status | Tags | City | Event | Format | Language |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| string | string | string | string | string | RichText[] | SelectProperty[] | string | status | SelectProperty[] | SelectProperty[] | string | string | SelectProperty[] |
-
CoverAlt: This will be the alt text used for the cover image of OG and on the page. -
Date: teaching metadata. -
Description_en: this is the OG description of the page. -
Description_de: this is the German OG description of the page. The issue of internationalization isn't clear. -
Description_pt: this is the Portuguese OG description of the page. The issue of internationalization isn't clear. -
Link: teaching metadata, an official or relevant link to the project. -
Authors: teaching metadata. -
Place: teaching metadata. -
Status: column defines whether the page is online (Live) or not (In progress / Not started). -
Tags: The idea for the tags is to recommend other similar content at the end of the pages. Not yet implemented. -
City: teaching metadata. -
Event: teaching metadata. -
Format: teaching metadata. -
Language: teaching metadata.
Personal projects
View all- Loading
About
I program buildings
