{"id":13519945,"url":"https://github.com/methylDragon/notion-backups","last_synced_at":"2025-03-31T14:31:26.889Z","repository":{"id":39980692,"uuid":"468643204","full_name":"methylDragon/notion-backups","owner":"methylDragon","description":"Blazingly fast async multi-user, multi-space Notion backups, invoked manually or with GH actions!","archived":false,"fork":false,"pushed_at":"2022-04-28T23:26:40.000Z","size":43,"stargazers_count":15,"open_issues_count":3,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-18T10:18:49.155Z","etag":null,"topics":["actions","async","automatic-backups","backups","cli","cli-app","gh-actions","nodejs","notion","npm-package"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/notion-backups","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/methylDragon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-03-11T06:58:15.000Z","updated_at":"2024-09-08T07:17:09.000Z","dependencies_parsed_at":"2022-06-26T01:32:08.156Z","dependency_job_id":null,"html_url":"https://github.com/methylDragon/notion-backups","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/methylDragon%2Fnotion-backups","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/methylDragon%2Fnotion-backups/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/methylDragon%2Fnotion-backups/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/methylDragon%2Fnotion-backups/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/methylDragon","download_url":"https://codeload.github.com/methylDragon/notion-backups/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246483038,"owners_count":20784823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","async","automatic-backups","backups","cli","cli-app","gh-actions","nodejs","notion","npm-package"],"created_at":"2024-08-01T05:02:07.280Z","updated_at":"2025-03-31T14:31:26.634Z","avatar_url":"https://github.com/methylDragon.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","HarmonyOS"],"sub_categories":["Windows Manager"],"readme":"# notion-backups\n\n[![npm version](https://badge.fury.io/js/notion-backups.svg)](https://badge.fury.io/js/notion-backups) [![GitHub version](https://badge.fury.io/gh/methyldragon%2Fnotion-backups.svg)](https://badge.fury.io/gh/methyldragon%2Fnotion-backups)\n\n\n\n## Description\n\nThis is a very simple tool to export a workspace from [Notion](https://www.notion.so/), designed to work as part of a GitHub workflow.\n\nIt's forked from [the original](https://github.com/darobin/notion-backup) (`notion-backup`), and offers additional functionality, such as:\n\n- Choosing export type\n- Backing up **multiple spaces** from **multiple users** into nice and neat directories\n- Blazingly fast backups, achieved by using asynchronous calls :fire:\n\nBut this comes at the tradeoff of requiring an extra parameter.\n\nIf you don't need any of the additional functionalities from this package, you can continue using the original!\n\n\u003e **Why this independent fork?**\n\u003e\n\u003e Unfortunately this would lead to API breaking bugs in the original, and so, this package has been independently released to be used in parallel to the original. I wrote this for myself, and wanted a nice and easy way to access the package, and I think things have been sufficiently changed to warrant a new package being created.\n\u003e\n\u003e Still though, credits for the original and the base of this package goes to [Robin Berjon](https://github.com/darobin).\n\n\n\n## Quick Start\n\nYou can actually run this in your command line easily with environment variables instead of GitHub action secrets!\n\n### If you have one space...\n\n```shell\n$ export BACKUP_DIRS=some/directory\n$ export NOTION_TOKENS=\u003ctoken_1\u003e\n$ export NOTION_SPACE_IDS=\u003cspace_1\u003e\n$ export NOTION_USER_IDS=\u003cuser_1\u003e\n\n# OPTIONAL, choose one, or none, in which case you're choosing both!\n$ export EXPORT_TYPE=html\n$ export EXPORT_TYPE=markdown\n\n$ npm install notion-backups\n$ notion-backups\n```\n\n\u003e Follow [this blog post](https://artur-en.medium.com/automated-notion-backups-f6af4edc298d) to see how to obtain your Notion tokens and IDs.\n\n\n\n### If you have more than one space, and more than one user!?!\n\n```shell\n$ export BACKUP_DIRS=some/directory; another/directory\n$ export NOTION_TOKENS=\u003ctoken_1\u003e; \u003ctoken_2\u003e\n$ export NOTION_SPACE_IDS=\u003cspace_1\u003e; \u003cspace_2\u003e\n$ export NOTION_USER_IDS=\u003cuser_1\u003e; \u003cuser_2\u003e\n\n# OPTIONAL, choose one, or none, in which case you're choosing both!\n$ export EXPORT_TYPE=html\n$ export EXPORT_TYPE=markdown\n\n$ npm install notion-backups\n$ notion-backups\n```\n\n\n\n## Detailed Usage Guide\n\nIn order to achieve multi-user, multi-space backing up functionality, you need to set your GitHub action secrets up a little bit more properly. Different from the original, now, you can enter a **semicolon-delineated** list of IDs!\n\nNo worries on spaces appearing next to each semicolon, the script trims them out for you. So actually if you wanted, you could even use newlines, as long as you put a semicolon between each list element!\n\n\u003e  **NOTE**: If you log out of your account, the `NOTION_TOKEN` will get invalidated and this process will fail. There isn't anything that I know of that I can do about that until Notion decides to add a backup endpoint to their official API, at which point this will be able to use a proper authentication token.\n\nThe secrets you need are:\n\n- `BACKUP_DIRS`\n  - Determines where the backups are saved, relative to the root of the repository\n- `NOTION_TOKENS`\n  - Your Notion user token (**one token per session**, can be used for multiple users if you're logged in to the same session), but with a caveat stated later on\n- `NOTION_SPACE_IDS`\n  - Your Notion space IDs (**one ID per workspace**) for spaces targeted for backup\n- `NOTION_USER_IDS`\n  - Your Notion user IDs (**one ID per user**, used for all workspaces that user has access to), same caveat for `NOTION_TOKENS` applies\n\n\n\u003e If you need to know how to get your `NOTION_TOKENS` or `NOTION_SPACE_IDS`, follow [this blog post](https://artur-en.medium.com/automated-notion-backups-f6af4edc298d).\n\u003e\n\u003e You can follow a similar process for the `NOTION_USER_IDS`, just look for the `notion_user_id` in the request headers.\n\nThere is also an optional secret you can use:\n\n- `EXPORT_TYPE` = {`\"markdown\"`, `\"html\"`, `\"\"`}\n  - Not entering anything causes both types to be backed up, otherwise it'll backup the requested type\n\n\n\n### Single Space Case\n\nFor the single space case, it's relatively trivial, just specify stuff as needed\n\n```\nBACKUP_DIRS: whatever/dir/you/want\nNOTION_TOKENS: \u003cyour_notion_token_v2\u003e\nNOTION_SPACE_IDS: \u003cyour_notion_space_id\u003e\nNOTION_USER_IDS: \u003cyour_notion_user_id\u003e\n```\n\nI'd personally recommend setting up your BACKUP_DIR to be `\u003cuser\u003e/\u003cspace_name\u003e`, but you can do whatever you want, really. Just know that it'll be **relative to your project root.**\n\n\n\n### Multi-Space, Single User Case\n\n\u003e Ensure all lists are the same element lengths!\n\nWith multiple spaces, things get a little bit more complicated. You'll need to either repeat your token declaration, or use the shorthand.\n\nIn this example, we're trying to back up three spaces that belong to the same user.\n\n**Explicit**\n\n```\nBACKUP_DIRS: \u003cdir_1\u003e; \u003cdir_2\u003e; \u003cdir_3\u003e\nNOTION_TOKENS: \u003ctoken_v2\u003e; \u003ctoken_v2\u003e; \u003ctoken_v2\u003e\nNOTION_SPACE_IDS: \u003cid_1\u003e; \u003cid_2\u003e; \u003cid_3\u003e\nNOTION_USER_IDS: \u003cuid_1\u003e; \u003cuid_1\u003e; \u003cuid_1\u003e\n```\n\nNotice that the tokens and user IDs are identical! This is because in this case, we're just accessing them using the **same session**, for a **single user**.\n\n**Shorthand**\n\n\u003e  The `node.js` script I modified makes an affordance to mitigate repetitions by allowing you to use `*` to tell the script to use the closest preceding valid entry. If you use this, you **must** specify your tokens in order (or at least, ensure that every `*` instance is preceded by the notion token that you want to be substituting in, or another `*`, all the way till it hits a non-`*` entry.)\n\nYou can use the same shorthand for user IDs!\n\n```\nBACKUP_DIRS: \u003cdir_1\u003e; \u003cdir_2\u003e; \u003cdir_3\u003e\nNOTION_TOKENS: \u003ctoken_v2\u003e; *; *\nNOTION_SPACE_IDS: \u003cid_1\u003e; \u003cid_2\u003e; \u003cid_3\u003e\nNOTION_USER_IDS: \u003cuid_1\u003e; *; *\n```\n\n\n\n### Multi-Space, Multi-User Case\n\n\u003e Ensure all lists are the same element lengths!\n\nIt should be pretty obvious what needs to be done here. Do the same repetitions, or use the shorthand, but ensure that there are more notion tokens in the mix.\n\nIn this case, we have two users, with two spaces each.\n\n**Explicit**\n\n```\nBACKUP_DIRS: \u003cdir_1\u003e; \u003cdir_2\u003e; \u003cdir_3\u003e; \u003cdir_4\u003e\nNOTION_TOKENS: \u003ctoken_v2_1\u003e; \u003ctoken_v2_1\u003e; \u003ctoken_v2_2\u003e; \u003ctoken_v2_2\u003e\nNOTION_SPACE_IDS: \u003cid_1\u003e; \u003cid_2\u003e; \u003cid_3\u003e; \u003cid_4\u003e\nNOTION_USER_IDS: \u003cuid_1\u003e; \u003cuid_2\u003e; \u003cuid_3\u003e; \u003cuid_4\u003e\n```\n\nWith the explicit method, you can swap the ordering, as long as each dir-token-id triplet appear in the same index.\n\n```\nBACKUP_DIRS: \u003cdir_1\u003e; \u003cdir_3\u003e; \u003cdir_2\u003e; \u003cdir_4\u003e\nNOTION_TOKENS: \u003ctoken_v2_1\u003e; \u003ctoken_v2_2\u003e; \u003ctoken_v2_1\u003e; \u003ctoken_v2_2\u003e\nNOTION_SPACE_IDS: \u003cid_1\u003e; \u003cid_3\u003e; \u003cid_2\u003e; \u003cid_4\u003e\nNOTION_USER_IDS: \u003cuid_1\u003e; \u003cuid_3\u003e; \u003cuid_2\u003e; \u003cuid_4\u003e\n```\n\n**Shorthand**\n\nYou can't swap the ordering around with the shorthand method though! But it'll cut down on the amount of copy-pasting you need to do.\n\n```\nBACKUP_DIRS: \u003cdir_1\u003e; \u003cdir_2\u003e; \u003cdir_3\u003e; \u003cdir_4\u003e\nNOTION_TOKENS: \u003ctoken_v2_1\u003e; *; \u003ctoken_v2_2\u003e; *\nNOTION_SPACE_IDS: \u003cid_1\u003e; \u003cid_2\u003e; \u003cid_3\u003e; \u003cid_4\u003e\nNOTION_USER_IDS: \u003cuid_1\u003e; \u003cuid_2\u003e; \u003cuid_3\u003e; \u003cuid_4\u003e\n```\n\nHere, the first `*` is substituted with `\u003ctoken_v2_1\u003e`, and the second `*` is substituted with `\u003ctoken_v2_2\u003e`.\n\n\n\n### Bonus: Choosing Export Type\n\nYou can specify the optional secret, `EXPORT_TYPE` to determine what export type you want for **all backup jobs**.\n\nYou don't repeat the type.\n\n```\nBACKUP_DIRS: \u003cdir_1\u003e; \u003cdir_2\u003e; \u003cdir_3\u003e; \u003cdir_4\u003e\nNOTION_TOKENS: \u003ctoken_v2_1\u003e; *; \u003ctoken_v2_2\u003e; *\nNOTION_SPACE_IDS: \u003cid_1\u003e; \u003cid_2\u003e; \u003cid_3\u003e; \u003cid_4\u003e\nEXPORT_TYPE: markdown\n```\n\n\n\n## Setup: Notion Backups Using GitHub Actions\n\nThis assumes you are looking to set this up to back up Notion to GitHub.\n\n1. Create a repo for your backup. You probably want it private.\n2. Get as many `NOTION_TOKENS`, `NOTION_SPACE_IDS`, and `NOTION_USER_IDS` elements as explained in [this blog post](https://medium.com/@arturburtsev/automated-notion-backups-f6af4edc298d).\n3. Set them as GitHub action secrets in your GitHub repo, following the usage guide above. Also remember to set `BACKUP_DIRS` and optionally `EXPORT_TYPE`!\n4. Install the following under `.github/workflows/\u003cwhatever\u003e.yml` in your repo.\n\nThe `cron` schedule triggers every 4th hour, but you can set your own schedule, using this [handy cron interpreter](https://crontab.guru/) to craft your schedule.\n\n```yaml\nname: \"Notion Backups\"\n\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - master\n  schedule:\n    -   cron: \"0 */4 * * *\"\n\njobs:\n  backup:\n    runs-on: ubuntu-latest\n    name: Backup\n    timeout-minutes: 15\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          node-version: '12'\n      - name: Setup dependencies\n        run: npm install -g notion-backups\n\n      - name: Run backup\n        run: notion-backups\n        env:\n          BACKUP_DIRS: ${{ secrets.BACKUP_DIRS }}\n          NOTION_TOKENS: ${{ secrets.NOTION_TOKENS }}\n          NOTION_SPACE_IDS: ${{ secrets.NOTION_SPACE_IDS }}\n          NOTION_USER_IDS: ${{ secrets.NOTION_USER_IDS }}\n          EXPORT_TYPE: ${{ secrets.EXPORT_TYPE }}\n          NODE_OPTIONS: '--max-http-header-size=80000'\n\n      - name: Delete zips\n        run: \"find . -type f -name '*.zip' -exec echo 'Cleaning up: {}' \\\\; -exec rm {} +\"\n\n      - name: Commit changes\n        uses: elstudio/actions-js-build/commit@v3\n        with:\n          commitMessage: Automated snapshot\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FmethylDragon%2Fnotion-backups","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FmethylDragon%2Fnotion-backups","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FmethylDragon%2Fnotion-backups/lists"}