DEV Community

Andrei Parfenov
Andrei Parfenov

Posted on

Search and Replace: Getting Started with the Notion API SDK for JavaScript

Notion is a powerful tool for creating and managing a variety of digital content, such as notes, articles, and databases. However, one feature that many users have requested for a long time is the ability to search and replace text within Notion documents and pages.

I have a lot of documents in my Notion databases and often need to search through all of the pages and replace specific words and phrases.

For example, I have a table with instructions on how to work with remote repositories, and I want to replace all instances of "GitHub" with "GitLab" in every document:

Notion database

In this post, I'll show you how to create a simple workaround to search for text and replace it in multiple documents inside a Notion database. All you need is Node.js installed on your machine.

Link to a GitHub repo with the full code: https://github.com/andreiparfenov/search-and-replace-notion-api

Notion API Reference: https://developers.notion.com/reference/intro

This is a very simple workaround where I mostly tried to experiment with the Notion API. Please note that I was only able to implement a solution for Notion text blocks or paragraphs. My script will not work for headings, code snippets, etc. because different block types have different object properties in the Notion API. The code is also far from perfect, so feel free to leave your suggestions for improvement. Also, share about your experience working with the Notion API.

Here's a step-by-step instruction.

Set up Notion

Assuming that you have an account on Notion, go to the "My integrations" page. Click the "New integration" button. Create an internal integration with the ability to read, update, and insert content:

Create a Notion integration

Go to the database you want to work with, press "Settings" (three dots), and then click "Add connections". Choose the newly created integration.

Set up the Node.js app

Notion has a JavaScript client for the API. We'll create a folder for the new Node.js project and initialize package.json inside:

mkdir notion-search-and-replace
npm init
Enter fullscreen mode Exit fullscreen mode

Now that we have the package.json file, let's install a package with the Notion SDK:

npm install @notionhq/client
Enter fullscreen mode Exit fullscreen mode

Create a Node.js file (I created app.js) in the project folder and initialize the Notion client:

const { Client } = require("@notionhq/client");

const notion = new Client({
  auth: process.env.NOTION_TOKEN,
});
Enter fullscreen mode Exit fullscreen mode

NOTION_TOKEN is your internal integration token from Notion. If you share your code with others, make sure that it's kept in .env as well.

Next, specify the value that the script will search for and what it should be replaced with. I want to replace all occurrences of "GitHub" with "GitLab" in my text:

const searchValue = "GitHub";
const newValue = "GitLab";
Enter fullscreen mode Exit fullscreen mode

Create an entry point function:

(async () => {
  const db = await notion.databases.query({
    database_id: process.env.NOTION_API_DATABASE,
  });

  for (const page of db.results) {
    // we'll access the page's blocks here and update them
  }
})();
Enter fullscreen mode Exit fullscreen mode

In this function, we access the database by its ID and create a loop to iterate over the pages (the results property) inside the database.

When we access each page from the database, we'll need to access the page's blocks. Let's do it in a separate function:

async function retrieveBlocks(pageId) {
  const page = await notion.blocks.children.list({
    block_id: pageId,
  });

  return page.results;
}
Enter fullscreen mode Exit fullscreen mode

On Notion, a page is also a block. That's why in the code above we access the children property of blocks.

We'll need to go one more level down and access the text inside each block. Let's add the following function:

async function findAndReplace(blocks) {
  for (const block of blocks) {
    if (!block.paragraph) continue;
    const textItems = block.paragraph.rich_text;
    const newTextItems = textItems.map((item) => {
      const selectedText = item.text.content;
      const newText = selectedText.includes(searchValue)
        ? selectedText.replaceAll(searchValue, newValue)
        : selectedText;
      item.text.content = newText;
      return item;
    });
    // we'll update the corresponding block here
  }
}
Enter fullscreen mode Exit fullscreen mode

In this function, we use the paragraph.rich_text property, which is an array of objects. Yes, the text content is actually an array where elements are split by their formatting style. It may sound complicated, but here's an example:

I love GitHub.

If this is a Notion paragraph, it will have four elements in the rich_text array:

  1. "I" - non-formatted
  2. "love" - bold
  3. "GitHub" - code
  4. "." - non-formatted

Read more about rich-text in the Notion API's docs.

Then we use map() to replace every needed instance.

Finally, let's update the entire block and insert the new text items:

async function updateBlock(block, newTextItems) {
  const selectedBlock = await notion.blocks.update({
    block_id: block.id,
    paragraph: {
      rich_text: newTextItems,
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

Update the findAndReplace() function by calling updateBlock() at the very end of the for...of loop:

async function findAndReplace(blocks) {
  for (const block of blocks) {
    // all the previous code
    await updateBlock(block, newTextItems);
  }
}
Enter fullscreen mode Exit fullscreen mode

Also, update the entry point function:

(async () => {
  const db = await notion.databases.query({
    database_id: process.env.NOTION_API_DATABASE,
  });

  for (const page of db.results) {
    // call functions retrieveBlocks and findAndReplace here
    const blocks = await retrieveBlocks(page.id);
    findAndReplace(blocks);
  }
})();
Enter fullscreen mode Exit fullscreen mode

Run the code with the following command:

node app.js
Enter fullscreen mode Exit fullscreen mode

The script will replace all instances of "GitHub" in all the documents inside the database:

Page before running the script
Page after running the screen

I hope you find this useful. Share how you use the Notion API to automate your work. 🤖

Top comments (0)