├── .github
└── workflows
│ └── deploy.yml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── assets
├── cover.png
├── guide_1.png
├── guide_2.png
├── guide_3.png
├── guide_4.png
├── guide_5.png
├── guide_6.png
├── guide_7.png
├── guide_8.png
├── light.png
└── maxresdefault.jpg
├── dist
└── worker.js
├── package-lock.json
├── package.json
├── pages
├── error.html
└── home.html
├── src
├── helpers
│ └── actions.js
├── index.js
└── lib
│ ├── logger.js
│ ├── notify.js
│ └── notion.js
├── webpack.config.js
└── wrangler.toml
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to Cloudflare Workers
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | repository_dispatch:
8 |
9 | jobs:
10 | build-and-deploy:
11 | runs-on: ubuntu-latest
12 | name: Build & Deploy
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: Use Node.js
16 | uses: actions/setup-node@v1
17 | with:
18 | node-version: '12.x'
19 | - run: npm install
20 | - name: Publish
21 | uses: cloudflare/wrangler-action@1.3.0
22 | with:
23 | apiToken: ${{ secrets.CF_API_TOKEN }}
24 | env:
25 | CF_ACCOUNT_ID: ${{secrets.CF_ACCOUNT_ID}}
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | **/*.rs.bk
3 | Cargo.lock
4 | bin/
5 | pkg/
6 | wasm-pack.log
7 | worker/
8 | node_modules/
9 | .cargo-ok
10 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "semi": false,
4 | "trailingComma": "all",
5 | "tabWidth": 2,
6 | "printWidth": 80
7 | }
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 NotionStuff
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Notion Backups
2 |
3 | Set up automated backups for your Notion workspaces that run on a time-basis and notify you by Slack, Discord, or email, so you never worry about losing your Notion data again.
4 |
5 | 
6 |
7 | ## Warning
8 | ⚠️ This tool uses the Notion unofficial API, which means it could break at any time. I'll try my best to keep it up to date, but you should be aware of this.
9 |
10 | ## Pre-requisites
11 |
12 | - A Free [Cloudflare workers](https://dash.cloudflare.com/sign-up) account
13 | - Notion token `token_v2` (See this [guide](https://www.notion.so/Find-Your-Notion-Token-5da17a8df27a4fb290e9e3b5d9ba89c4))
14 |
15 | ## Getting started
16 |
17 | 1. Log in to your Cloudflare workers dashboard, select the workers tab, and then create a new service.
18 | 
19 |
20 | 2. Give your script a name and then click the 'create service' button.
21 | 
22 |
23 | 3. Click on the `Quick edit` button and Copy-paste the [Script code](https://raw.githubusercontent.com/notionblog/notion-backups/master/dist/worker.js?) into the editor.
24 | 
25 |
26 | 4. Follow this [guide](https://www.notion.so/Find-Your-Notion-Token-5da17a8df27a4fb290e9e3b5d9ba89c4) to find your Notion token v2.
27 |
28 | 5. Navigate to your **Worker > Settings > Variables** and add the following secrets:
29 |
30 | - `TOKEN_V2` paste the value of your Notion token (**required)**
31 | - `SLACK_WEBHOOK` paste your [Slack webhook](https://api.slack.com/messaging/webhooks#posting_with_webhooks) URL (optional to receive notification via Slack)
32 | - `DISCORD_WEBHOOK` paste your [Discord webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) URL (optional to receive notification via Discord)
33 | 
34 |
35 | 6. Returning to your worker editor page, you should now see the following page.
36 | 
37 | 7. To manually test the script, add a new variable with the name `MODE` and the value `test` to your environment variables.
38 | 
39 | 8. If you click the trigger export button again, you should receive a success message, and it will begin exporting your workspace. If you configured your Discord or Slack webhook url, you should receive a message in a few minutes, and you will also receive an email from Notion.
40 | 
41 | 9. in order for the script to execute on a time-based, you must create a cron job task for it,
42 |
43 | Navigate to **Worker > Triggers > Cron Triggers** and create a new cron trigger
44 |
45 | Examples:
46 |
47 | `0 0 * * *` will cause the script to execute once everyday.
48 |
49 | `0 0 */10 * *` will cause the script to execute once every ten days
50 |
51 | `0 0 1 * *` will cause the script to run on a monthly basis.
52 | 
53 |
54 | ## Change export format to `Markdown`
55 |
56 | To change the backup's export format from html to markdown or PDF (enterprise plan), create a new environment variable called `EXPORT_TYPE` and set its value to `html` or `markdown`.
57 |
58 | ## Guides
59 |
60 | - [Find your Notion Token](https://www.notion.so/Find-Your-Notion-Token-5da17a8df27a4fb290e9e3b5d9ba89c4)
61 | - [Set up a Slack webhook](https://api.slack.com/messaging/webhooks#posting_with_webhooks)
62 | - [Set up a Discord webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks)
63 |
64 | ## Running project locally
65 |
66 | **Requirements**
67 |
68 | - Linux or WSL
69 | - Node
70 |
71 | ### Steps to get server up and running
72 |
73 | **Install wrangler**
74 |
75 | ```
76 | npm i -g wrangler
77 | ```
78 |
79 | **Login With Wrangler to Cloudflare**
80 |
81 | ```
82 | wrangler login
83 | ```
84 |
85 | **Install packages**
86 |
87 | ```
88 | npm install
89 | ```
90 |
91 | **Run**
92 |
93 | ```
94 | wrangler dev
95 | ```
96 |
97 | # Support Me
98 |
99 |
100 |
--------------------------------------------------------------------------------
/assets/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/cover.png
--------------------------------------------------------------------------------
/assets/guide_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_1.png
--------------------------------------------------------------------------------
/assets/guide_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_2.png
--------------------------------------------------------------------------------
/assets/guide_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_3.png
--------------------------------------------------------------------------------
/assets/guide_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_4.png
--------------------------------------------------------------------------------
/assets/guide_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_5.png
--------------------------------------------------------------------------------
/assets/guide_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_6.png
--------------------------------------------------------------------------------
/assets/guide_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_7.png
--------------------------------------------------------------------------------
/assets/guide_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/guide_8.png
--------------------------------------------------------------------------------
/assets/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/light.png
--------------------------------------------------------------------------------
/assets/maxresdefault.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/notionblog/notion-backups/cee6a68bf462926ef21685c11b9287faea9418f3/assets/maxresdefault.jpg
--------------------------------------------------------------------------------
/dist/worker.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function n(o){if(t[o])return t[o].exports;var a=t[o]={i:o,l:!1,exports:{}};return e[o].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(o,a,function(t){return e[t]}.bind(null,a));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=2)}([function(e,t){e.exports='
in order for the script to execute on a time-based, you must create
a cron job task for it, Navigate to Worker > Triggers > Cron Triggers
and add a new cron trigger