Skip to content

Instantly share code, notes, and snippets.

@ian-pvd
Created February 10, 2026 22:03
Show Gist options
  • Select an option

  • Save ian-pvd/95e66193f8a3767251e7de2d0e43e76f to your computer and use it in GitHub Desktop.

Select an option

Save ian-pvd/95e66193f8a3767251e7de2d0e43e76f to your computer and use it in GitHub Desktop.
A node script that leverages the Notion CLI to export WordPress markup from a Notion database.
/**
* Notion Export
*
* Export WP block markup from a Notion data source.
*
* Usage:
* - Set environment variables:
* NOTION_TOKEN=your_notion_integration_token
* DATA_SOURCE_ID=your_notion_data_source_id
*
* Run with:
* node notion-export.js
*
* @requires @notionhq/client
*
* @see https://developers.notion.com/reference/query-a-data-source
*/
const fs = require("fs");
const { Client } = require("@notionhq/client");
// Initialize Notion client with auth token.
const notion = new Client({
auth: process.env.NOTION_TOKEN
});
/**
* Get text from Notion property types.
*
* @param {object} prop - Notion property object
* @returns {string} Extracted text value
*
* @see https://developers.notion.com/reference/property-object
*/
function getText(prop) {
// Early return for empty properties.
if (!prop) return "";
// Handle rich text
if (prop.rich_text) return prop.rich_text.map(t => t.plain_text).join("");
// Handle URL
if (prop.url) {
return prop.url;
}
// Handle rollup
if (prop.rollup) {
// Handle rollup arrays
if (prop.rollup.array?.length) {
return prop.rollup.array
.map(item => item.title?.[0]?.plain_text || item.rich_text?.[0]?.plain_text || "")
.join(", ");
}
// Handle text rollup
if (prop.rollup.type === "text" && prop.rollup.text) {
return prop.rollup.text;
}
}
// Handle select and multi-select
if (prop.select?.name) return prop.select.name;
if (prop.multi_select?.length)
return prop.multi_select.map(s => s.name).join(", ");
return "";
}
(async () => {
// Validate the request.
// @see https://nodejs.org/api/process.html#processenv
if (!process.env.DATA_SOURCE_ID) {
console.error("Error: DATA_SOURCE_ID environment variable is not set.");
process.exit(1);
}
// Request data from a Notion date source.
const dataSourceId = process.env.DATA_SOURCE_ID;
const response = await notion.dataSources.query({
data_source_id: dataSourceId,
filter: {
property: "To Export",
checkbox: { equals: true }
},
page_size: 20
});
console.log(`# Results: ${response.results.length}`);
// Initialize HTML output.
let html = "";
// Prepend markup before the notion export html.
// For example, into text or custom styles.
html += `<!-- wp:html -->
<style type="text/css">
.wp-block-group h3 {
color: #333;
margin-bottom: 0.5em;
}
</style>
<!-- /wp:html -->
`;
// Create an item count for logging.
let itemCount = 1;
// For each result, get properties and append HTML.
for (const page of response.results) {
const properties = page.properties;
const title = getText(properties.Title);
const creator = getText(properties.Creator);
const sourceUrl = getText(properties.SourceURL);
const embedRef = getText(properties.EmbedReference);
console.log(`${itemCount++} Item: ${title}`);
// Append the WordPress block markup to the HTML export.
html += `
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">${title}<br>by ${creator}</h3>
<!-- /wp:heading -->
<!-- wp:html -->
<iframe style="border: 0; width: 100%; height: 120px;" src="${embedRef}" seamless><a href="${sourceUrl}">${title}</a></iframe>
<!-- /wp:html -->
<!-- wp:buttons -->
<div class="wp-block-buttons">
<!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="${sourceUrl}" target="_blank" rel="noreferrer noopener">View Source</a></div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
</div>
<!-- /wp:group -->
`;
}
// Generate a unique, sortable timestamp suffix for the file name.
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
fs.writeFileSync(`notion-export-${timestamp}.html`, html, "utf8");
// console.log(html);
// console.log(response);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment