• Home
  • Blog
  • Stack

© 2026 YIKZERO

Next.js Calling Notion API Records

Develop· October 4, 2023
This article was translated from Chinese byGemini 3 Pro. If there are any discrepancies, please refer to the Chinese version.

Pitfalls Collection

The pitfalls stem partly from Next.js and partly from the Notion API. Of course, I am the biggest pitfall myself.

  1. Next.js Server-Side Rendering
  2. Notion API Data Filtering
  3. Notion Block Data Rendering
  4. Notion Temporary Image Expiration
  5. Next.js Image Component Usage
  6. Notion Article Page Style Rendering

These are essentially all the pitfalls I encountered. Before sharing the experience of dealing with them, I'd like to briefly discuss the original intention of the project.

Original Intention

Initially, after learning frontend development, I wanted to understand the backend. I first created a full-stack text-to-speech project based on edge-tts, Rotts (Frontend React + Backend Flask). However, this project was very simple; the backend basically just requested the API, fetched the list of voices, passed information like voice, pitch, and text to edge-tts, waited for the audio return, and then allowed playback/download. It felt like the backend experience ended before it truly began.

So, I decided to find another project to continue learning the backend. My first thought was Node.js. During my research, I saw many people recommending Next.js, which is also based on Node.js. It was a perfect fit. I also wanted to simply build a wheel—a minimalist blogging system using Notion as the CMS. Visually, everything would be simplified to reduce overhead, focusing primarily on content rendering.

I originally thought that with ChatGPT, I could just ask it if I got stuck. However, the Next.js App Router was too new, and it wasn't in its knowledge base. Every time I asked about related content, the answers were not accurate enough.

Project Information

  • Name: Brog
  • Description: A minimalist blogging system built with Next.js using Notion as the CMS.
  • Tech Stack: React + Next.js + Typescript + TailwindCSS
  • Github: https://github.com/yikZero/Brog

Next.js Pitfalls

Duplicate Requests

When I first started fetching data, I had a doubt: I fetch here, and I fetch there. If it's the same data, won't making multiple requests be wasteful?

Because of this, I was constantly separating function logic from requests, trying to pass multiple props... But actually, you don't need to worry about this, at least not in React.

Passing data between a parent layout and its children is not possible. However, you can fetch the same data in a route more than once, and React will automatically dedupe the requests without affecting performance.

If the URL and parameters you are fetching remain unchanged, React will help merge your multiple requests into a single request. So, you don't need to keep forwarding props between components; just request the same data multiple times, it's fine. React will automatically merge the requests and will not make duplicate requests that impact network performance.

Server Components

What counts as a Server Component? Components placed under the app/ directory should all be Server Components. When I wasn't sure if something was a Server Component, I threw all the components and lib directories I used into app/... just to make them Server Components.

To turn it into a Client Component, just add use client at the top, and it will be recognized as a Client Component. The official Next.js recommendation is to use Server Components whenever possible.

next/image Usage

The official Next.js team optimized the usage of the <img> element and recommends using the official Image component due to LCP performance.

For specific usage instructions, refer to Image Optimization

I thought it would be simple—just replacing the name—but it required me to provide explicit height and width. How would I know the height and width of dynamically fetched images? So, I resorted to a clever workaround... which was the solution found on stackoverflow.

<figure className="relative">
<image
src="{src}"
width="{0}"
height="{0}"
sizes="100vw"
className="w-full h-auto"
/>
</figure>

Notion-Client Pitfalls

Notion API
Notion API

Data Retrieval

Notion officially provides @notionhq/client, and react-notion-x also has a notion-client. I first learned about notion-client, so after finishing the styling, I tried integrating the third-party implementation.

Well, notion-client is decent. It allows you to retrieve data by providing a public NOTION_PAGE_ID environment variable. However, it retrieves full data and lacks the filtering capability based on field names that the official API offers, making data organization much more cumbersome. For a beginner like me, this was too much trouble... After all, the data retrieved from Notion is layered like nesting dolls, and every block has its ID, which left me utterly confused.

In the end, I referenced the official API implementation used in notion-blog-nextjs to retrieve the corresponding data.

Image Expiration

The image links provided in the official Notion data are temporary Amazon links that expire after one hour. This causes the images to break.

Vercel Cron: Many people choose to use Vercel cron functionality to rebuild and re-render every hour. But I think this is too resource-intensive and not environmentally friendly (:

Converting Temporary Addresses to Permanent Addresses: For a solution, you can refer to fix: solve linked img crash #524.

Uploading via PicGo to Upyun: Because I have migrated data before, using relative addresses for Markdown images would be a disaster. Therefore, I now choose to upload images to Upyun via PicGo, which returns my CDN address. If I ever need to migrate again, at least the images won't be lost.

Modular UI Design Research: Icons
HomeLab Environment Configuration