Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

A TypeScript-first monorepo for working with Notion. Fork of React Notion X with added search API, backlink support, and extended property rendering. Uses the unofficial Notion API.

## Common Commands

```bash
pnpm i # Install dependencies
pnpm build # Build all packages (turbo + tsup)
pnpm dev # Watch mode development
pnpm test # Run all tests (vitest)
pnpm lint # Lint and fix TS/TSX files
pnpm format # Format with Prettier
pnpm clean # Clean build artifacts
```

### Running a Single Test

```bash
pnpm vitest run packages/nutils/src/parse-page-id.test.ts
```

### CLI Usage

```bash
pnpm tsx packages/cli/src/main.ts export -p <PAGE_ID> --raw -r -f
```

## Architecture

### Package Dependency Graph

```
ntypes (types) ─────────┬──────────────────────┐
│ │
▼ ▼
nutils (utilities) ncompat (compat layer)
┌─────────────┼─────────────┐
▼ ▼ ▼
nclient nreact cli
(API) (React) (exporter)
```
Comment on lines +37 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to fenced code block.

The architecture diagram code block lacks a language identifier. While this is an ASCII diagram, adding a language specifier (or text/plaintext) satisfies the markdown linting rule and improves consistency.

📝 Proposed fix
-```
+```text
 ntypes (types) ─────────┬──────────────────────┐
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 37-37: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@CLAUDE.md` around lines 37 - 47, The fenced code block containing the ASCII
architecture diagram (the block starting with "ntypes (types)
─────────┬──────────────────────┐") is missing a language specifier; update that
opening fence to include a language identifier such as "text" or "plaintext"
(e.g., change "```" to "```text") so the markdown linter passes and the diagram
is rendered consistently.


### Packages

| Package | Purpose | Build Target |
| ------------------ | --------------------------------------------- | -------------------- |
| `@texonom/ntypes` | Shared TypeScript type definitions | node14/ESM |
| `@texonom/nutils` | Isomorphic utility functions (Node & browser) | es2015/browser/ESM |
| `@texonom/nclient` | Unofficial Notion API client | node14/ESM |
| `@texonom/ncompat` | Bridge to official @notionhq/client | node14/ESM |
| `@texonom/nreact` | React renderer components | ESM (React 16+ peer) |
| `@texonom/cli` | CLI exporter using Clipanion | Node binary |

### Build Order (Turbo)

Turbo respects dependencies defined in `turbo.json`:

1. `ntypes` builds first (no dependencies)
2. `nutils`, `nclient`, `ncompat` build next (depend on ntypes)
3. `nreact` builds (depends on ntypes + nutils)
4. `cli` builds last (depends on nclient)

## Code Style

- ESM-only output (no CommonJS)
- Single quotes, no semicolons (Prettier)
- camelCase for variables, PascalCase for types
- Pre-commit hook runs `pnpm format && pnpm lint`

## Key Files

- `turbo.json` - Build task dependencies
- `tsconfig.base.json` - Shared TypeScript config
- Each package has `tsup.config.ts` for bundling

## Testing

Tests use Vitest. Test files are colocated with source:

- `packages/nutils/src/*.test.ts`
- `packages/nclient/src/notion-api.test.ts`
- `packages/cli/src/notion/export.test.ts`

Environment variable `NOTION_TOKEN` is needed for API tests.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"tsx": "^4.21.0",
"turbo": "^2.8.0",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vite": "^7.3.1",
"vite-plugin-dts": "^4.5.0",
Comment on lines +46 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Formatting inconsistency on line 46.

The vite entry on line 46 is missing leading indentation spaces, breaking the consistent JSON formatting. All other entries have proper indentation with 4 spaces.

🔧 Proposed fix
-"vite": "^7.3.1",
+    "vite": "^7.3.1",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"vite": "^7.3.1",
"vite-plugin-dts": "^4.5.0",
"vite": "^7.3.1",
"vite-plugin-dts": "^4.5.0",
🤖 Prompt for AI Agents
In `@package.json` around lines 46 - 47, The package.json has inconsistent
indentation for the "vite" dependency (the "vite" entry is missing the 4-space
leading indentation used by other entries); update the JSON so the "vite" line
uses the same 4-space indentation as surrounding dependency lines (ensure the
key "vite": "^7.3.1", matches the spacing style of "vite-plugin-dts" and other
entries) and validate the file remains valid JSON.

"vitest": "^4.0.18"
},
"standard-version": {
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
"notion": "./build/src/main.js"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"test": "vitest --run",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
Expand Down
14 changes: 0 additions & 14 deletions packages/cli/tsup.config.ts

This file was deleted.

30 changes: 30 additions & 0 deletions packages/cli/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' with { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/main.ts',
formats: ['es'],
fileName: () => 'main.js'
},
outDir: 'build/src',
target: 'node16',
sourcemap: true,
minify: true,
rollupOptions: {
external: [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
'fs',
'fs/promises',
'path',
'stream',
'util'
]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build/src' })]
})

4 changes: 2 additions & 2 deletions packages/nclient/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"node": ">=22.22.0"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"test": "vitest --run",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
Expand Down
14 changes: 0 additions & 14 deletions packages/nclient/tsup.config.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/nclient/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' with { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
4 changes: 2 additions & 2 deletions packages/ncompat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"node": ">=22.22.0"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
"pu": "pnpm publish"
Expand Down
13 changes: 0 additions & 13 deletions packages/ncompat/tsup.config.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/ncompat/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' with { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
4 changes: 2 additions & 2 deletions packages/nreact/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"node": ">=22.22.0"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
"pu": "pnpm publish"
Expand Down
3 changes: 1 addition & 2 deletions packages/nreact/src/components/search-dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React from 'react'
import { getBlockParentPage, getBlockTitle } from '@texonom/nutils'

import { NotionContextConsumer, NotionContextProvider } from '../context'
import { ClearIcon } from '../icons/clear-icon'
import { LoadingIcon } from '../icons/loading-icon'
import { SearchIcon } from '../icons/search-icon'
import { PageTitle } from './page-title'

import type { SearchParams, SearchResults, APIError } from '@texonom/ntypes'
import { getBlockTitle, getBlockParentPage } from '@texonom/nutils'
// TODO: modal.default.setAppElement('.notion-viewport')

// simple debounce utility so we only search after the user stops typing
Expand Down
2 changes: 0 additions & 2 deletions packages/nreact/src/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,9 @@ export const NotionContextProvider: React.FC<PartialNotionContext> = ({
if (components.nextLink) {
const nextLink = wrapNextLink(components.nextLink)
components.nextLink = nextLink

if (!components.PageLink) components.PageLink = nextLink
if (!components.Link) components.Link = nextLink
}

// ensure the user can't override default components with falsy values
// since it would result in very difficult-to-debug react errors
for (const key of Object.keys(components)) if (!components[key]) delete components[key]
Expand Down
34 changes: 0 additions & 34 deletions packages/nreact/tsup.config.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/nreact/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' with { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/index.tsx',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
8 changes: 6 additions & 2 deletions packages/ntypes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@
"build"
],
"scripts": {
"build": "tsc && tsup",
"build": "tsc && vite build",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
"pu": "pnpm publish"
"pu": "pnpm publish",
"watch": "vite build --watch --mode development"
},
"engines": {
"node": ">=22.22.0"
},
"devDependencies": {
"vite-plugin-dts": "^4.5.0"
},
"standard-version": {
"skip": {
"commit": true,
Expand Down
14 changes: 0 additions & 14 deletions packages/ntypes/tsup.config.ts

This file was deleted.

Loading
Loading