Knowledge base9 September 2026·updated September 9, 2026

Notion as a data source for the site

The Notion database sends page properties and a tree of blocks via the API, the site takes them in the assembly and turns them into static pages. Analysis of the pipeline, pitfalls with expiring links to images and request limits.

What does this solve?

Texts are not edited by developers. A marketer wants to change the title on a landing page, a lawyer wants to change a paragraph in an offer, a product manager wants to change a tariff description, and each such edit turns into a task, a commit, and an upload. Installing a full-fledged CMS for ten pages is expensive: it needs to be deployed, updated, protected from hacking, and people need to be trained to use it. Notion solves this with what is already in place: the editor is familiar to the team, the rights are configured, the database with fields works as a list of materials, and the API sends the contents outside. The site remains static and fast.

How it works

Access is granted through integration. In the workspace settings, an internal integration is created, it receives a secret token, after which the desired page or database is separately shared with this integration. A missed share step is the most common reason for an “object not found” response when the token is valid: the integration only sees what was explicitly passed to it.

Each request leaves with two headers - authorization and API version. The version is fixed explicitly and only changed consciously, because the response format is different between versions.

Then the conveyor consists of four parts.

List of materials. A database query with filter and sorting returns pages along with properties. Properties are metadata of the material: title, slug, publication date, status, author, tags, cover. The answer is page-by-page: as long as the continuation sign comes in the body, you need to repeat the request with the cursor. Filtering by status directly in the request eliminates the need to filter out drafts on the site side.

Page body. Properties and contents live separately. The text of the page is obtained by requesting child blocks, and this is a tree: a block may have a sign of the presence of children, for which another request is needed. Nested lists, toggles, columns, elements inside callouts - all these are levels of recursion. For a long article, the number of requests is in the dozens.

Conversion. The block is described by type (paragraph, heading_2, bulleted_list_item, code, image, table) and an array of rich text fragments. Each fragment has its own markings: bold, italic, monospace, strikethrough, color, link. The parser's task is to assemble markdown or HTML from this. Ready-made converters cover common block types; rare ones you have to add yourself, and the unknown type should end up in the log, and not silently disappear from the page.

Files. Images and attachments are provided with signed links with a short lifespan. Paste such a link into HTML and forget - guaranteed broken images in a few hours. The file is downloaded during assembly, placed in its own storage or in a static directory, and its address is included in the markup.

Everything that comes from Notion must be picked up at the assembly and stored at home - including pictures.

The build looks like this: the script goes to the API, puts the result into a JSON cache inside the repository, and the static generator builds pages from this cache. The cache in the repository gives two things at once - repeatability of the build (the same input gives the same output, even when the API is not available) and a visible diff, which makes it clear what exactly changed in the content before uploading. The reassembly is launched according to a schedule, by a button or by automation from the database itself, which pulls the deployment webhook.

Useful scripts

  • A blog or directory maintained by marketers and support: a new entry in the database turns into a website page after reassembly.
  • Landing page with texts and prices that change more often than code: the lines are page properties, the layout is in the repository.
  • List of vacancies, team composition, FAQ —short, structured sections that require fields rather than free text.
  • Product documentation, which is still written in Notion: the public version is collected from the same database as the internal one, using a status filter.
  • A small catalog with pictures and characteristics, where the number of positions is measured in hundreds, not tens of thousands.

Limitations

API limits the request rate. A tree of deep page blocks plus page-by-page sampling of the database gives hundreds of requests for assembly, and without pauses between them, responses will begin to come with refusal. Replay with increasing delay and cache are required - otherwise the build will fail randomly.

It takes a long time to assemble. A full passage through a large section takes minutes, and this does not fit well with the habit of “corrected a typo - updated in ten seconds.” Partially cured by incremental updating based on the time of the last page edit, but editing a nested block does not always move this mark on the parent.

You cannot serve a page from Notion at the time of a user request. The API limit and delay will not withstand this - there is always a cache or static assembly between the site and Notion.

There are no drafts or previews in the usual form. The author sees his page in Notion, but does not see how it looks on the site until the build takes place. You have to do a separate preview mode, which pulls one page by identifier, bypassing the cache.

Some blocks are not converted well. Columns, synchronized blocks, nested databases, built-in widgets, and complex tables in the site layout look different than in Notion. It is better to limit the set of allowed blocks explicitly and agree on it with the authors in advance.

Calculated properties—formulas and relationship summaries—come ready-made and read-only. It is possible to write something back into Notion from the site side, but it is not worth using the database as a two-way storage of counters of views or likes: the request limit and the lack of transactions will take their toll.

There is no versioning of content tied to the site release. The history of edits lives in Notion and follows its own rules; You can roll back a site to the state of content from two weeks ago only through a committed cache.

Deleted or renamed page breaks links. The slug must be stored in a separate property and not be displayed automatically from the title, otherwise the very first edit of the title will drop the address and accumulated positions in the search.

The site, not Notion, is responsible for speed, layout and sitemap. Publishing with the built-in Notion mechanism does not solve these problems and is not suitable for search traffic.

How to check the result

Building from scratch on an empty cache - basic check. It must pass without errors and be completed within an acceptable time, and its duration is worth recording: an increase by several times means that the recursion across blocks has gotten out of control or repetitions have been added due to the limit.

After assembly - search for foreign domains in the collected statics. There should not be a single link to the Notion file storage in the finished HTML; if there is at least one, the pictures on the site will die in the next few hours. Checking is quite common grep according to the assembly catalog.

Pages from a week ago are checked separately: open material published before the last build and make sure that the images are in place. This check catches exactly the case when the file is not transferred for all types of blocks.

Diff of the cache before uploading shows what has actually changed. Editing one typo, which generates changes in a hundred files, means unstable sorting or identifiers that are generated anew on each build - because of this, the entire site is rebuilt and re-indexed instead of just one page.

The publication filter is checked in reverse: the page is transferred to draft, the assembly is launched, its address should give an error. Material that remains available via a direct link after being removed from publication is a typical leak of unannounced texts.

The parser must keep a log of ununderstood blocks. The list of unknown types after each build is read with the eyes: a silently discarded block is otherwise discovered only by the author’s complaint “I wrote a warning, but it’s not on the site.”

The build logs track failures by request frequency and number of retries. While repetitions are rare, there is a reserve; when there are a lot of them, the pipeline is based on luck and will fall at the moment when there is more content.

  • notion
  • cms
  • api
  • static sites