skip to content
Site header image Demo Astro Notion Setup

Stream

Are you looking for me rambling? Here is where you can take a peek at me babbling.
  • Lorem ipsum dolor sit amet 我爱你 with 愛してます

    This is lorem ipsum

    Lorem ipsum content with an image and a random file below

    import process from "node:process";
    import { TodoistApi } from "npm:@doist/todoist-api-typescript";
    import { Client } from "npm:@notionhq/client";
    
    const TODOIST_API_KEY = process.env.TODOIST_API_KEY;
    const todoistapi = new TodoistApi(TODOIST_API_KEY);
    const NOTION_API_KEY = process.env.NOTION_API_KEY;
    const notion = new Client({
      auth: NOTION_API_KEY,
    });
    
    var add_to_notion_todoist_project_id = "PROJECT_ID_HERE";
    
    var todoist_dict_mapping = {
      "habit": {
        "todoist-section-id": "SECTION_ID_HERE",
        "notion-map-type": "page",
        "notion-id": "PAGE_ID_HERE",
      },
      "papers": {
        "todoist-section-id": "SECTION_ID_HERE",
        "notion-map-type": "database",
        "notion-id": "DB_ID_HERE",
      },
    };
    
    function getNotionId(section_id) {
      if (!section_id) {
        return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
      }
    
      for (var key in todoist_dict_mapping) {
        if (todoist_dict_mapping[key]["todoist-section-id"] === section_id) {
          return [
            todoist_dict_mapping[key]["notion-map-type"] || todoist_dict_mapping["dump"]["notion-map-type"],
            todoist_dict_mapping[key]["notion-id"] || todoist_dict_mapping["dump"]["notion-id"],
          ];
        }
      }
    
      return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
    }
    
    function convertDateObject(due) {
      function convertToISOWithOffset(datetimeStr, timezoneStr) {
        const date = new Date(datetimeStr);
        const [, sign, hours, minutes] = timezoneStr.match(/GMT ([+-])(\d{1,2}):(\d{2})/);
        date.setUTCMinutes(date.getUTCMinutes() + (parseInt(hours) * 60 + parseInt(minutes)) * (sign === "+" ? 1 : -1));
        return date.toISOString().split(".")[0]
          + `${sign}${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
      }
      const formatDate = (date, datetime, timezone) => {
        let isoString = datetime ? datetime : date;
        if (timezone && timezone.startsWith("GMT") && timezone.length > 3) {
          return convertToISOWithOffset(datetime, timezone);
        } else {
          return isoString;
        }
      };
    
      return {
        start: due ? formatDate(due.date, due.datetime, due.timezone) : new Date().toISOString(),
        end: null,
        time_zone: due && due.datetime && due.timezone && due.timezone.startsWith("GMT") && due.timezone.length > 3
          ? null
          : (due && due.datetime && due.timezone ? due.timezone : "America/Los_Angeles"),
      };
    }
    
    async function addCalloutToNotionPage(page_id, content, date) {
      console.log(JSON.stringify(date));
      const response = await notion.blocks.children.append({
        block_id: page_id,
        children: [{
          "callout": {
            "rich_text": [{
              "type": "mention",
              "mention": {
                "type": "date",
                "date": date,
              },
            }],
            "icon": {
              "type": "external",
              "external": {
                "url": "https://www.notion.so/icons/circle-dot_lightgray.svg",
              },
            },
            "children": [{
              "paragraph": {
                "rich_text": [{
                  "text": {
                    "content": content,
                  },
                }],
              },
            }],
          },
        }],
      });
      console.log(JSON.stringify(response));
    }
    
    async function addPageToNotionDatabse(database_id, content) {
      const response = await notion.pages.create({
        "parent": {
          "type": "database_id",
          "database_id": database_id,
        },
        "properties": {
          "Name": {
            "title": [{
              "text": {
                "content": content,
              },
            }],
          },
        },
      });
    }
    
    export default async function(interval: Interval) {
      var tasks = await todoistapi.getTasks({
        projectId: add_to_notion_todoist_project_id,
      });
    
      for (const task of tasks) {
        console.log(task);
        const [mappedNotionType, mappedNotionId] = getNotionId(task.sectionId);
        if (mappedNotionId)
        {
          if (mappedNotionType == "page" && mappedNotionId) {
            addCalloutToNotionPage(mappedNotionId, task.content, convertDateObject(task.due));
          }
          else if (mappedNotionType == "database" && mappedNotionId) {
            addPageToNotionDatabse(mappedNotionId, task.content);
          }
          todoistapi.deleteTask(task.id);
        }
      }
    }
    Remember this code is in format of val town and hence the weird imports. You would need to switch that to require probably (I ain’t good at JS)
    Code in case you want to host somewhere else
    import process from "node:process";
    import { TodoistApi } from "npm:@doist/todoist-api-typescript";
    import { Client } from "npm:@notionhq/client";
    
    const TODOIST_API_KEY = process.env.TODOIST_API_KEY;
    const todoistapi = new TodoistApi(TODOIST_API_KEY);
    const NOTION_API_KEY = process.env.NOTION_API_KEY;
    const notion = new Client({
      auth: NOTION_API_KEY,
    });
    
    var add_to_notion_todoist_project_id = "PROJECT_ID_HERE";
    
    var todoist_dict_mapping = {
      "habit": {
        "todoist-section-id": "SECTION_ID_HERE",
        "notion-map-type": "page",
        "notion-id": "PAGE_ID_HERE",
      },
      "papers": {
        "todoist-section-id": "SECTION_ID_HERE",
        "notion-map-type": "database",
        "notion-id": "DB_ID_HERE",
      },
    };
    
    function getNotionId(section_id) {
      if (!section_id) {
        return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
      }
    
      for (var key in todoist_dict_mapping) {
        if (todoist_dict_mapping[key]["todoist-section-id"] === section_id) {
          return [
            todoist_dict_mapping[key]["notion-map-type"] || todoist_dict_mapping["dump"]["notion-map-type"],
            todoist_dict_mapping[key]["notion-id"] || todoist_dict_mapping["dump"]["notion-id"],
          ];
        }
      }
    
      return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
    }
    
    function convertDateObject(due) {
      function convertToISOWithOffset(datetimeStr, timezoneStr) {
        const date = new Date(datetimeStr);
        const [, sign, hours, minutes] = timezoneStr.match(/GMT ([+-])(\d{1,2}):(\d{2})/);
        date.setUTCMinutes(date.getUTCMinutes() + (parseInt(hours) * 60 + parseInt(minutes)) * (sign === "+" ? 1 : -1));
        return date.toISOString().split(".")[0]
          + `${sign}${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
      }
      const formatDate = (date, datetime, timezone) => {
        let isoString = datetime ? datetime : date;
        if (timezone && timezone.startsWith("GMT") && timezone.length > 3) {
          return convertToISOWithOffset(datetime, timezone);
        } else {
          return isoString;
        }
      };
    
      return {
        start: due ? formatDate(due.date, due.datetime, due.timezone) : new Date().toISOString(),
        end: null,
        time_zone: due && due.datetime && due.timezone && due.timezone.startsWith("GMT") && due.timezone.length > 3
          ? null
          : (due && due.datetime && due.timezone ? due.timezone : "America/Los_Angeles"),
      };
    }
    
    async function addCalloutToNotionPage(page_id, content, date) {
      console.log(JSON.stringify(date));
      const response = await notion.blocks.children.append({
        block_id: page_id,
        children: [{
          "callout": {
            "rich_text": [{
              "type": "mention",
              "mention": {
                "type": "date",
                "date": date,
              },
            }],
            "icon": {
              "type": "external",
              "external": {
                "url": "https://www.notion.so/icons/circle-dot_lightgray.svg",
              },
            },
            "children": [{
              "paragraph": {
                "rich_text": [{
                  "text": {
                    "content": content,
                  },
                }],
              },
            }],
          },
        }],
      });
      console.log(JSON.stringify(response));
    }
    
    async function addPageToNotionDatabse(database_id, content) {
      const response = await notion.pages.create({
        "parent": {
          "type": "database_id",
          "database_id": database_id,
        },
        "properties": {
          "Name": {
            "title": [{
              "text": {
                "content": content,
              },
            }],
          },
        },
      });
    }
    
    export default async function(interval: Interval) {
      var tasks = await todoistapi.getTasks({
        projectId: add_to_notion_todoist_project_id,
      });
    
      for (const task of tasks) {
        console.log(task);
        const [mappedNotionType, mappedNotionId] = getNotionId(task.sectionId);
        if (mappedNotionId)
        {
          if (mappedNotionType == "page" && mappedNotionId) {
            addCalloutToNotionPage(mappedNotionId, task.content, convertDateObject(task.due));
          }
          else if (mappedNotionType == "database" && mappedNotionId) {
            addPageToNotionDatabse(mappedNotionId, task.content);
          }
          todoistapi.deleteTask(task.id);
        }
      }
    }
    Remember this code is in format of val town and hence the weird imports. You would need to switch that to require probably (I ain’t good at JS)



    sample2.html Download

  • Title but no excerpt or tags works

    Content here?

    xychart-beta
        title "Sales Revenue"
        x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
        y-axis "Revenue (in $)" 4000 --> 11000
        bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
        line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]