Skill: vaibhav1805/notion-to-markdown (version 1.0.1)

--- name: notion-to-markdown description: "Convert Notion pages and databases to markdown format using the official Notion API. Use when you need to: (1) Export a single Notion page to markdown, (2) Bulk export entire Notion databases, (3) Automate Notion content publishing, or (4) Integrate Notion content into documentation workflows. Requires Notion API token setup." metadata: requiredCredentials: "NOTION_API_KEY" credentialsType: "Notion API token (personal integration)" networkAccess: "Notion API only (@notionhq/client)" supplyChainRisk: "Low - only talks to official Notion API, no external data sources" security: "Read-only access recommended. Only shares specific pages, not entire workspace." --- # Notion to Markdown Converter Convert Notion pages and databases to clean, readable markdown using the official Notion API. ## ⚠️ Security & Credentials **Required Credentials:** - `NOTION_API_KEY` - Your personal Notion integration token (required) **Security Best Practices:** 1. **Create a dedicated integration** - Go to [notion.so/my-integrations](https://www.notion.so/my-integrations) and create an integration for this tool only 2. **Use read-only permissions** - Grant the integration "Reader" access, not "Editor" 3. **Share selectively** - Only share specific pages/databases with the integration, not your entire workspace 4. **Protect your token** - Never commit `.env` files containing `NOTION_API_KEY` to version control 5. **Use temporary tokens** - Consider creating a rotation policy for tokens or using temporary tokens 6. **Code inspection** - This tool only uses the official `@notionhq/client` library and communicates exclusively with Notion's API. No data is sent elsewhere. **Network Access:** - Only connects to: `https://api.notion.com` (official Notion API) - No external APIs or data sources - No telemetry or logging sent elsewhere ## Requirements - **Node.js:** 14.0.0 or higher - **npm:** 6.0.0 or higher - **Notion API Token:** Required (get from [notion.so/my-integrations](https://www.notion.so/my-integrations)) Check your Node version: ```bash node --version # Should be v14.0.0 or higher npm --version ``` ## Quick Start ### 1. Get Your Notion API Key See [Notion API Setup](references/notion-api-setup.md) for complete instructions: - Create an integration at [notion.so/my-integrations](https://www.notion.so/my-integrations) - Copy your API token (`notioneq_...`) - Share your Notion pages with the integration - Set environment variable: `export NOTION_API_KEY="your_token"` ### 2. Install Dependencies ```bash cd scripts npm install ``` ### 3. Convert Pages **Single page:** ```bash NOTION_API_KEY=your_token node convert.js <page-id> > output.md ``` **Database export:** ```bash NOTION_API_KEY=your_token node convert.js <database-id> --database ./exports ``` ## Usage Patterns ### Convert Single Notion Page Extract a page and output to a file: ```bash node scripts/convert.js a1b2c3d4e5f6g7h8 > my-page.md ``` The converter automatically: - Fetches the page from Notion - Converts all blocks to markdown - Preserves formatting (bold, italic, links, etc.) - Outputs to stdout or file ### Bulk Export Database Convert all pages in a Notion database: ```bash node scripts/convert.js a1b2c3d4e5f6g7h8 --database ./notion-export ``` Creates individual markdown files for each page: ``` notion-export/ ├── page-one.md ├── page-two.md └── page-three.md ``` ### Extract Page Metadata The converter preserves page properties: ```javascript const result = await convertPageToMarkdown(pageId); console.log(result.title); // Page title from Notion console.log(result.markdown); // Converted markdown content console.log(result.pageId); // Original page ID ``` ## What Gets Converted ### Supported Block Types ✅ Text, headings, and paragraphs ✅ Bold, italic, underline, strikethrough, code inline ✅ Links (internal and external) ✅ Lists (ordered and unordered) ✅ Code blocks with syntax highlighting ✅ Tables ✅ Quotes and callouts ✅ Images (as markdown image syntax) ✅ Dividers and separators ✅ Database properties as frontmatter ### Formatting Preserved - Heading hierarchy (H1, H2, H3, etc.) - List nesting - Code block languages - Link URLs and text - Emphasis and styling ### Not Preserved - Notion databases (converted as tables where possible) - Some advanced formatting (superscript, subscript) - Canvas blocks - Embedded web content (converted to links) ## Environment Setup ### Setting the API Key **Option 1: Using `.env` file (Recommended)** Create a `.env` file in the scripts directory: ```bash # scripts/.env NOTION_API_KEY=ntn_your_api_key_here ``` Then run the converter normally: ```bash node convert.js <page-id> > output.md ``` The script automatically loads environment variables from `.env` via the `dotenv` package. **Option 2: Export environment variable** Permanently set in your shell: ```bash # ~/.bashrc, ~/.zshrc, or ~/.config/fish/config.fish export NOTION_API_KEY="notioneq_..." ``` **Option 3: Set for a single command** ```bash NOTION_API_KEY=your_token node convert.js <page-id> ``` **Security Note:** Add `.env` to `.gitignore` to prevent accidentally committing your API key: ```bash echo ".env" >> .gitignore ``` ## Finding IDs ### Page ID from URL Notion URL format: ``` https://www.notion.so/Workspace-Name/Page-Title-abc123def456?v=xyz ↑ Page ID ``` Copy the ID part (without hyphens in the URL). ### Database ID Same as page URL - find the ID in the database's URL. ## Troubleshooting ### "NOTION_API_KEY is not set" Make sure the environment variable is exported: ```bash export NOTION_API_KEY="notioneq_..." echo $NOTION_API_KEY # Verify it's set ``` ### "Page not found or not accessible" - Verify the page ID is correct - Check that you've shared the page with your Notion integration - Ensure the integration has access to that workspace ### "Invalid page ID format" - Notion page IDs are 32-character alphanumeric strings - Remove hyphens from the URL - Example valid ID: [REDACTED_SECRET] ### Markdown output is incomplete - The API might have rate-limited your request - Try again after a moment - For bulk exports, add delays: `sleep 0.5` between conversions ## Advanced Usage ### Custom Output Processing Modify `scripts/convert.js` to process markdown before saving: ```javascript let markdown = result.markdown; // Add custom processing markdown = markdown.replace(/\n{3,}/g, '\n\n'); // Clean up spacing fs.writeFileSync('output.md', markdown); ``` ### Batch Processing Convert multiple pages in a loop: ```bash for pageId in page1 page2 page3; do node convert.js $pageId > "$pageId.md" done ``` ### Integration with Other Tools The markdown output is plain text and compatible with: - Static site generators (Hugo, Jekyll, Next.js) - Documentation platforms (Docusaurus, Doclify) - Version control (git, GitHub) - Publishing tools (WordPress, Medium) ## API Reference For advanced usage, see the [notion-to-md documentation](https://github.com/souvikinator/notion-to-md) and [Notion API reference](https://developers.notion.com/). ## Security Notes - Keep your `NOTION_API_KEY` secret - Don't commit API keys to version control - Use `.gitignore` for `.env` files - Rotate tokens if compromised - Share Notion pages with integration only as needed ## See Also - [Notion API Setup Guide](references/notion-api-setup.md) - Complete setup instructions - [notion-to-md GitHub](https://github.com/souvikinator/notion-to-md) - Source library - [Notion API Docs](https://developers.notion.com/) - Official API documentation

path: references/notion-api-setup.md
content: # Notion API Setup Guide

## Getting Your API Key

### Step 1: Create a Notion Integration

1. Go to [Notion Integrations](https://www.notion.so/my-integrations)
2. Click "Create new integration"
3. Enter a name (e.g., "Markdown Converter")
4. Select the workspace you want to use
5. Click "Submit"

### Step 2: Copy Your API Token

1. On the integration details page, find the "Secrets" section
2. Click "Show" next to the "Internal Integration Secret"
3. Copy the token (it starts with `notioneq_...`)
4. **Keep this token secret** - treat it like a password

### Step 3: Share Pages with Your Integration

Notion pages must be explicitly shared with your integration for it to access them:

1. Open the Notion page you want to convert
2. Click "Share" in the top right
3. Search for your integration name (e.g., "Markdown Converter")
4. Click to add it
5. Grant "Editor" or "Reader" access

For databases, share the database parent page with your integration.

### Step 4: Set the Environment Variable

Add your API key to your shell configuration:

```bash
export NOTION_API_KEY="notioneq_your_token_here"
```

Add to `~/.bashrc`, `~/.zshrc`, or equivalent.

## Finding Page IDs

### From URL

The page ID is in the URL:
```
https://www.notion.so/MyWorkspace/Page-Title-abc123def456?v=123abc
                                           ↑ Page ID (remove hyphens)
```

Copy `abc123def456` (the ID without hyphens).

### From Database

For database exports, use the database ID from its URL:
```
https://www.notion.so/MyWorkspace/Database-Name-abc123def456
                                         ↑ Database ID
```

## Permissions & Access Control

### What Your Integration Can Access

- ✅ Pages and databases explicitly shared with it
- ✅ All blocks and properties within shared pages
- ✅ Images and embeds (downloaded as URLs)
- ❌ Pages or databases NOT shared with the integration

### Required Permissions

Your integration needs:
- **Read** permission for basic conversion
- **Write** permission if you need to add comments or update content

## API Rate Limits

Notion API has rate limits:
- 3 requests per second (burst)
- Generous daily limits for most use cases

For large bulk exports, add small delays between requests:

```bash
# Small delay between conversions
sleep 0.5
```

## Troubleshooting

### "Invalid Notion API key"

- Check the token was copied completely
- Verify it starts with `notioneq_`
- Ensure the environment variable is set: `echo $NOTION_API_KEY`

### "Page not found"

- The page ID might be incorrect
- The integration hasn't been shared with the page
- Check the page is accessible in your Notion workspace

### "Validation error: Invalid page ID"

- Remove hyphens from the page ID
- Use only alphanumeric characters (no `-` in the ID)

## Security Best Practices

1. **Never commit API keys** to version control
2. **Use environment variables** instead
3. **Rotate tokens** if you suspect compromise
4. **Share pages minimally** - only with the integration
5. **Use read-only access** when you don't need write permission

## API Documentation

Full Notion API documentation: https://developers.notion.com/reference


path: scripts/convert.js
content: #!/usr/bin/env node

/**
 * Notion Page to Markdown Converter
 * Converts Notion pages to markdown using the Notion API and notion-to-md library
 *
 * Usage:
 *   node convert.js <pageId> [outputPath]
 *   node convert.js <pageId> --database [queryFilter]
 *
 * Environment:
 *   NOTION_API_KEY - Your Notion API token (required)
 *   .env file - Create a .env file with NOTION_API_KEY=your_token
 */

require("dotenv").config();

const { NotionToMarkdown } = require("notion-to-md");
const { Client } = require("@notionhq/client");
const fs = require("fs");
const path = require("path");

// Validate API key
const [REDACTED_SECRET];
if (!apiKey) {
  console.error(
    "❌ Error: NOTION_API_KEY environment variable is not set.\n" +
      "Please set your Notion API token:\n" +
      "  export NOTION_API_KEY=your_token_here\n" +
      "See README for how to get your API key."
  );
  process.exit(1);
}

// Initialize clients
const notion = new Client({ auth: apiKey });
const n2m = new NotionToMarkdown({ notionClient: notion });

async function convertPageToMarkdown(pageId) {
  try {
    // Fetch page metadata
    const page = await notion.pages.retrieve({ page_id: pageId });
    const pageTitle =
      page.properties.title?.title?.[0]?.plain_text ||
      page.properties.Name?.title?.[0]?.plain_text ||
      "Untitled";

    // Convert blocks to markdown
    const mdblocks = await n2m.pageToMarkdown(pageId);
    const mdResult = n2m.toMarkdownString(mdblocks);
    const mdString = typeof mdResult === 'string' ? mdResult : mdResult.parent || mdResult;

    return {
      title: pageTitle,
      markdown: mdString,
      pageId: pageId,
    };
  } catch (error) {
    if (error.code === "validation_error") {
      console.error("❌ Error: Invalid page ID format or page not found");
    } else if (error.status === 401) {
      console.error("❌ Error: Invalid Notion API key");
    } else if (error.status === 404) {
      console.error("❌ Error: Page not found or not accessible");
    } else {
      console.error("❌ Error converting page:", error.message);
    }
    process.exit(1);
  }
}

async function convertDatabaseToMarkdown(databaseId, outputDir = "./notion-exports") {
  try {
    // Ensure output directory exists
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir, { recursive: true });
    }

    // Query database
    const response = await notion.databases.query({ database_id: databaseId });
    const pages = response.results;

    console.log(`📚 Found ${pages.length} pages in database`);

    const results = [];

    for (const page of pages) {
      const pageId = page.id;
      const pageTitle =
        page.properties.title?.title?.[0]?.plain_text ||
        page.properties.Name?.title?.[0]?.plain_text ||
        `Untitled-${pageId.substring(0, 8)}`;

      try {
        const mdblocks = await n2m.pageToMarkdown(pageId);
        const mdResult = n2m.toMarkdownString(mdblocks);
        const mdString = typeof mdResult === 'string' ? mdResult : mdResult.parent || mdResult;

        // Write to file
        const safeFileName = pageTitle
          .replace(/[^\w\s-]/g, "")
          .replace(/\s+/g, "-")
          .toLowerCase();
        const filePath = path.join(outputDir, `${safeFileName}.md`);

        fs.writeFileSync(filePath, mdString);

        results.push({
          title: pageTitle,
          file: path.basename(filePath),
          status: "✅",
        });

        console.log(`✅ Converted: ${pageTitle}`);
      } catch (error) {
        results.push({
          title: pageTitle,
          status: "❌",
          error: error.message,
        });
        console.log(`❌ Failed: ${pageTitle} - ${error.message}`);
      }
    }

    return {
      outputDir,
      totalPages: pages.length,
      results,
    };
  } catch (error) {
    console.error("❌ Error querying database:", error.message);
    process.exit(1);
  }
}

async function main() {
  const args = process.argv.slice(2);

  if (args.length === 0) {
    console.log(
      "Usage: node convert.js <pageId|databaseId> [--database] [outputPath]\n"
    );
    console.log("Examples:");
    console.log("  node convert.js abc123def456 > page.md");
    console.log(
      "  node convert.js abc123def456 --database ./notion-export\n"
    );
    console.log("Environment:");
    console.log("  NOTION_API_KEY=your_token (required)");
    process.exit(0);
  }

  const id = args[0];
  const isDatabase = args.includes("--database");
  const outputPath = args[args.length - 1];

  if (isDatabase) {
    // Database export mode
    const result = await convertDatabaseToMarkdown(id, outputPath);
    console.log(`\n✨ Exported to: ${result.outputDir}`);
  } else {
    // Single page conversion mode
    const result = await convertPageToMarkdown(id);
    process.stdout.write(result.markdown);
  }
}

main().catch((error) => {
  console.error("Fatal error:", error);
  process.exit(1);
});


path: scripts/package-lock.json
content: {
  "name": "notion-to-md-converter",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "notion-to-md-converter",
      "version": "1.0.0",
      "license": "MIT",
      "dependencies": {
        "@notionhq/client": "^2.2.0",
        "notion-to-md": "^3.1.9"
      },
      "bin": {
        "notion-to-md": "convert.js"
      },
      "devDependencies": {}
    },
    "node_modules/@notionhq/client": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/@notionhq/client/-/client-2.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "@types/node-fetch": "^2.5.10",
        "node-fetch": "^2.6.1"
      },
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/@types/node": {
      "version": "25.3.0",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "undici-types": "~7.18.0"
      }
    },
    "node_modules/@types/node-fetch": {
      "version": "2.6.13",
      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "@types/node": "*",
        "form-data": "^4.0.4"
      }
    },
    "node_modules/asynckit": {
      "version": "0.4.0",
      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
      "integrity": [REDACTED_SECRET]
    },
    "node_modules/call-bind-apply-helpers": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "es-errors": "^1.3.0",
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/combined-stream": {
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "delayed-stream": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/delayed-stream": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">=0.4.0"
      }
    },
    "node_modules/dunder-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.1",
        "es-errors": "^1.3.0",
        "gopd": "^1.2.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-define-property": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-errors": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-object-atoms": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "es-errors": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-set-tostringtag": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.6",
        "has-tostringtag": "^1.0.2",
        "hasown": "^2.0.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/form-data": {
      "version": "4.0.5",
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "asynckit": "^0.4.0",
        "combined-stream": "^1.0.8",
        "es-set-tostringtag": "^2.1.0",
        "hasown": "^2.0.2",
        "mime-types": "^2.1.12"
      },
      "engines": {
        "node": ">= 6"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-intrinsic": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "es-define-property": "^1.0.1",
        "es-errors": "^1.3.0",
        "es-object-atoms": "^1.1.1",
        "function-bind": "^1.1.2",
        "get-proto": "^1.0.1",
        "gopd": "^1.2.0",
        "has-symbols": "^1.1.0",
        "hasown": "^2.0.2",
        "math-intrinsics": "^1.1.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "dunder-proto": "^1.0.1",
        "es-object-atoms": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/gopd": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-symbols": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-tostringtag": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "has-symbols": "^1.0.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/hasown": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/markdown-table": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "repeat-string": "^1.0.0"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/wooorm"
      }
    },
    "node_modules/math-intrinsics": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/mime-db": {
      "version": "1.52.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime-types": {
      "version": "2.1.35",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "mime-db": "1.52.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/node-fetch": {
      "version": "2.7.0",
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "whatwg-url": "^5.0.0"
      },
      "engines": {
        "node": "4.x || >=6.0.0"
      },
      "peerDependencies": {
        "encoding": "^0.1.0"
      },
      "peerDependenciesMeta": {
        "encoding": {
          "optional": true
        }
      }
    },
    "node_modules/notion-to-md": {
      "version": "3.1.9",
      "resolved": "https://registry.npmjs.org/notion-to-md/-/notion-to-md-3.1.9.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "markdown-table": "^2.0.0",
        "node-fetch": "2"
      },
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/repeat-string": {
      "version": "1.6.1",
      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": ">=0.10"
      }
    },
    "node_modules/tr46": {
      "version": "0.0.3",
      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
      "integrity": [REDACTED_SECRET]
    },
    "node_modules/undici-types": {
      "version": "7.18.2",
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
      "integrity": [REDACTED_SECRET]
    },
    "node_modules/webidl-conversions": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
      "integrity": [REDACTED_SECRET]
    },
    "node_modules/whatwg-url": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dependencies": {
        "tr46": "~0.0.3",
        "webidl-conversions": "^3.0.0"
      }
    }
  }
}


path: scripts/package.json
content: {
  "name": "notion-to-md-converter",
  "version": "1.0.0",
  "description": "Convert Notion pages to Markdown using the official Notion API",
  "main": "convert.js",
  "type": "commonjs",
  "bin": {
    "notion-to-md": "convert.js"
  },
  "dependencies": {
    "@notionhq/client": "^2.2.0",
    "dotenv": "^16.0.0",
    "notion-to-md": "^3.1.9"
  },
  "devDependencies": {},
  "scripts": {
    "start": "node convert.js"
  },
  "engines": {
    "node": ">=14.0.0"
  },
  "keywords": [
    "notion",
    "markdown",
    "converter",
    "api"
  ],
  "author": "",
  "license": "MIT"
}


Security scan verdicts — ClawScan: clean | static analysis:  | VirusTotal: clean | SkillSpector: clean (LOW)