Heads up! This post was written before Notion came out with an official API, and uses a reverse-engineering method that isnāt officially supported. Notion now has an official developer API, so you should use that instead. I no longer maintain Potion, which is used in this article.
I wrote my own reverse-engineered API for Notion, called Potion. The code is open source on GitHub.
Today, weāre going to use that API to turn a Notion document into a website.
Thereās two ways of doing it: using a static website (no server), or using a Node.js server. Weāll also discuss the pros and cons of each.
Getting the ID of your Notion doc
For both of these methods, youāll need the ID of your Notion doc.
First, make the Notion doc public using the Share button in the top right corner:
Then, click the Copy page link button and paste it somewhere. The long random string of characters in that link is the document ID:
Weāll use this ID in our code later.
Method 1: Static website
The benefits of this approach are that you can host the website very cheaply (for example, on Netlify) since itās just static files. However, the webpage is empty before the javascript executes, and crawlers (like Google) need to run the javascript in order to āseeā the contents.
Letās set up the skeleton of the web page:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Notion Doc</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/style.css" />
<script src="/script.js" defer></script>
</head>
<body>
<main></main>
</body>
</html>
This empty HTML page links a javascript file (at /script.js
) and a CSS file (/style.css
).
I also added an empty <main>
element in the body, which is where weāll load the Notion doc into.
Then, I wrote some javascript in script.js
that makes a request to the Potion API and fills in the <main>
element with the result. It uses the Notion document ID you copied earlier.
const notionDocId = "0cb628857f3c4c77bf7f9a879a6ec21d";
fetch("https://potion-api.now.sh/html?id=" + notionDocId)
.then((res) => res.text())
.then((text) => {
document.querySelector("main").innerHTML = text;
});
Thatās it! Now you have a website powered by your Notion doc. Hereās the full code if youād like to check it out: Live demo and source code.
Method 2: Node.js server
The benefits of this approach are that the HTML sent by the server fully includes the Notion documentās content, so itās easy for web crawlers (like Google) to read and understand. It doesnāt require any client-side javascript to run. However, you need to run a full Node.js server to host it, so this solution canāt be hosted on a static file host.
I started by installing express
, a framework for Node.js servers, and node-fetch
, a package that replicates the fetch
API in Node.js.
const express = require("express");
const app = express();
const fetch = require("node-fetch");
app.listen(process.env.PORT);
Then, I added this Express route. It uses the Notion doc ID you copied earlier, makes a request to the Potion API, and then inserts the result of the API request in an HTML document on the server.
app.get("/", (req, res) => {
const notionDocId = "0cb628857f3c4c77bf7f9a879a6ec21d";
fetch("https://potion-api.now.sh/html?id=" + notionDocId)
.then((res) => res.text())
.then((text) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Notion Doc</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: system-ui, sans-serif;
}
img {
max-width: 100%;
max-height: 70vh;
}
/* add your own CSS to make it look how you want */
</style>
</head>
<body>
<main>${text}</main>
</body>
</html>
`);
});
});
This website looks the exact same, but is generated on the server-side instead of in the browser. Hereās the full code for the Node.js solution: Live demo and source code.