library(tidyverse) ## for data manipulation
library(dotenv) ## for loading environment secrets
library(httr) ## for doing API requetss
library(whisker) ## for rendering templates
library(glue) ## for string interpolation
library(jsonlite) ## Working with JSON
library(cli) ## for nice console output messages
CEC Notion Deployment 2024-08-23
1 Introduction
If we start with data (a table or dataframe) we can write it to many digital formats: Notion Pages, Quarto Web Pages or Custom web pages like SALURBAL Portal. Here we demonstrate a workflow for writing data to Notion pages. This is a proof of concept for the CEC team to show how we can write data to Notion pages.
We can write page content to Notion pages via API. The inputs for these could be any database. In this example, we will actually use the page’s own Notion properties as ‘data’ to populate the page. So for each page there are actually two steps: 1) import page properties and 2) writing the properties as Notion blocks.
Before we start, lets just do some quick setup.
2 Setup
We will need three packages.
You will also need an .env
file in the root of your project that has an Notion API key. Do NOT SHARE this or have this under version control. It should be in your gitignore folder! From here we can load ‘secrets’ for R to use but not exposed to anyone else.
## Load .env file into local environment
::load_dot_env(file = ".env")
dotenv
## Assign secret to a variabel
<- Sys.getenv("NOTION_API_KEY") secret_notion_api_key
We will also need to reuse some functions which were informed by the NotionR package but essentially build again to be more lightweight and maintainable in by the CCUH/SALURBAL infrastructure team. Feel free to modify it for your own needs - maybe we can publish it as a packge one day if matures =)
source('R/read_notion_database.R')
source('R/make_notion_request.R')
3 Import Data
In this case, the data is a Notion database which is uniquely identified with a database id which can be found in the URL between the account id (drexel-ccuh) and the first ?
- as highlighted in the snip below.
Once we have this we can just use the read_notion_database
function to get the data.
= read_notion_database(database = '6ac8fe17c3ec4c7d9f2f1d3068d7d877')
df_policies_main_table dim(df_policies_main_table)
[1] 150 220
This is a big table with 150 rows (one per database row) and 206 columns. Notion API returns a lot of information about each page and a lot of metadata for each property. While this is all very useful and makes for a very flexible API, it can be a bit overwhelming. So one challenge is looking through and picking out the information we are interested in; we’ll do that in the next section data cleaning.
4 Clean Data
4.1 Subset for ‘1-pager test case’
We will test this out with a few of the rows with this TODO tag. Let’s take a loko at what type of information we have on this property.
%>%
df_policies_main_table select(contains('TODO')) %>%
View()
It looks like what we want is in the
properties.TODO's.multi_select.name
column. Lets filter this dataframe to only include those that have the tag of interest.
= df_policies_main_table %>%
df_db_subset_rows filter(str_detect(`properties.TODO's.multi_select.name`, '1-pager'))
dim(df_db_subset_rows)
[1] 5 220
Indeed we are down to 5 rows!
Lets initialize a new dataframe to store cleaned results.
= df_db_subset_rows %>%
df_parsed select(id) %>%
as_tibble()
4.2 Identify properties of interest
So the request was originally for a template that had some ‘keys’ to render property values which include:
- [Title]
- [Sectors]
- [Governance level]
- [Primary effect(s)]
- [Relevance to health]
- [Description]
- [Additional description]
- [Climate change scope]
- [Climate narrative]
- [Health impact pathways]
- [Exposures affected]
- [Health narrative]
- [Related policies]
- [Feasibility]
- [Timeframe]
- [One pager]
- [Image files]
4.3 Example code for parsing properties
Okay. For Notion each property type has its own types of columns returned. Below is a list of the properties we are interested in and the column names that contain the information we want. Below that are some subsections show how that process works for each type of property in the requets - just to give example code for how to handle/process.
- Text: Title
- Relation: Sectors
- Multi-select: Primary effect(s)
- Image: Image files
4.3.1 Text - [Title]
%>%
df_db_subset_rows select(contains('Title')) %>%
glimpse()
Rows: 5
Columns: 20
$ properties.Policies.title.annotations.bold <chr> "FALSE", "FALSE",…
$ properties.Policies.title.annotations.code <chr> "FALSE", "FALSE",…
$ properties.Policies.title.annotations.color <chr> "default", "defau…
$ properties.Policies.title.annotations.italic <chr> "FALSE", "FALSE",…
$ properties.Policies.title.annotations.strikethrough <chr> "FALSE", "FALSE",…
$ properties.Policies.title.annotations.underline <chr> "FALSE", "FALSE",…
$ properties.Policies.title.plain_text <chr> "Complete streets…
$ properties.Policies.title.text.content <chr> "Complete streets…
$ properties.Policies.title.type <chr> "text", "text", "…
$ properties.Title.id <chr> "ASrg", "ASrg", "…
$ properties.Title.type <chr> "rich_text", "ric…
$ properties.Title.rich_text.annotations.bold <chr> "FALSE", "FALSE",…
$ properties.Title.rich_text.annotations.code <chr> "FALSE", "FALSE",…
$ properties.Title.rich_text.annotations.color <chr> "default", "defau…
$ properties.Title.rich_text.annotations.italic <chr> "TRUE", "TRUE", "…
$ properties.Title.rich_text.annotations.strikethrough <chr> "FALSE", "FALSE",…
$ properties.Title.rich_text.annotations.underline <chr> "FALSE", "FALSE",…
$ properties.Title.rich_text.plain_text <chr> "Complete Streets…
$ properties.Title.rich_text.text.content <chr> "Complete Streets…
$ properties.Title.rich_text.type <chr> "text", "text", "…
Looks like rich text, we will just take the plain text!
## Select column of interest
= df_db_subset_rows %>%
df_title select(id, title = `properties.Title.rich_text.plain_text`)
## Merge into results
= df_parsed %>%
df_parsed left_join(df_title)
4.3.2 Relation to other db pages - [Sectors]
%>%
df_db_subset_rows select(id, contains('.Sectors')) %>%
glimpse()
Rows: 5
Columns: 5
$ id <chr> "df0ef29f-da8a-4e74-8713-f30f19727503",…
$ properties.Sectors.has_more <chr> "FALSE", "FALSE", "FALSE", "FALSE", "FA…
$ properties.Sectors.id <chr> "TVp%3A", "TVp%3A", "TVp%3A", "TVp%3A",…
$ properties.Sectors.type <chr> "relation", "relation", "relation", "re…
$ properties.Sectors.relation.id <chr> "6b2c4777-339f-4898-a849-8b6190ba7865 |…
This is one is more complex, because this is a relation. See the relation information above really just gives a link to the other table via properties.Sectors.relation.id
. So there are two ways of handling it:
- Easy:
- Create a Notion Rollup of in Policy Main with the value of the relation
- Hard:
- Import the Sectors table in R
- Link the Sectors table to the Policy Main table in R
Lets do the hard way first; we can got rhough easy example later. Lets read in the Sectors
table to get the sector name.
= read_notion_database(database = '09b80694ea9d4fd7bffe8fd0cd4df489')
df_sectors glimpse(df_sectors)
Rows: 18
Columns: 30
$ archived <chr> "FALSE", "FALSE", "F…
$ created_by.id <chr> "9711549e-0df7-4268-…
$ created_by.object <chr> "user", "user", "use…
$ created_time <chr> "2024-08-23T00:34:00…
$ id <chr> "4fca3b06-d65f-4200-…
$ in_trash <chr> "FALSE", "FALSE", "F…
$ last_edited_by.id <chr> "9711549e-0df7-4268-…
$ last_edited_by.object <chr> "user", "user", "use…
$ last_edited_time <chr> "2024-08-23T00:34:00…
$ object <chr> "page", "page", "pag…
$ parent.database_id <chr> "09b80694-ea9d-4fd7-…
$ parent.type <chr> "database_id", "data…
$ properties.Policies.has_more <chr> "FALSE", "FALSE", "F…
$ properties.Policies.id <chr> "gCBj", "gCBj", "gCB…
$ properties.Policies.type <chr> "relation", "relatio…
$ properties.Sector.id <chr> "title", "title", "t…
$ properties.Sector.title.annotations.bold <chr> "FALSE", "FALSE", "F…
$ properties.Sector.title.annotations.code <chr> "FALSE", "FALSE", "F…
$ properties.Sector.title.annotations.color <chr> "default", "default"…
$ properties.Sector.title.annotations.italic <chr> "FALSE", "FALSE", "F…
$ properties.Sector.title.annotations.strikethrough <chr> "FALSE", "FALSE", "F…
$ properties.Sector.title.annotations.underline <chr> "FALSE", "FALSE", "F…
$ properties.Sector.title.plain_text <chr> "Technology developm…
$ properties.Sector.title.text.content <chr> "Technology developm…
$ properties.Sector.title.type <chr> "text", "text", "tex…
$ properties.Sector.type <chr> "title", "title", "t…
$ properties.Tags.id <chr> "wUd%5C", "wUd%5C", …
$ properties.Tags.type <chr> "multi_select", "mul…
$ url <chr> "https://www.notion.…
$ properties.Policies.relation.id <chr> NA, NA, NA, NA, NA, …
Okay. lets operataionzlie some templating data with just the sector page id and the sector name as as a hyperlink to the Notion page. I mean we could do text, but this just shows we can do a hyperlink to increase findability (in case you have SEctor specific dcumentaiton on Notion).
= df_sectors %>%
df_sectors_processed mutate(sector_value = glue("[{properties.Sector.title.plain_text}]({url})")) %>%
select(id, sector_value)
= as.list(df_sectors_processed$sector_value) %>%
templating_data_sectors setNames(df_sectors_processed$id)
head(templating_data_sectors)
$`4fca3b06-d65f-4200-bdb6-faf70292a11a`
[1] "[Technology development and innovation](https://www.notion.so/Technology-development-and-innovation-4fca3b06d65f4200bdb6faf70292a11a)"
$`cf0a3883-40b3-4194-9471-449731df87bc`
[1] "[Finance and insurance](https://www.notion.so/Finance-and-insurance-cf0a388340b341949471449731df87bc)"
$`0d0f82e1-d8bb-49fe-9d12-579da1869e1b`
[1] "[Education](https://www.notion.so/Education-0d0f82e1d8bb49fe9d12579da1869e1b)"
$`ad3364a0-6eca-42fe-a9ee-08b2fa043c2d`
[1] "[Health](https://www.notion.so/Health-ad3364a06eca42fea9ee08b2fa043c2d)"
$`373fb372-2455-40d0-90d1-ac7ba6000a93`
[1] "[Social welfare and services](https://www.notion.so/Social-welfare-and-services-373fb372245540d090d1ac7ba6000a93)"
$`41225582-438d-49a1-8443-4b3e06cdd94b`
[1] "[Governance and regulation](https://www.notion.so/Governance-and-regulation-41225582438d49a184434b3e06cdd94b)"
Now lets prep the df_db_subset_rows
to adhere to templating syntax.
= function(relation_id_string) {
prepare_render_ready_relation_id_string # relation_id_string = "6b2c4777-339f-4898-a849-8b6190ba7865 | 997e4a17-4b08-4f35-b86e-a5028c9910e4"
= relation_id_string %>%
render_ready_string str_split("\\|") %>%
unlist() %>%
str_trim() %>%
paste0("{{",.,"}}") %>%
paste(collapse = ', ')
return(render_ready_string)
}
= df_db_subset_rows %>%
df_db_subset_rows_sectors_prerender rowwise() %>%
mutate(sectors = prepare_render_ready_relation_id_string(properties.Sectors.relation.id)) %>%
ungroup() %>%
select(id, sectors)
df_db_subset_rows_sectors_prerender
# A tibble: 5 × 2
id sectors
<chr> <chr>
1 df0ef29f-da8a-4e74-8713-f30f19727503 {{6b2c4777-339f-4898-a849-8b6190ba7865}}…
2 81b63652-a8be-48ea-a1b2-fcfb8aa8165e {{43e35fb1-0303-4094-92b9-d37dcc71816a}}…
3 f8f99d62-9bfc-4668-8379-67406ad3a01b {{997e4a17-4b08-4f35-b86e-a5028c9910e4}}
4 3f0c1c1b-a26a-4636-9aaa-64c8c0a3bdbd {{997e4a17-4b08-4f35-b86e-a5028c9910e4}}
5 c3e2e324-4a3f-4cf0-9a82-c28365bd0a3e {{fa03fd40-ea99-4bfe-af51-c7f573360550}}
Now lets render
## Render
= df_db_subset_rows_sectors_prerender %>%
df_db_subset_rows_sectors_rendered rowwise() %>%
mutate(sectors = whisker::whisker.render(sectors, templating_data_sectors)) %>%
ungroup()
## Preview render results
df_db_subset_rows_sectors_rendered
# A tibble: 5 × 2
id sectors
<chr> <chr>
1 df0ef29f-da8a-4e74-8713-f30f19727503 [Urban planning and land use](https://ww…
2 81b63652-a8be-48ea-a1b2-fcfb8aa8165e [Architecture and Housing](https://www.n…
3 f8f99d62-9bfc-4668-8379-67406ad3a01b [Transportation](https://www.notion.so/T…
4 3f0c1c1b-a26a-4636-9aaa-64c8c0a3bdbd [Transportation](https://www.notion.so/T…
5 c3e2e324-4a3f-4cf0-9a82-c28365bd0a3e [Thermal governance](https://www.notion.…
## Merge into results
= df_parsed %>%
df_parsed left_join(df_db_subset_rows_sectors_rendered)
4.3.3 Multiselect - [Primary effect]
%>%
df_db_subset_rows select(id, contains('.Primary')) %>%
glimpse()
Rows: 5
Columns: 6
$ id <chr> "df0ef29f-da8a-4e74-…
$ `properties.Primary effect(s).id` <chr> "O%3BA%7B", "O%3BA%7…
$ `properties.Primary effect(s).type` <chr> "multi_select", "mul…
$ `properties.Primary effect(s).multi_select.color` <chr> "green | default", N…
$ `properties.Primary effect(s).multi_select.id` <chr> "^kTo | Au~q", NA, "…
$ `properties.Primary effect(s).multi_select.name` <chr> "Traffic safety impr…
Primary effect is a multi-select. The columnn of interest seems to be properties.Primary effect(s).multi_select.name
. Lets take a look at hte values.
%>%
df_db_subset_rows count(`properties.Primary effect(s).multi_select.name`)
# A tibble: 4 × 2
`properties.Primary effect(s).multi_select.name` n
<chr> <int>
1 GHG reduction 1
2 GHG reduction | Traffic safety improvements 1
3 Traffic safety improvements | GHG reduction 1
4 <NA> 2
This is just slightly more complex than text, we just need to replace the API seperator |
with what ever you want. Lets do a comma.
= df_db_subset_rows %>%
df_primary_effect mutate(primary_effects = str_replace_all( `properties.Primary effect(s).multi_select.name`, "\\|", ", ")) %>%
select(id,primary_effects)
## Merge into results
= df_parsed %>%
df_parsed left_join(df_primary_effect)
4.3.4 Image - [Image files]
%>%
df_db_subset_rows select(id, contains('.Image')) %>%
glimpse()
Rows: 5
Columns: 6
$ id <chr> "df0ef29f-da8a-4e74-8713-f…
$ `properties.Image files.id` <chr> "QMLZ", "QMLZ", "QMLZ", "Q…
$ `properties.Image files.type` <chr> "files", "files", "files",…
$ `properties.Image files.files.external.url` <chr> "https://www.mdpi.com/sust…
$ `properties.Image files.files.name` <chr> "https://www.mdpi.com/sust…
$ `properties.Image files.files.type` <chr> "external", "external", NA…
For images we just need where the file is located which is properties.Image files.files.external.url
.
= df_db_subset_rows %>%
df_image_files select(id,image = `properties.Image files.files.external.url`)
## Merge into results
= df_parsed %>%
df_parsed left_join(df_image_files)
4.4 Parse minimal properties
Here we apply the above logic across a few other properties - just so we have a basic amount of data for generating a Proof of concept.
4.4.1 [Descrption]
= df_db_subset_rows %>%
df_description select(id, description = `properties.Description.rich_text.plain_text`)
df_description
# A tibble: 5 × 2
id description
<chr> <chr>
1 df0ef29f-da8a-4e74-8713-f30f19727503 "Complete Streets policies aim for all p…
2 81b63652-a8be-48ea-a1b2-fcfb8aa8165e "Green roofs, or living roofs, vegetated…
3 f8f99d62-9bfc-4668-8379-67406ad3a01b "Reducing speed limits on streets helps …
4 3f0c1c1b-a26a-4636-9aaa-64c8c0a3bdbd <NA>
5 c3e2e324-4a3f-4cf0-9a82-c28365bd0a3e "Air conditioning inside buildings and h…
Looks okay, lets bind.
## Merge into results
= df_parsed %>%
df_parsed left_join(df_description)
4.4.2 [Climate narrative]
= df_db_subset_rows %>%
df_climate_narrative select(id, climate_narrative = `properties.Climate narrative.rich_text.plain_text`)
Looks okay, lets bind.
## Merge into results
= df_parsed %>%
df_parsed left_join(df_climate_narrative)
4.5 Review Templating Data
Now we have a minimum amount of data to show the workflow.
= df_parsed %>%
df_parsed mutate(id_clean = stringr::str_remove_all(id, "-")) %>%
glimpse()
Rows: 5
Columns: 8
$ id <chr> "df0ef29f-da8a-4e74-8713-f30f19727503", "81b63652-a8…
$ title <chr> "Complete Streets policy approach for safe and equit…
$ sectors <chr> "[Urban planning and land use](https://www.notion.so…
$ primary_effects <chr> "Traffic safety improvements , GHG reduction", NA, …
$ image <chr> "https://www.mdpi.com/sustainability/sustainability-…
$ description <chr> "Complete Streets policies aim for all people regard…
$ climate_narrative <chr> "Complete Street policies play a role in larger clim…
$ id_clean <chr> "df0ef29fda8a4e748713f30f19727503", "81b63652a8be48e…
Lets do the writing to Notion pages
5 Functions for Writing to Notion
The Logic here adopted from a few CCUH pieces of work:
- CCUH DBT Docs to Notion Integration - Proof of Concept - this was the origianl notebook for this workflow
- Drafted protocols for translate each Notion property type to API synax (JSON format)
The basic idea is that for each block we have an R function that generates the content in JSON format. When the compose a JSON request that contains all these individual pieces of logic. Here we draft the functions for the first few blocks of the template - the CEC can do the rest.
Notion has good documentation about how to write blocks here: https://developers.notion.com/reference/block
5.1 Content functions
Here we have functions you can edit for the property types you requsted.
5.1.1 H1 block
<- function(title) {
make_h1_block glue('
{{
"object": "block",
"type": "heading_1",
"heading_1": {{
"rich_text": [
{{
"type": "text",
"text": {{
"content": "{title}"
}}
}}
]
}}
}}
')
}
5.1.2 Notion Mentions Block
This is use to display relations - links to other notion db pages. We will use this for the sectors and other relations. See official notion docs here: https://developers.notion.com/reference/block#mention.
<- function(text) {
make_notion_mention_block # Split the markdown text into parts
<- strsplit(text, "\\[|\\]\\(|\\)")[[1]]
parts
<- list()
rich_text
for (i in seq_along(parts)) {
if (i %% 3 == 1) {
# Plain text
if (nchar(parts[i]) > 0) {
<- c(rich_text, list(list(
rich_text type = "text",
text = list(content = parts[i])
)))
}else if (i %% 3 == 2) {
} # Page mention
<- parts[i + 1]
url <- sub(".*-", "", url) # Extract the ID from the end of the URL
page_id <- c(rich_text, list(list(
rich_text type = "mention",
mention = list(
type = "page",
page = list(id = page_id)
)
)))
}
}
<- jsonlite::toJSON(list(
json object = "block",
type = "paragraph",
paragraph = list(
rich_text = rich_text
)auto_unbox = TRUE, pretty = TRUE)
),
# Remove escaped forward slashes
<- gsub("\\\\/", "/", json)
json
return(json)
}
5.1.3 Text block
This is the easiet, just text.
<- function(text) {
make_text_block <- gsub("\n", "\\\\n", text)
text_escaped glue('
{{
"object": "block",
"type": "paragraph",
"paragraph": {{
"rich_text": [
{{
"type": "text",
"text": {{
"content": "{text_escaped}"
}}
}}
]
}}
}}
')
}
5.1.4 Image
As per https://developers.notion.com/reference/block#image
<- function(image_url) {
make_image_block
## If no image just return empty text
= glue('
text_if_no_image {{
"object": "block",
"type": "paragraph",
"paragraph": {{
"rich_text": [
{{
"type": "text",
"text": {{
"content": ""
}}
}}
]
}}
}}
')
= glue('
image_if_available {{
"object": "block",
"type": "image",
"image": {{
"type": "external",
"external": {{
"url": "{image_url}"
}}
}}
}}
')
if (is.na(image_url) | image_url == "") {
return(text_if_no_image)
else {
} return(image_if_available)
} }
5.2 Writing funcitons
These fucntions will be used to edit content on a page. We test with the Green Roofs page
= 'df0ef29fda8a4e748713f30f19727503' test_page
5.2.1 Clear Page Blocks
This funciton will clear a all blocks in a page. Just used to clear thigns if needed.
<- function(page_id) {
clear_page_children # First, retrieve all children blocks
<- make_request(
get_children_response endpoint = glue("blocks/{page_id}/children"),
method = "GET"
)
# Extract block IDs
<- sapply(get_children_response$results, function(block) block$id)
block_ids
# If there are no children, we're done
if (length(block_ids) == 0) {
cat("Page is already empty.\n")
return(invisible(NULL))
}
# Delete each block
for (block_id in block_ids) {
make_request(
endpoint = glue("blocks/{block_id}"),
method = "DELETE"
)cat(glue("Deleted block {block_id}\n"))
}
cat(glue("Cleared {length(block_ids)} blocks from page {page_id}\n"))
}
clear_page_children(test_page)
Deleted block 5626e666-1cbd-4d94-8c5f-3123ecd77e6cDeleted block 8eced27b-b67d-4fe1-a70f-0159aa31fd5bDeleted block 22b0231d-d421-4f3b-b21c-c983d78dc6f5Deleted block f56881ba-03f0-426f-be47-259b2deb5282Deleted block c6343a23-1d68-4e9a-97a2-b0cdb7de7b55Deleted block 45575f08-d7e8-4e6c-9b8f-9455d9f99a74Deleted block 5acc8d5b-f5e6-455f-851f-4391ebbefef9Deleted block 68d7f884-f2a2-49a1-8a6d-8edf6e6e6cc3Deleted block 4883dd52-56f0-4669-8ed7-82712bdf427bCleared 9 blocks from page df0ef29fda8a4e748713f30f19727503
5.2.2 write_cec_template_poc()
This will add children blocks to specified page. We compose the content here. We assume we have a input data frame hwere each row is a page with content to write.
## Prep Input data
= df_parsed %>%
page_row filter(id_clean == test_page)
page_row
# A tibble: 1 × 8
id title sectors primary_effects image description climate_narrative
<chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 df0ef29f-da… Comp… [Urban… Traffic safety… http… "Complete … Complete Street …
# ℹ 1 more variable: id_clean <chr>
## Function to compose template
<- function(page_row) {
write_cec_template_poc
= glue('
body_json {{
"children": [
{make_h1_block(page_row$title)},
{make_notion_mention_block(glue("Sectors: {page_row$sectors}"))},
{make_notion_mention_block(glue("Primarily intended effect of policy:: {page_row$sectors}"))},
{make_h1_block("Description")},
{make_text_block(page_row$description)},
{make_h1_block("How this policy relates to climate change")},
{make_text_block(page_row$climate_narrative)},
{make_h1_block("Image")},
{make_image_block(page_row$image)}
]
}}
')
make_request(
endpoint = glue("blocks/{page_row$id_clean}/children"),
method = "PATCH",
body = body_json,
body_format_json = TRUE
)
}
clear_page_children(test_page)
Page is already empty.
write_cec_template_poc(page_row)
$object
[1] "list"
$results
$results[[1]]
$results[[1]]$object
[1] "block"
$results[[1]]$id
[1] "0cec0e78-1c5d-443c-906d-571d6f97151e"
$results[[1]]$parent
$results[[1]]$parent$type
[1] "page_id"
$results[[1]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[1]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[1]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[1]]$created_by
$results[[1]]$created_by$object
[1] "user"
$results[[1]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[1]]$last_edited_by
$results[[1]]$last_edited_by$object
[1] "user"
$results[[1]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[1]]$has_children
[1] FALSE
$results[[1]]$archived
[1] FALSE
$results[[1]]$in_trash
[1] FALSE
$results[[1]]$type
[1] "heading_1"
$results[[1]]$heading_1
$results[[1]]$heading_1$rich_text
$results[[1]]$heading_1$rich_text[[1]]
$results[[1]]$heading_1$rich_text[[1]]$type
[1] "text"
$results[[1]]$heading_1$rich_text[[1]]$text
$results[[1]]$heading_1$rich_text[[1]]$text$content
[1] "Complete Streets policy approach for safe and equitable mobility"
$results[[1]]$heading_1$rich_text[[1]]$text$link
NULL
$results[[1]]$heading_1$rich_text[[1]]$annotations
$results[[1]]$heading_1$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[1]]$heading_1$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[1]]$heading_1$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[1]]$heading_1$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[1]]$heading_1$rich_text[[1]]$annotations$code
[1] FALSE
$results[[1]]$heading_1$rich_text[[1]]$annotations$color
[1] "default"
$results[[1]]$heading_1$rich_text[[1]]$plain_text
[1] "Complete Streets policy approach for safe and equitable mobility"
$results[[1]]$heading_1$rich_text[[1]]$href
NULL
$results[[1]]$heading_1$is_toggleable
[1] FALSE
$results[[1]]$heading_1$color
[1] "default"
$results[[2]]
$results[[2]]$object
[1] "block"
$results[[2]]$id
[1] "59b021f4-1944-422c-abd0-bc982dc1ea63"
$results[[2]]$parent
$results[[2]]$parent$type
[1] "page_id"
$results[[2]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[2]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[2]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[2]]$created_by
$results[[2]]$created_by$object
[1] "user"
$results[[2]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[2]]$last_edited_by
$results[[2]]$last_edited_by$object
[1] "user"
$results[[2]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[2]]$has_children
[1] FALSE
$results[[2]]$archived
[1] FALSE
$results[[2]]$in_trash
[1] FALSE
$results[[2]]$type
[1] "paragraph"
$results[[2]]$paragraph
$results[[2]]$paragraph$rich_text
$results[[2]]$paragraph$rich_text[[1]]
$results[[2]]$paragraph$rich_text[[1]]$type
[1] "text"
$results[[2]]$paragraph$rich_text[[1]]$text
$results[[2]]$paragraph$rich_text[[1]]$text$content
[1] "Sectors: "
$results[[2]]$paragraph$rich_text[[1]]$text$link
NULL
$results[[2]]$paragraph$rich_text[[1]]$annotations
$results[[2]]$paragraph$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[2]]$paragraph$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[2]]$paragraph$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[2]]$paragraph$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[2]]$paragraph$rich_text[[1]]$annotations$code
[1] FALSE
$results[[2]]$paragraph$rich_text[[1]]$annotations$color
[1] "default"
$results[[2]]$paragraph$rich_text[[1]]$plain_text
[1] "Sectors: "
$results[[2]]$paragraph$rich_text[[1]]$href
NULL
$results[[2]]$paragraph$rich_text[[2]]
$results[[2]]$paragraph$rich_text[[2]]$type
[1] "mention"
$results[[2]]$paragraph$rich_text[[2]]$mention
$results[[2]]$paragraph$rich_text[[2]]$mention$type
[1] "page"
$results[[2]]$paragraph$rich_text[[2]]$mention$page
$results[[2]]$paragraph$rich_text[[2]]$mention$page$id
[1] "6b2c4777-339f-4898-a849-8b6190ba7865"
$results[[2]]$paragraph$rich_text[[2]]$annotations
$results[[2]]$paragraph$rich_text[[2]]$annotations$bold
[1] FALSE
$results[[2]]$paragraph$rich_text[[2]]$annotations$italic
[1] FALSE
$results[[2]]$paragraph$rich_text[[2]]$annotations$strikethrough
[1] FALSE
$results[[2]]$paragraph$rich_text[[2]]$annotations$underline
[1] FALSE
$results[[2]]$paragraph$rich_text[[2]]$annotations$code
[1] FALSE
$results[[2]]$paragraph$rich_text[[2]]$annotations$color
[1] "default"
$results[[2]]$paragraph$rich_text[[2]]$plain_text
[1] "Urban planning and land use"
$results[[2]]$paragraph$rich_text[[2]]$href
[1] "https://www.notion.so/6b2c4777339f4898a8498b6190ba7865"
$results[[2]]$paragraph$rich_text[[3]]
$results[[2]]$paragraph$rich_text[[3]]$type
[1] "text"
$results[[2]]$paragraph$rich_text[[3]]$text
$results[[2]]$paragraph$rich_text[[3]]$text$content
[1] ", "
$results[[2]]$paragraph$rich_text[[3]]$text$link
NULL
$results[[2]]$paragraph$rich_text[[3]]$annotations
$results[[2]]$paragraph$rich_text[[3]]$annotations$bold
[1] FALSE
$results[[2]]$paragraph$rich_text[[3]]$annotations$italic
[1] FALSE
$results[[2]]$paragraph$rich_text[[3]]$annotations$strikethrough
[1] FALSE
$results[[2]]$paragraph$rich_text[[3]]$annotations$underline
[1] FALSE
$results[[2]]$paragraph$rich_text[[3]]$annotations$code
[1] FALSE
$results[[2]]$paragraph$rich_text[[3]]$annotations$color
[1] "default"
$results[[2]]$paragraph$rich_text[[3]]$plain_text
[1] ", "
$results[[2]]$paragraph$rich_text[[3]]$href
NULL
$results[[2]]$paragraph$rich_text[[4]]
$results[[2]]$paragraph$rich_text[[4]]$type
[1] "mention"
$results[[2]]$paragraph$rich_text[[4]]$mention
$results[[2]]$paragraph$rich_text[[4]]$mention$type
[1] "page"
$results[[2]]$paragraph$rich_text[[4]]$mention$page
$results[[2]]$paragraph$rich_text[[4]]$mention$page$id
[1] "997e4a17-4b08-4f35-b86e-a5028c9910e4"
$results[[2]]$paragraph$rich_text[[4]]$annotations
$results[[2]]$paragraph$rich_text[[4]]$annotations$bold
[1] FALSE
$results[[2]]$paragraph$rich_text[[4]]$annotations$italic
[1] FALSE
$results[[2]]$paragraph$rich_text[[4]]$annotations$strikethrough
[1] FALSE
$results[[2]]$paragraph$rich_text[[4]]$annotations$underline
[1] FALSE
$results[[2]]$paragraph$rich_text[[4]]$annotations$code
[1] FALSE
$results[[2]]$paragraph$rich_text[[4]]$annotations$color
[1] "default"
$results[[2]]$paragraph$rich_text[[4]]$plain_text
[1] "Transportation"
$results[[2]]$paragraph$rich_text[[4]]$href
[1] "https://www.notion.so/997e4a174b084f35b86ea5028c9910e4"
$results[[2]]$paragraph$color
[1] "default"
$results[[3]]
$results[[3]]$object
[1] "block"
$results[[3]]$id
[1] "5a65ff61-8b18-48e3-97e0-95a0f7dccdc3"
$results[[3]]$parent
$results[[3]]$parent$type
[1] "page_id"
$results[[3]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[3]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[3]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[3]]$created_by
$results[[3]]$created_by$object
[1] "user"
$results[[3]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[3]]$last_edited_by
$results[[3]]$last_edited_by$object
[1] "user"
$results[[3]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[3]]$has_children
[1] FALSE
$results[[3]]$archived
[1] FALSE
$results[[3]]$in_trash
[1] FALSE
$results[[3]]$type
[1] "paragraph"
$results[[3]]$paragraph
$results[[3]]$paragraph$rich_text
$results[[3]]$paragraph$rich_text[[1]]
$results[[3]]$paragraph$rich_text[[1]]$type
[1] "text"
$results[[3]]$paragraph$rich_text[[1]]$text
$results[[3]]$paragraph$rich_text[[1]]$text$content
[1] "Primarily intended effect of policy:: "
$results[[3]]$paragraph$rich_text[[1]]$text$link
NULL
$results[[3]]$paragraph$rich_text[[1]]$annotations
$results[[3]]$paragraph$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[3]]$paragraph$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[3]]$paragraph$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[3]]$paragraph$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[3]]$paragraph$rich_text[[1]]$annotations$code
[1] FALSE
$results[[3]]$paragraph$rich_text[[1]]$annotations$color
[1] "default"
$results[[3]]$paragraph$rich_text[[1]]$plain_text
[1] "Primarily intended effect of policy:: "
$results[[3]]$paragraph$rich_text[[1]]$href
NULL
$results[[3]]$paragraph$rich_text[[2]]
$results[[3]]$paragraph$rich_text[[2]]$type
[1] "mention"
$results[[3]]$paragraph$rich_text[[2]]$mention
$results[[3]]$paragraph$rich_text[[2]]$mention$type
[1] "page"
$results[[3]]$paragraph$rich_text[[2]]$mention$page
$results[[3]]$paragraph$rich_text[[2]]$mention$page$id
[1] "6b2c4777-339f-4898-a849-8b6190ba7865"
$results[[3]]$paragraph$rich_text[[2]]$annotations
$results[[3]]$paragraph$rich_text[[2]]$annotations$bold
[1] FALSE
$results[[3]]$paragraph$rich_text[[2]]$annotations$italic
[1] FALSE
$results[[3]]$paragraph$rich_text[[2]]$annotations$strikethrough
[1] FALSE
$results[[3]]$paragraph$rich_text[[2]]$annotations$underline
[1] FALSE
$results[[3]]$paragraph$rich_text[[2]]$annotations$code
[1] FALSE
$results[[3]]$paragraph$rich_text[[2]]$annotations$color
[1] "default"
$results[[3]]$paragraph$rich_text[[2]]$plain_text
[1] "Urban planning and land use"
$results[[3]]$paragraph$rich_text[[2]]$href
[1] "https://www.notion.so/6b2c4777339f4898a8498b6190ba7865"
$results[[3]]$paragraph$rich_text[[3]]
$results[[3]]$paragraph$rich_text[[3]]$type
[1] "text"
$results[[3]]$paragraph$rich_text[[3]]$text
$results[[3]]$paragraph$rich_text[[3]]$text$content
[1] ", "
$results[[3]]$paragraph$rich_text[[3]]$text$link
NULL
$results[[3]]$paragraph$rich_text[[3]]$annotations
$results[[3]]$paragraph$rich_text[[3]]$annotations$bold
[1] FALSE
$results[[3]]$paragraph$rich_text[[3]]$annotations$italic
[1] FALSE
$results[[3]]$paragraph$rich_text[[3]]$annotations$strikethrough
[1] FALSE
$results[[3]]$paragraph$rich_text[[3]]$annotations$underline
[1] FALSE
$results[[3]]$paragraph$rich_text[[3]]$annotations$code
[1] FALSE
$results[[3]]$paragraph$rich_text[[3]]$annotations$color
[1] "default"
$results[[3]]$paragraph$rich_text[[3]]$plain_text
[1] ", "
$results[[3]]$paragraph$rich_text[[3]]$href
NULL
$results[[3]]$paragraph$rich_text[[4]]
$results[[3]]$paragraph$rich_text[[4]]$type
[1] "mention"
$results[[3]]$paragraph$rich_text[[4]]$mention
$results[[3]]$paragraph$rich_text[[4]]$mention$type
[1] "page"
$results[[3]]$paragraph$rich_text[[4]]$mention$page
$results[[3]]$paragraph$rich_text[[4]]$mention$page$id
[1] "997e4a17-4b08-4f35-b86e-a5028c9910e4"
$results[[3]]$paragraph$rich_text[[4]]$annotations
$results[[3]]$paragraph$rich_text[[4]]$annotations$bold
[1] FALSE
$results[[3]]$paragraph$rich_text[[4]]$annotations$italic
[1] FALSE
$results[[3]]$paragraph$rich_text[[4]]$annotations$strikethrough
[1] FALSE
$results[[3]]$paragraph$rich_text[[4]]$annotations$underline
[1] FALSE
$results[[3]]$paragraph$rich_text[[4]]$annotations$code
[1] FALSE
$results[[3]]$paragraph$rich_text[[4]]$annotations$color
[1] "default"
$results[[3]]$paragraph$rich_text[[4]]$plain_text
[1] "Transportation"
$results[[3]]$paragraph$rich_text[[4]]$href
[1] "https://www.notion.so/997e4a174b084f35b86ea5028c9910e4"
$results[[3]]$paragraph$color
[1] "default"
$results[[4]]
$results[[4]]$object
[1] "block"
$results[[4]]$id
[1] "d99fc22c-1120-498c-a954-da70aa9a7f08"
$results[[4]]$parent
$results[[4]]$parent$type
[1] "page_id"
$results[[4]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[4]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[4]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[4]]$created_by
$results[[4]]$created_by$object
[1] "user"
$results[[4]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[4]]$last_edited_by
$results[[4]]$last_edited_by$object
[1] "user"
$results[[4]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[4]]$has_children
[1] FALSE
$results[[4]]$archived
[1] FALSE
$results[[4]]$in_trash
[1] FALSE
$results[[4]]$type
[1] "heading_1"
$results[[4]]$heading_1
$results[[4]]$heading_1$rich_text
$results[[4]]$heading_1$rich_text[[1]]
$results[[4]]$heading_1$rich_text[[1]]$type
[1] "text"
$results[[4]]$heading_1$rich_text[[1]]$text
$results[[4]]$heading_1$rich_text[[1]]$text$content
[1] "Description"
$results[[4]]$heading_1$rich_text[[1]]$text$link
NULL
$results[[4]]$heading_1$rich_text[[1]]$annotations
$results[[4]]$heading_1$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[4]]$heading_1$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[4]]$heading_1$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[4]]$heading_1$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[4]]$heading_1$rich_text[[1]]$annotations$code
[1] FALSE
$results[[4]]$heading_1$rich_text[[1]]$annotations$color
[1] "default"
$results[[4]]$heading_1$rich_text[[1]]$plain_text
[1] "Description"
$results[[4]]$heading_1$rich_text[[1]]$href
NULL
$results[[4]]$heading_1$is_toggleable
[1] FALSE
$results[[4]]$heading_1$color
[1] "default"
$results[[5]]
$results[[5]]$object
[1] "block"
$results[[5]]$id
[1] "933e132a-3bc1-4cd0-b1d5-6287d9cab90e"
$results[[5]]$parent
$results[[5]]$parent$type
[1] "page_id"
$results[[5]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[5]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[5]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[5]]$created_by
$results[[5]]$created_by$object
[1] "user"
$results[[5]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[5]]$last_edited_by
$results[[5]]$last_edited_by$object
[1] "user"
$results[[5]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[5]]$has_children
[1] FALSE
$results[[5]]$archived
[1] FALSE
$results[[5]]$in_trash
[1] FALSE
$results[[5]]$type
[1] "paragraph"
$results[[5]]$paragraph
$results[[5]]$paragraph$rich_text
$results[[5]]$paragraph$rich_text[[1]]
$results[[5]]$paragraph$rich_text[[1]]$type
[1] "text"
$results[[5]]$paragraph$rich_text[[1]]$text
$results[[5]]$paragraph$rich_text[[1]]$text$content
[1] "Complete Streets policies aim for all people regardless of travel mode, age, ability, income, race, or ethnicity to safely and conveniently access destinations. Complete Streets involve high-level policy direction that gradually modifies corridors, driveways, intersections, curbs, lanes, crosswalks, landscaping, transit stops, and more. Complete Streets policies work through everyday decision-making processes rather than a single project or design prescription. They come in a variety of forms like resolutions, policies, laws, plans, design manuals, executive orders, or tax ordinances. "
$results[[5]]$paragraph$rich_text[[1]]$text$link
NULL
$results[[5]]$paragraph$rich_text[[1]]$annotations
$results[[5]]$paragraph$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[5]]$paragraph$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[5]]$paragraph$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[5]]$paragraph$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[5]]$paragraph$rich_text[[1]]$annotations$code
[1] FALSE
$results[[5]]$paragraph$rich_text[[1]]$annotations$color
[1] "default"
$results[[5]]$paragraph$rich_text[[1]]$plain_text
[1] "Complete Streets policies aim for all people regardless of travel mode, age, ability, income, race, or ethnicity to safely and conveniently access destinations. Complete Streets involve high-level policy direction that gradually modifies corridors, driveways, intersections, curbs, lanes, crosswalks, landscaping, transit stops, and more. Complete Streets policies work through everyday decision-making processes rather than a single project or design prescription. They come in a variety of forms like resolutions, policies, laws, plans, design manuals, executive orders, or tax ordinances. "
$results[[5]]$paragraph$rich_text[[1]]$href
NULL
$results[[5]]$paragraph$color
[1] "default"
$results[[6]]
$results[[6]]$object
[1] "block"
$results[[6]]$id
[1] "31a6ca81-05b5-45fc-a530-f7c1cc8e8d33"
$results[[6]]$parent
$results[[6]]$parent$type
[1] "page_id"
$results[[6]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[6]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[6]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[6]]$created_by
$results[[6]]$created_by$object
[1] "user"
$results[[6]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[6]]$last_edited_by
$results[[6]]$last_edited_by$object
[1] "user"
$results[[6]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[6]]$has_children
[1] FALSE
$results[[6]]$archived
[1] FALSE
$results[[6]]$in_trash
[1] FALSE
$results[[6]]$type
[1] "heading_1"
$results[[6]]$heading_1
$results[[6]]$heading_1$rich_text
$results[[6]]$heading_1$rich_text[[1]]
$results[[6]]$heading_1$rich_text[[1]]$type
[1] "text"
$results[[6]]$heading_1$rich_text[[1]]$text
$results[[6]]$heading_1$rich_text[[1]]$text$content
[1] "How this policy relates to climate change"
$results[[6]]$heading_1$rich_text[[1]]$text$link
NULL
$results[[6]]$heading_1$rich_text[[1]]$annotations
$results[[6]]$heading_1$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[6]]$heading_1$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[6]]$heading_1$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[6]]$heading_1$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[6]]$heading_1$rich_text[[1]]$annotations$code
[1] FALSE
$results[[6]]$heading_1$rich_text[[1]]$annotations$color
[1] "default"
$results[[6]]$heading_1$rich_text[[1]]$plain_text
[1] "How this policy relates to climate change"
$results[[6]]$heading_1$rich_text[[1]]$href
NULL
$results[[6]]$heading_1$is_toggleable
[1] FALSE
$results[[6]]$heading_1$color
[1] "default"
$results[[7]]
$results[[7]]$object
[1] "block"
$results[[7]]$id
[1] "2c51a036-17a3-467e-b138-fc94ba81aac3"
$results[[7]]$parent
$results[[7]]$parent$type
[1] "page_id"
$results[[7]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[7]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[7]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[7]]$created_by
$results[[7]]$created_by$object
[1] "user"
$results[[7]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[7]]$last_edited_by
$results[[7]]$last_edited_by$object
[1] "user"
$results[[7]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[7]]$has_children
[1] FALSE
$results[[7]]$archived
[1] FALSE
$results[[7]]$in_trash
[1] FALSE
$results[[7]]$type
[1] "paragraph"
$results[[7]]$paragraph
$results[[7]]$paragraph$rich_text
$results[[7]]$paragraph$rich_text[[1]]
$results[[7]]$paragraph$rich_text[[1]]$type
[1] "text"
$results[[7]]$paragraph$rich_text[[1]]$text
$results[[7]]$paragraph$rich_text[[1]]$text$content
[1] "Complete Street policies play a role in larger climate goals by supporting sustainable transit options and transit-oriented development. By prioritizing street safety, active mobility, and transit, these policies can reap the climate benefits of low-carbon mobility and dense urban spaces. "
$results[[7]]$paragraph$rich_text[[1]]$text$link
NULL
$results[[7]]$paragraph$rich_text[[1]]$annotations
$results[[7]]$paragraph$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[7]]$paragraph$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[7]]$paragraph$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[7]]$paragraph$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[7]]$paragraph$rich_text[[1]]$annotations$code
[1] FALSE
$results[[7]]$paragraph$rich_text[[1]]$annotations$color
[1] "default"
$results[[7]]$paragraph$rich_text[[1]]$plain_text
[1] "Complete Street policies play a role in larger climate goals by supporting sustainable transit options and transit-oriented development. By prioritizing street safety, active mobility, and transit, these policies can reap the climate benefits of low-carbon mobility and dense urban spaces. "
$results[[7]]$paragraph$rich_text[[1]]$href
NULL
$results[[7]]$paragraph$color
[1] "default"
$results[[8]]
$results[[8]]$object
[1] "block"
$results[[8]]$id
[1] "00661a3f-13f0-4117-a27e-6186089c9e91"
$results[[8]]$parent
$results[[8]]$parent$type
[1] "page_id"
$results[[8]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[8]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[8]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[8]]$created_by
$results[[8]]$created_by$object
[1] "user"
$results[[8]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[8]]$last_edited_by
$results[[8]]$last_edited_by$object
[1] "user"
$results[[8]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[8]]$has_children
[1] FALSE
$results[[8]]$archived
[1] FALSE
$results[[8]]$in_trash
[1] FALSE
$results[[8]]$type
[1] "heading_1"
$results[[8]]$heading_1
$results[[8]]$heading_1$rich_text
$results[[8]]$heading_1$rich_text[[1]]
$results[[8]]$heading_1$rich_text[[1]]$type
[1] "text"
$results[[8]]$heading_1$rich_text[[1]]$text
$results[[8]]$heading_1$rich_text[[1]]$text$content
[1] "Image"
$results[[8]]$heading_1$rich_text[[1]]$text$link
NULL
$results[[8]]$heading_1$rich_text[[1]]$annotations
$results[[8]]$heading_1$rich_text[[1]]$annotations$bold
[1] FALSE
$results[[8]]$heading_1$rich_text[[1]]$annotations$italic
[1] FALSE
$results[[8]]$heading_1$rich_text[[1]]$annotations$strikethrough
[1] FALSE
$results[[8]]$heading_1$rich_text[[1]]$annotations$underline
[1] FALSE
$results[[8]]$heading_1$rich_text[[1]]$annotations$code
[1] FALSE
$results[[8]]$heading_1$rich_text[[1]]$annotations$color
[1] "default"
$results[[8]]$heading_1$rich_text[[1]]$plain_text
[1] "Image"
$results[[8]]$heading_1$rich_text[[1]]$href
NULL
$results[[8]]$heading_1$is_toggleable
[1] FALSE
$results[[8]]$heading_1$color
[1] "default"
$results[[9]]
$results[[9]]$object
[1] "block"
$results[[9]]$id
[1] "ad1f972d-4dc5-4dde-85f4-367ffb2ddcfd"
$results[[9]]$parent
$results[[9]]$parent$type
[1] "page_id"
$results[[9]]$parent$page_id
[1] "df0ef29f-da8a-4e74-8713-f30f19727503"
$results[[9]]$created_time
[1] "2024-08-26T12:23:00.000Z"
$results[[9]]$last_edited_time
[1] "2024-08-26T12:23:00.000Z"
$results[[9]]$created_by
$results[[9]]$created_by$object
[1] "user"
$results[[9]]$created_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[9]]$last_edited_by
$results[[9]]$last_edited_by$object
[1] "user"
$results[[9]]$last_edited_by$id
[1] "1ca75cfc-5e6e-4d74-a910-22230756647c"
$results[[9]]$has_children
[1] FALSE
$results[[9]]$archived
[1] FALSE
$results[[9]]$in_trash
[1] FALSE
$results[[9]]$type
[1] "image"
$results[[9]]$image
$results[[9]]$image$caption
list()
$results[[9]]$image$type
[1] "external"
$results[[9]]$image$external
$results[[9]]$image$external$url
[1] "https://www.mdpi.com/sustainability/sustainability-14-13142/article_deploy/html/images/sustainability-14-13142-g009b-550.jpg"
$next_cursor
NULL
$has_more
[1] FALSE
$type
[1] "block"
$block
named list()
$request_id
[1] "f5e9ef98-70fb-4c30-98f5-a2e521bcfaf2"
clear_page_children(test_page)
Deleted block 0cec0e78-1c5d-443c-906d-571d6f97151eDeleted block 59b021f4-1944-422c-abd0-bc982dc1ea63Deleted block 5a65ff61-8b18-48e3-97e0-95a0f7dccdc3Deleted block d99fc22c-1120-498c-a954-da70aa9a7f08Deleted block 933e132a-3bc1-4cd0-b1d5-6287d9cab90eDeleted block 31a6ca81-05b5-45fc-a530-f7c1cc8e8d33Deleted block 2c51a036-17a3-467e-b138-fc94ba81aac3Deleted block 00661a3f-13f0-4117-a27e-6186089c9e91Deleted block ad1f972d-4dc5-4dde-85f4-367ffb2ddcfdCleared 9 blocks from page df0ef29fda8a4e748713f30f19727503
6 Choose which pages to write to
Now we have basic logic lets just subset for pages we want to write and execute. Earlier we already created df_parsed
which is the operatioanlie tempalting data for the 5 pages for this PoC. Lets just loop through and write to each page.
%>%
df_parsed group_by(row_number()) %>%
group_walk(~{
= .x # row = df_parsed %>% slice(1)
row cli_alert_info("Starting to write to page - {row$title}")
clear_page_children(row$id_clean)
write_cec_template_poc(row)
cli_alert_success("Finished writing to page")
})
Page is already empty.
Deleted block 5c5afc0b-9686-463e-a17e-6884677ee82cDeleted block 1d76d259-dc19-401c-bbf0-36164c57f389Deleted block b08a4f69-fbd9-4ee1-a5db-5e8b0ca0e13bDeleted block de58e88c-34fd-4d83-87a0-6bd5e35bfae4Deleted block aeb7fcae-1dfb-4676-915d-6980fceae2cdDeleted block f9723304-e1ca-471f-a490-d8b29a85b2d8Deleted block b0b495b5-3234-4fa4-bac8-08e7b63baa44Deleted block b41c9773-147e-4ec3-947f-d6e9d37d98c2Deleted block 9c8da68a-c5a7-4764-b6d6-83bef4429146Cleared 9 blocks from page 81b63652a8be48eaa1b2fcfb8aa8165eDeleted block 8b23d11a-97b4-4380-9c49-18e1edd4ba45Deleted block a7656980-ed47-4a43-838b-a384551b1f54Deleted block 5ab6485d-45cf-4697-80f2-17403b9688e3Deleted block b2b77a9e-f2df-43a0-843e-71a04a6bb3acDeleted block 679ac6ea-cfed-4804-b973-b51e394519a2Deleted block 1c8196bc-dad5-44e6-a74c-596e5ea0a33bDeleted block d4284d59-bc6e-4d06-9047-756832dfcf2fDeleted block 4029a920-00d3-4ddb-ae6d-2858118ee8ccDeleted block 3b560444-18c4-42bb-9831-f97b0c201fafCleared 9 blocks from page f8f99d629bfc4668837967406ad3a01bDeleted block 710c9a3b-9cd3-40b1-bfb3-2615a96dd52dDeleted block ccff8ea7-2a35-42ce-8829-6c423a402ea2Deleted block 8dfbc9b8-ad1f-4a22-bc75-4f1d940a901dDeleted block d9d43cb6-8396-4161-b5ca-df165281029fDeleted block 815b74ef-9611-4105-9808-9a1481b1ba34Deleted block a1d001de-afce-4bbb-a01b-d63b6a199cadDeleted block 9a7a4e54-3e19-4c13-b4f4-95732affbb2eDeleted block 084ab109-3c7c-4cca-b412-9930aea2bdddDeleted block 4e47ffc8-5690-4651-a6bd-178ddf8f5836Cleared 9 blocks from page 3f0c1c1ba26a46369aaa64c8c0a3bdbdDeleted block 8ad6737d-b32a-44a8-a275-0bb20a4e6a11Deleted block 2d25a6bd-3abc-42f0-9c7e-76c635c887aaDeleted block d0a12f00-d218-4f6f-968c-8a9b36b75d15Deleted block f6910619-b06e-4618-8da4-efed0e6f472aDeleted block 0d465d25-1dd8-4a4d-87f2-091950ee16dbDeleted block abd38676-f529-48b7-8b61-8f2228dc3b81Deleted block 0e3d90b6-5587-4612-80a9-ce3aaf32ca17Deleted block d0a035cf-0a2f-4f40-8a30-71c47f502da3Deleted block 205534fc-fa22-4288-a011-546a1d5619d0Cleared 9 blocks from page c3e2e3244a3f4cf09a82c28365bd0a3e