diff --git a/.env.sample b/.env.sample
new file mode 100644
index 0000000000..bce33191f8
--- /dev/null
+++ b/.env.sample
@@ -0,0 +1,2 @@
+export NX_SELF_HOSTED_REMOTE_CACHE_SERVER=https://cache.nickthesick.com
+export NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN=g8@ucL8em4*Z9TKXDY9OEX@!upf^Nz9
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index 1413ba09c4..0000000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,60 +0,0 @@
-const typeScriptExtensions = [".ts", ".cts", ".mts", ".tsx"];
-
-const allExtensions = [...typeScriptExtensions, ".js", ".jsx"];
-
-module.exports = {
- root: true,
- extends: [
- "eslint:recommended",
- "plugin:@typescript-eslint/recommended",
- "react-app",
- "react-app/jest",
- ],
- parser: "@typescript-eslint/parser",
- plugins: ["import", "@typescript-eslint"],
- settings: {
- "import/extensions": allExtensions,
- "import/external-module-folders": ["node_modules", "node_modules/@types"],
- "import/parsers": {
- "@typescript-eslint/parser": typeScriptExtensions,
- },
- "import/resolver": {
- node: {
- extensions: allExtensions,
- },
- },
- },
- ignorePatterns: ["**/ui/*"],
- rules: {
- "no-console": "error",
- curly: 1,
- "import/extensions": ["error", "always", { ignorePackages: true }],
- "import/no-extraneous-dependencies": [
- "error",
- {
- devDependencies: true,
- peerDependencies: true,
- optionalDependencies: false,
- bundledDependencies: false,
- },
- ],
- // would be nice to enable these rules later, but they are too noisy right now
- "@typescript-eslint/no-non-null-assertion": "off",
- "@typescript-eslint/no-explicit-any": "off",
- "@typescript-eslint/ban-ts-comment": "off",
- "import/no-cycle": "error",
- // doesn't work:
- // "import/no-restricted-paths": [
- // "error",
- // {
- // zones: [
- // {
- // target: "./src/**/*",
- // from: "./types/**/*",
- // message: "Import from this module to types is not allowed.",
- // },
- // ],
- // },
- // ],
- },
-};
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000000..e9511bbf61
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,42 @@
+{
+ "root": true,
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "react-app",
+ "react-app/jest"
+ ],
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["import", "@typescript-eslint"],
+ "settings": {
+ "import/extensions": [".ts", ".cts", ".mts", ".tsx", ".js", ".jsx"],
+ "import/external-module-folders": ["node_modules", "node_modules/@types"],
+ "import/parsers": {
+ "@typescript-eslint/parser": [".ts", ".cts", ".mts", ".tsx"]
+ },
+ "import/resolver": {
+ "node": {
+ "extensions": [".ts", ".cts", ".mts", ".tsx", ".js", ".jsx"]
+ }
+ }
+ },
+ "ignorePatterns": ["**/ui/*"],
+ "rules": {
+ "no-console": "error",
+ "curly": 1,
+ "import/extensions": ["error", "always", { "ignorePackages": true }],
+ "import/no-extraneous-dependencies": [
+ "error",
+ {
+ "devDependencies": true,
+ "peerDependencies": true,
+ "optionalDependencies": false,
+ "bundledDependencies": false
+ }
+ ],
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/ban-ts-comment": "off",
+ "import/no-cycle": "error"
+ }
+}
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index fec535d794..0000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: bug
-assignees: ''
-
----
-
-**Describe the bug**
-
-
-**To Reproduce**
-
-
-**Misc**
-- Node version:
-- Package manager:
-- Browser:
-- [ ] I'm a [sponsor](https://github.com/sponsors/YousefED) and would appreciate if you could look into this sooner than later 💖
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000000..372e429b34
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,101 @@
+name: Bug report
+description: Report a bug or broken behavior in BlockNote
+labels:
+ - bug
+ - needs-triage
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for reporting a bug!
+ Please use this template to describe **broken or incorrect behavior**.
+
+ Feature ideas or questions should go to **Discussions**.
+
+ - type: textarea
+ id: problem
+ attributes:
+ label: What’s broken?
+ description: >
+ Describe the problem clearly and concisely.
+ What is happening that should not be happening?
+ placeholder: >
+ Example:
+ When editing a table cell and pressing Enter, the editor crashes and the document cannot be recovered.
+ validations:
+ required: true
+
+ - type: textarea
+ id: expected
+ attributes:
+ label: What did you expect to happen?
+ description: >
+ Describe the expected or correct behavior.
+ validations:
+ required: true
+
+ - type: textarea
+ id: steps
+ attributes:
+ label: Steps to reproduce
+ description: >
+ Provide clear steps so we can reproduce the issue.
+ If possible, an online reproduction (e.g. StackBlitz) is extremely helpful.
+ placeholder: |
+ 1. Create a new document
+ 2. Insert a table
+ 3. Click inside a cell
+ 4. Press Enter
+
+ Optional: If you can, provide a minimal online reproduction.
+ You can use this starter sandbox:
+ https://stackblitz.com/github/TypeCellOS/BlockNote/tree/main/examples/01-basic/01-minimal?file=App.tsx
+ validations:
+ required: false
+
+ - type: input
+ id: version
+ attributes:
+ label: BlockNote version
+ description: >
+ Optional — specify the version you’re using, if known.
+ placeholder: e.g. v0.18.2
+ validations:
+ required: false
+
+ - type: input
+ id: environment
+ attributes:
+ label: Environment
+ description: >
+ Browser, OS, framework, or other relevant environment details.
+ placeholder: e.g. Chrome 121, macOS 14, React 18
+ validations:
+ required: false
+
+ - type: textarea
+ id: additional
+ attributes:
+ label: Additional context
+ description: >
+ Screenshots, videos, logs, or any other context that might help.
+ validations:
+ required: false
+
+ - type: checkboxes
+ id: contribute
+ attributes:
+ label: Contribution
+ options:
+ - label: "I'd be interested in contributing a fix for this issue"
+ required: false
+
+ - type: checkboxes
+ id: sponsor
+ attributes:
+ label: Sponsor
+ description: >
+ Optional — helps us prioritize first response according to our SLA.
+ options:
+ - label: "I'm a [sponsor](https://www.blocknotejs.org/pricing) and would appreciate if you could look into this sooner than later 💖"
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..f258f05126
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,6 @@
+blank_issues_enabled: false
+
+contact_links:
+ - name: Share an idea or suggest an enhancement
+ url: https://github.com/TypeCellOS/BlockNote/discussions/categories/ideas-enhancements
+ about: Share feature ideas, enhancement suggestions, or other ideas for the BlockNote project.
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index a76f4cd708..0000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: enhancement
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
-
-**Bonus**
-[ ] I'm a [sponsor](https://github.com/sponsors/YousefED) and would appreciate if you could look into this sooner than later 💖
diff --git a/.github/ISSUE_TEMPLATE/share_block.yml b/.github/ISSUE_TEMPLATE/share_block.yml
deleted file mode 100644
index 889bb404be..0000000000
--- a/.github/ISSUE_TEMPLATE/share_block.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-name: "Submit a Custom Block"
-description: "Use this template to submit a new custom block (schema) for BlockNote."
-title: ""
-body:
- - type: markdown
- attributes:
- value: |
- ## Submit a Custom Block (Schema)
-
- Thank you for contributing to BlockNote! Please fill out the following sections to submit your custom block. Make sure to provide as much detail as possible to help us understand and showcase your block effectively.
-
- - type: input
- id: block_name
- attributes:
- label: "Block Name"
- description: "Enter the name of your custom block."
- placeholder: "e.g., Alert Block"
-
- - type: textarea
- id: block_description
- attributes:
- label: "Block Description"
- description: "Provide a detailed description of your custom block. Explain its purpose and how it works."
- placeholder: "This block is used to display alert messages with different severity levels."
-
- - type: textarea
- id: block_dependencies
- attributes:
- label: "Dependencies"
- description: "Provide a full list of all the dependencies needed to make your custom block work."
- placeholder: "`npm_package_1`, `npm_package_2`, ...etc "
-
- - type: input
- id: live_example
- attributes:
- label: "Live Example"
- description: "Please provide a valid URL to a codepen, stackblitz, codeSandbox, or simply a github repo"
- placeholder: "live example URL here"
-
- - type: textarea
- id: usage_instructions
- attributes:
- label: "Usage Instructions"
- description: "Explain how to use your custom block in a BlockNote application. Include any necessary setup steps."
- placeholder: |
- ```markdown
- 1. Import your custom block.
- 2. Add it to the BlockNote editor configuration.
- 3. Use it within the BlockNote editor.
- ```
-
- - type: textarea
- id: additional_notes
- attributes:
- label: "Additional Notes"
- description: "Include any additional information or notes about your custom block."
- placeholder: "Any additional context or information."
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..165dad4e01
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,57 @@
+version: 2
+updates:
+ - package-ecosystem: "npm"
+ versioning-strategy: "lockfile-only"
+ directories:
+ - "/"
+ - "/packages/*"
+ schedule:
+ interval: "weekly"
+ labels:
+ - "npm dependencies"
+ commit-message:
+ prefix: "chore"
+ allow:
+ # @tiptap packages
+ - dependency-name: "@tiptap/core"
+ - dependency-name: "@tiptap/pm"
+ - dependency-name: "@tiptap/react"
+ - dependency-name: "@tiptap/extensions"
+ - dependency-name: "@tiptap/extension-bold"
+ - dependency-name: "@tiptap/extension-code"
+ - dependency-name: "@tiptap/extension-horizontal-rule"
+ - dependency-name: "@tiptap/extension-italic"
+
+ - dependency-name: "@tiptap/extension-paragraph"
+ - dependency-name: "@tiptap/extension-strike"
+ - dependency-name: "@tiptap/extension-text"
+ - dependency-name: "@tiptap/extension-underline"
+ # prosemirror packages
+ - dependency-name: "prosemirror-changeset"
+ - dependency-name: "prosemirror-highlight"
+ - dependency-name: "prosemirror-model"
+ - dependency-name: "prosemirror-state"
+ - dependency-name: "prosemirror-tables"
+ - dependency-name: "prosemirror-transform"
+ - dependency-name: "prosemirror-view"
+ # react packages
+ - dependency-name: "react"
+ - dependency-name: "react-dom"
+ # yjs packages
+ - dependency-name: "yjs"
+ - dependency-name: "y-prosemirror"
+ ignore:
+ # Hono packages are used only in the demo AI server and are not part of
+ # the main editor/runtime surface area.
+ - dependency-name: "hono"
+ - dependency-name: "@hono/node-server"
+ - dependency-name: "@hono/*"
+ groups:
+ editor-dependencies:
+ patterns:
+ - "@tiptap/*"
+ - "prosemirror-*"
+ - "react"
+ - "react-dom"
+ - "yjs"
+ - "y-prosemirror"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..9870532e04
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,34 @@
+# Summary
+
+
+
+## Rationale
+
+
+
+## Changes
+
+
+
+## Impact
+
+
+
+## Testing
+
+
+
+## Screenshots/Video
+
+
+
+## Checklist
+
+- [ ] Code follows the project's coding standards.
+- [ ] Unit tests covering the new feature have been added.
+- [ ] All existing tests pass.
+- [ ] The documentation has been updated to reflect the new feature
+
+## Additional Notes
+
+
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e52aa26925..91b5ca0414 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -7,7 +7,10 @@ on:
types: [opened, synchronize, reopened, edited]
env:
- NX_REJECT_UNKNOWN_LOCAL_CACHE: 0
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
+ NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN }}
+ NX_SELF_HOSTED_REMOTE_CACHE_SERVER: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_SERVER }}
+ pnpm_config_store_dir: ./node_modules/.pnpm-store
jobs:
build:
@@ -15,23 +18,23 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
fetch-depth: 100
- name: Install pnpm
- uses: pnpm/action-setup@v4
+ uses: pnpm/action-setup@v5
- - uses: nrwl/nx-set-shas@v3
+ - uses: nrwl/nx-set-shas@v5
- - uses: actions/setup-node@v4
+ - uses: actions/setup-node@v6
with:
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
node-version-file: ".nvmrc"
- name: Cache NX
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: .nx/cache
key: nx-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-${{ github.sha }}
@@ -40,8 +43,6 @@ jobs:
nx-${{ env.NX_BRANCH }}-
nx-
- # This is needed for the canvas dep, Tiptap V3 should remove the need for this
- - run: sudo apt-get update && sudo apt-get install -y build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev pkg-config
- name: Install Dependencies
run: pnpm install
@@ -54,6 +55,9 @@ jobs:
- name: Run unit tests
run: pnpm run test
+ - name: Run Next.js integration test (production build)
+ run: NEXTJS_TEST_MODE=build npx vitest run tests/src/unit/nextjs/serverUtil.test.ts
+
- name: Upload webpack stats artifact (editor)
uses: relative-ci/agent-upload-artifact-action@v2
with:
@@ -62,59 +66,142 @@ jobs:
- name: Soft release
id: soft-release
- run: pnpx pkg-pr-new publish './packages/*' # --compact enable compact after release
+ run: pnpx pkg-pr-new publish './packages/*' # TODO disabled only for AI branch--compact
- playwright:
- name: "Playwright Tests - ${{ matrix.browser }}"
+ playwright-build:
+ name: "Playwright Build"
runs-on: ubuntu-latest
- timeout-minutes: 60
- container:
- image: mcr.microsoft.com/playwright:v1.51.1-noble
- strategy:
- fail-fast: false
- matrix:
- browser: [chromium, firefox, webkit]
+ timeout-minutes: 30
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
fetch-depth: 100
- name: Install pnpm
- uses: pnpm/action-setup@v4
+ uses: pnpm/action-setup@v5
- - uses: nrwl/nx-set-shas@v3
+ - uses: nrwl/nx-set-shas@v5
- - uses: actions/setup-node@v4
+ - uses: actions/setup-node@v6
with:
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
node-version-file: ".nvmrc"
- name: Cache NX
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: .nx/cache
- key: nx-${{ matrix.browser }}-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-${{ github.sha }}
+ key: nx-playwright-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-${{ github.sha }}
restore-keys: |
- nx-${{ matrix.browser }}-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-
- nx-${{ matrix.browser }}-${{ env.NX_BRANCH }}-
+ nx-playwright-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-
+ nx-playwright-${{ env.NX_BRANCH }}-
nx-
- - run: apt-get update && apt-get install -y build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev pkg-config
-
- name: Install dependencies
run: pnpm install
- name: Build packages
run: pnpm run build
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v7
+ with:
+ name: playwright-build
+ path: |
+ packages/*/dist
+ playground/dist
+ retention-days: 1
+
+ playwright:
+ name: "Playwright Tests - ${{ matrix.browser }} (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})"
+ runs-on: ubuntu-latest
+ needs: playwright-build
+ timeout-minutes: 30
+ container:
+ image: mcr.microsoft.com/playwright:v1.51.1-noble
+ strategy:
+ fail-fast: false
+ matrix:
+ browser: [chromium, firefox, webkit]
+ shardIndex: [1, 2]
+ shardTotal: [2]
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 100
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v5
+
+ - uses: actions/setup-node@v6
+ with:
+ cache: "pnpm"
+ cache-dependency-path: "**/pnpm-lock.yaml"
+ node-version-file: ".nvmrc"
+
+ - name: Download build artifacts
+ uses: actions/download-artifact@v8
+ with:
+ name: playwright-build
+
+ - name: Install dependencies
+ run: pnpm install
+
- name: Run server and Playwright tests
run: |
- HOME=/root PLAYWRIGHT_CONFIG="--project ${{ matrix.browser }}" pnpm run e2e
+ HOME=/root PLAYWRIGHT_CONFIG="--project ${{ matrix.browser }} --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}" pnpm run e2e
+
+ - name: Upload blob report
+ uses: actions/upload-artifact@v7
+ if: ${{ !cancelled() }}
+ with:
+ name: blob-report-${{ matrix.browser }}-${{ matrix.shardIndex }}
+ path: tests/blob-report/
+ retention-days: 1
+
+ - name: Upload HTML report
+ uses: actions/upload-artifact@v7
+ if: ${{ !cancelled() }}
+ with:
+ name: playwright-report-${{ matrix.browser }}-${{ matrix.shardIndex }}
+ path: tests/playwright-report/
+ retention-days: 30
+
+ merge-reports:
+ name: "Merge Playwright Reports"
+ if: ${{ !cancelled() }}
+ needs: playwright
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v5
+
+ - uses: actions/setup-node@v6
+ with:
+ cache: "pnpm"
+ cache-dependency-path: "**/pnpm-lock.yaml"
+ node-version-file: ".nvmrc"
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Download blob reports
+ uses: actions/download-artifact@v8
+ with:
+ path: tests/all-blob-reports
+ pattern: blob-report-*
+ merge-multiple: true
+
+ - name: Merge reports
+ run: npx playwright merge-reports --reporter html ./all-blob-reports
+ working-directory: tests
- - uses: actions/upload-artifact@v4
- if: always()
+ - name: Upload merged HTML report
+ uses: actions/upload-artifact@v7
with:
- name: playwright-report-${{ matrix.browser }}
+ name: playwright-report-merged
path: tests/playwright-report/
retention-days: 30
diff --git a/.github/workflows/fresh-install-tests.yml b/.github/workflows/fresh-install-tests.yml
new file mode 100644
index 0000000000..6d6ed4a452
--- /dev/null
+++ b/.github/workflows/fresh-install-tests.yml
@@ -0,0 +1,144 @@
+name: Fresh Install Tests
+
+# Periodically tests BlockNote with the latest versions of its production
+# dependencies (within declared semver ranges). This catches breakage when a
+# new release of a dep like @tiptap/* or prosemirror-* ships and conflicts
+# with BlockNote's declared ranges — the kind of failure a user would hit when
+# running `npm install @blocknote/react` in a fresh project.
+#
+# Only production dependencies of published (non-private) packages are updated.
+# DevDependencies (vitest, vite, typescript, etc.) stay pinned to the lockfile,
+# so test tooling churn doesn't cause false positives.
+
+on:
+ schedule:
+ - cron: "0 2 * * *" # Daily at 02:00 UTC
+ workflow_dispatch: # Allow manual runs
+
+env:
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
+ pnpm_config_store_dir: ./node_modules/.pnpm-store
+
+jobs:
+ fresh-install-unit-tests:
+ name: Unit Tests (Fresh Dep Resolution)
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+
+ steps:
+ - id: checkout
+ uses: actions/checkout@v6
+
+ - id: install_pnpm
+ name: Install pnpm
+ uses: pnpm/action-setup@v5
+
+ - id: setup_node
+ uses: actions/setup-node@v6
+ with:
+ node-version-file: ".nvmrc"
+ # Intentionally no pnpm cache — we want fresh prod dep resolution
+
+ - id: install_dependencies
+ name: Install dependencies
+ run: pnpm install
+
+ - id: update_prod_deps
+ name: Update prod deps of published packages
+ # Resolves production dependencies of every published (non-private)
+ # workspace package to the latest version within their declared semver
+ # ranges. This simulates what a user gets when running
+ # `npm install @blocknote/react` in a fresh project.
+ # DevDependencies are left at their lockfile versions.
+ run: |
+ FILTERS=$(node -e "
+ const fs = require('fs');
+ const path = require('path');
+ fs.readdirSync('packages').forEach(dir => {
+ try {
+ const pkg = JSON.parse(fs.readFileSync(path.join('packages', dir, 'package.json'), 'utf8'));
+ if (!pkg.private && pkg.name) process.stdout.write('--filter ' + pkg.name + ' ');
+ } catch {}
+ });
+ ")
+ echo "Updating prod deps for: $FILTERS"
+ eval pnpm update --prod $FILTERS
+
+ - id: dedupe_deps
+ name: Dedupe transitive dependencies
+ # After bumping the publishable packages' prod deps, collapse any
+ # duplicate transitive resolutions (e.g. @tiptap/core + @tiptap/pm)
+ # that would otherwise differ between the updated publishable packages
+ # and the un-updated examples/playground. Without this, TypeScript
+ # treats the two copies' exports as unrelated types and example-editor
+ # fails to build (TS2322 on Extension vs AnyExtension).
+ # Dedupe only rewrites the lockfile — it does NOT modify package.json,
+ # so the examples' "@blocknote/*": "latest" specs (which is what
+ # CodeSandbox users see) stay intact.
+ run: pnpm dedupe
+
+ - id: build_packages
+ name: Build packages
+ run: pnpm run build
+ env:
+ NX_SKIP_NX_CACHE: "true"
+
+ - id: run_unit_tests
+ name: Run unit tests
+ run: pnpm run test
+ env:
+ NX_SKIP_NX_CACHE: "true"
+
+ - name: Notify Slack on workflow failure
+ if: ${{ failure() }}
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ REPOSITORY: ${{ github.repository }}
+ WORKFLOW: ${{ github.workflow }}
+ RUN_ID: ${{ github.run_id }}
+ RUN_NUMBER: ${{ github.run_number }}
+ RUN_ATTEMPT: ${{ github.run_attempt }}
+ BRANCH: ${{ github.ref_name }}
+ run: |
+ if [ -z "$SLACK_WEBHOOK_URL" ]; then
+ echo "SLACK_WEBHOOK_URL is not configured; skipping Slack notification."
+ exit 0
+ fi
+
+ failed_step="Unknown step"
+ if [ "${{ steps.checkout.outcome }}" = "failure" ]; then
+ failed_step="Checkout repository"
+ elif [ "${{ steps.install_pnpm.outcome }}" = "failure" ]; then
+ failed_step="Install pnpm"
+ elif [ "${{ steps.setup_node.outcome }}" = "failure" ]; then
+ failed_step="Setup Node.js"
+ elif [ "${{ steps.install_dependencies.outcome }}" = "failure" ]; then
+ failed_step="Install dependencies"
+ elif [ "${{ steps.update_prod_deps.outcome }}" = "failure" ]; then
+ failed_step="Update prod deps of published packages"
+ elif [ "${{ steps.dedupe_deps.outcome }}" = "failure" ]; then
+ failed_step="Dedupe transitive dependencies"
+ elif [ "${{ steps.build_packages.outcome }}" = "failure" ]; then
+ failed_step="Build packages"
+ elif [ "${{ steps.run_unit_tests.outcome }}" = "failure" ]; then
+ failed_step="Run unit tests"
+ fi
+
+ run_url="https://github.com/${REPOSITORY}/actions/runs/${RUN_ID}"
+ message=$(printf '%s\n%s\n%s\n%s' \
+ ":warning: Fresh Install Tests failed in *${REPOSITORY}* on branch *${BRANCH}*." \
+ "*Workflow:* ${WORKFLOW}" \
+ "*Run:* <${run_url}|#${RUN_NUMBER} (attempt ${RUN_ATTEMPT})>" \
+ "*Failed step:* ${failed_step}")
+ payload=$(jq --compact-output --null-input --arg text "$message" '{text: $text}')
+
+ curl -sS -X POST \
+ --fail \
+ --retry 4 \
+ --retry-all-errors \
+ --retry-max-time 60 \
+ --connect-timeout 10 \
+ --max-time 30 \
+ -H "Content-type: application/json" \
+ --data "$payload" \
+ "$SLACK_WEBHOOK_URL"
diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml
index b6f1bacef0..280d5a5af1 100644
--- a/.github/workflows/publish.yaml
+++ b/.github/workflows/publish.yaml
@@ -5,9 +5,19 @@ on:
push:
tags:
- v*.*.*
+ - v*.*.*-*
+ workflow_dispatch:
+ inputs:
+ version:
+ description: "Version tag to publish (e.g., v0.x.x-hotfix)"
+ required: true
+ type: string
env:
- NX_REJECT_UNKNOWN_LOCAL_CACHE: 0
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
+ NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN }}
+ NX_SELF_HOSTED_REMOTE_CACHE_SERVER: ${{ secrets.NX_SELF_HOSTED_REMOTE_CACHE_SERVER }}
+ pnpm_config_store_dir: ./node_modules/.pnpm-store
jobs:
publish:
@@ -19,27 +29,32 @@ jobs:
attestations: write
timeout-minutes: 10
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
+ ref: ${{ inputs.version }}
fetch-depth: 100
+ - name: Display version being published
+ run: |
+ echo "Publishing version: ${{ inputs.version }}"
+
- run: jq '.packageManager' package.json | tr -d '"pnpm@'
id: package-manager-version
- name: Install pnpm
- uses: pnpm/action-setup@v4
+ uses: pnpm/action-setup@v5
with:
version: ${{ steps.package-manager-version.outputs.stdout }}
- - uses: nrwl/nx-set-shas@v3
+ - uses: nrwl/nx-set-shas@v5
- - uses: actions/setup-node@v4
+ - uses: actions/setup-node@v6
with:
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
node-version-file: ".nvmrc"
- name: Cache NX
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: .nx/cache
key: nx-${{ env.NX_BRANCH }}-${{ env.NX_RUN_GROUP }}-${{ github.sha }}
@@ -48,8 +63,6 @@ jobs:
nx-${{ env.NX_BRANCH }}-
nx-
- - run: sudo apt-get update && sudo apt-get install -y build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev pkg-config
-
- name: Install Dependencies & Build
run: pnpm install && pnpm build
@@ -57,8 +70,5 @@ jobs:
run: pnpm exec nx report
- name: Publish packages
- run: pnpm exec nx release publish
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
- NPM_CONFIG_PROVENANCE: true
- GITHUB_TOKEN: "${{ github.token }}"
+ # Ensure npm 11.5.1 or later for trusted publishing
+ run: npm install -g npm@latest && pnpm exec nx release publish --access public
diff --git a/.gitignore b/.gitignore
index a705a35f8b..898dcdcc62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,8 +29,15 @@ yarn-error.log*
.vercel
test-results/
playwright-report/
+blob-report/
release
/test-results/
/playwright-report/
+/blob-report/
/playwright/.cache/
-.nx/
\ No newline at end of file
+.env
+*.pem
+.nx/
+# Nightshift plan artifacts (keep out of version control)
+.nightshift-plan
+.claude
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000000..0f4e5b7d67
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,12 @@
+{
+ "$schema": "http://json.schemastore.org/prettierrc",
+ "semi": true,
+ "singleQuote": false,
+ "tabWidth": 2,
+ "printWidth": 80,
+ "trailingComma": "all",
+ "bracketSpacing": true,
+ "arrowParens": "always",
+ "endOfLine": "lf",
+ "plugins": ["prettier-plugin-tailwindcss"]
+}
diff --git a/.resources/release-workflow.excalidraw.svg b/.resources/release-workflow.excalidraw.svg
new file mode 100644
index 0000000000..635f94e031
--- /dev/null
+++ b/.resources/release-workflow.excalidraw.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8786fe0f0e..7c24081186 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -13,5 +13,13 @@
"typescript.tsdk": "node_modules/typescript/lib",
"[xml]": {
"editor.defaultFormatter": "redhat.vscode-xml"
+ },
+ "scm.defaultViewMode": "tree",
+ "search.defaultViewMode": "tree",
+ "[typescript]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[mdx]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0f1d15a56..112608f8ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,837 @@
+## 0.51.0 (2026-05-14)
+
+### 🚀 Features
+
+- Trailing block extension rewrite ([#2733](https://github.com/TypeCellOS/BlockNote/pull/2733))
+- **markdown:** replace unified.js with custom markdown parser/serializer ([#2624](https://github.com/TypeCellOS/BlockNote/pull/2624))
+- **react:** configurable portal targets for floating UI ([#2729](https://github.com/TypeCellOS/BlockNote/pull/2729), [#2692](https://github.com/TypeCellOS/BlockNote/issues/2692))
+
+### 🩹 Fixes
+
+- Pasting plain text from VSCode (BLO-366) ([#2713](https://github.com/TypeCellOS/BlockNote/pull/2713))
+- Parse new lines in `text/plain` as line breaks (BLO-1170) ([#2712](https://github.com/TypeCellOS/BlockNote/pull/2712))
+- Code block PDF export (BLO-987) ([#2725](https://github.com/TypeCellOS/BlockNote/pull/2725))
+- Formatting toolbar opening when inserting file block with `trailingBlock: false` (BLO-860) ([#2704](https://github.com/TypeCellOS/BlockNote/pull/2704))
+- numbered list item decorations missed on initial render ([#2734](https://github.com/TypeCellOS/BlockNote/pull/2734))
+- flicker-free mobile formatting toolbar via CSS custom properties ([#2617](https://github.com/TypeCellOS/BlockNote/pull/2617), [#2616](https://github.com/TypeCellOS/BlockNote/issues/2616))
+- add `bn-thread-orphaned` CSS class to distinguish orphaned threads ([#2737](https://github.com/TypeCellOS/BlockNote/pull/2737), [#2735](https://github.com/TypeCellOS/BlockNote/issues/2735))
+- set width attribute on image and video elements in editor render ([#2740](https://github.com/TypeCellOS/BlockNote/pull/2740), [#2726](https://github.com/TypeCellOS/BlockNote/issues/2726))
+- **a11y:** use figure/figcaption for media block captions ([#2717](https://github.com/TypeCellOS/BlockNote/pull/2717))
+- **ai:** loosen serialization of blocks in columns ([#2716](https://github.com/TypeCellOS/BlockNote/pull/2716), [#2718](https://github.com/TypeCellOS/BlockNote/pull/2718))
+- **core:** trigger codeblock input rule on Enter and place cursor inside ([#2686](https://github.com/TypeCellOS/BlockNote/pull/2686))
+- **core:** preserve list item type when pasting into empty list items ([#2722](https://github.com/TypeCellOS/BlockNote/pull/2722), [#2330](https://github.com/TypeCellOS/BlockNote/issues/2330))
+- **core:** unmount editors in transformPasted tests to prevent unhandled error ([e62880b21](https://github.com/TypeCellOS/BlockNote/commit/e62880b21))
+- **drag-n-drop:** support PDF block drag & drop (BLO-893) ([#2714](https://github.com/TypeCellOS/BlockNote/pull/2714))
+- **i18:** improve french translation for empty toggle list ([#2721](https://github.com/TypeCellOS/BlockNote/pull/2721))
+- **markdown:** emit tight lists when serializing blocks to markdown ([#2715](https://github.com/TypeCellOS/BlockNote/pull/2715))
+- **markdown:** skip placeholder text for empty files ([#434](https://github.com/TypeCellOS/BlockNote/pull/434), [#2719](https://github.com/TypeCellOS/BlockNote/pull/2719))
+- **markdown:** stable round-trip for tables, captions, and audio ([#2720](https://github.com/TypeCellOS/BlockNote/pull/2720))
+- **tests:** stabilize webkit keyboard handler tests with programmatic cursor positioning ([#2746](https://github.com/TypeCellOS/BlockNote/pull/2746))
+
+### ❤️ Thank You
+
+- Cyril G
+- Manuel Raynaud @lunika
+- Matthew Lipski @matthewlipski
+- Movm
+- Nick Perez
+- Nick the Sick @nperez0111
+
+## 0.50.0 (2026-05-04)
+
+### 🚀 Features
+
+- Dark mode styling for file block wrapper component (BLO-866) ([#2680](https://github.com/TypeCellOS/BlockNote/pull/2680))
+- Drag hendle menu delete button removes all other blocks in selection (BLO-1007) ([#2683](https://github.com/TypeCellOS/BlockNote/pull/2683))
+- Enter moves selection to cell below in tables (BLO-1006) ([#2685](https://github.com/TypeCellOS/BlockNote/pull/2685))
+- additional heading top padding (BLO-1008) ([#2690](https://github.com/TypeCellOS/BlockNote/pull/2690))
+- Code mark input rule edge case (BLO-938) ([#2698](https://github.com/TypeCellOS/BlockNote/pull/2698))
+- **mantine:** upgrade @mantine/core and @mantine/hooks to v9.0.2 ([#2655](https://github.com/TypeCellOS/BlockNote/pull/2655))
+
+### 🩹 Fixes
+
+- Hardcoded strings in comment components (BLO-1033) ([#2681](https://github.com/TypeCellOS/BlockNote/pull/2681))
+- Color naming & CSS (BLO-946) ([#2684](https://github.com/TypeCellOS/BlockNote/pull/2684))
+- link HTML attributes (BLO-915) ([#2687](https://github.com/TypeCellOS/BlockNote/pull/2687))
+- guard hideMenuIfNotFrozen against undefined view state ([#2694](https://github.com/TypeCellOS/BlockNote/pull/2694), [#2699](https://github.com/TypeCellOS/BlockNote/pull/2699))
+- Clicking comment overlapping link opens link (BLO-1091) ([#2696](https://github.com/TypeCellOS/BlockNote/pull/2696))
+- prevent table row drag from moving an extra adjacent row ([#2703](https://github.com/TypeCellOS/BlockNote/pull/2703))
+- **clipboard:** use ProseMirror selection state for Shadow DOM compatibility ([#2677](https://github.com/TypeCellOS/BlockNote/pull/2677))
+
+### ❤️ Thank You
+
+- jt_fox @LimChaeJune
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Wieland Lindenthal
+- Yousef
+
+## 0.49.0 (2026-04-24)
+
+### 🚀 Features
+
+- simplify links by inlining it to BlockNote ([#2623](https://github.com/TypeCellOS/BlockNote/pull/2623))
+- add Unicode quotation mark input rule for quote blocks ([#2673](https://github.com/TypeCellOS/BlockNote/pull/2673))
+
+### 🩹 Fixes
+
+- Inserting link removes comment & add comment button click buggy ([#2620](https://github.com/TypeCellOS/BlockNote/pull/2620), [#2573](https://github.com/TypeCellOS/BlockNote/issues/2573))
+- `useEditorDOMElement` hook ([#2619](https://github.com/TypeCellOS/BlockNote/pull/2619))
+- text color was not applying to table block ([#2663](https://github.com/TypeCellOS/BlockNote/pull/2663))
+- Drag preview blocking drops when overlapping the editor (BLO-996) ([#2670](https://github.com/TypeCellOS/BlockNote/pull/2670))
+- Drag & drop of blocks without inline content opens formatting toolbar (BLO-1116) ([#2628](https://github.com/TypeCellOS/BlockNote/pull/2628), [#2603](https://github.com/TypeCellOS/BlockNote/issues/2603))
+- save file caption/name on every keystroke instead of on close ([#2575](https://github.com/TypeCellOS/BlockNote/pull/2575))
+- prevent FloatingFocusManager from resetting editor selection ([#2525](https://github.com/TypeCellOS/BlockNote/pull/2525), [#2664](https://github.com/TypeCellOS/BlockNote/pull/2664))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- miadnguyen @miadnguyen
+- mianguyen
+- Nick Perez
+- Yousef
+
+## 0.48.1 (2026-04-16)
+
+### 🩹 Fixes
+
+- make CustomChange compatible with prosemirror-changeset 2.4.1 ([#2647](https://github.com/TypeCellOS/BlockNote/pull/2647))
+- **deps:** upgrade nx to 22.6.5 to resolve axios security vulnerability (CVE-2025-62718) ([c1ef3018a](https://github.com/TypeCellOS/BlockNote/commit/c1ef3018a))
+- **deps:** upgrade nx to 22.6.5 to resolve axios security vulnerability ([#2653](https://github.com/TypeCellOS/BlockNote/pull/2653))
+- **docx-exporter:** omit w:lang when no locale provided instead of defaulting to en-US ([#2651](https://github.com/TypeCellOS/BlockNote/pull/2651))
+
+### ❤️ Thank You
+
+- Claude Opus 4.6 (1M context)
+- Nick Perez
+- Nick the Sick
+- Stephan Meijer @StephanMeijer
+
+## 0.48.0 (2026-04-13)
+
+### 🚀 Features
+
+- upgrade shiki to v4 and prosemirror-highlight to v0.15.1 ([#2625](https://github.com/TypeCellOS/BlockNote/pull/2625))
+- upgrade nx to 22.6.4 and liveblocks to 3.17.0 ([#2627](https://github.com/TypeCellOS/BlockNote/pull/2627))
+
+### 🩹 Fixes
+
+- Image block selection clears on mouse leave in Safari ([#2613](https://github.com/TypeCellOS/BlockNote/pull/2613))
+- Backspace bug when current block is empty and previous block's last child is empty ([#2610](https://github.com/TypeCellOS/BlockNote/pull/2610))
+- allow using latest @tiptap/extension-link version ([1ae8de713](https://github.com/TypeCellOS/BlockNote/commit/1ae8de713))
+- restore depth guard in getParentBlockInfo to prevent RangeError (blo-1103) ([#2585](https://github.com/TypeCellOS/BlockNote/pull/2585))
+- pin better-auth to ~1.4.x to fix docs build ([bda30458a](https://github.com/TypeCellOS/BlockNote/commit/bda30458a))
+- hide side menu on scroll instead of overflow hacks ([#2630](https://github.com/TypeCellOS/BlockNote/pull/2630), [#2043](https://github.com/TypeCellOS/BlockNote/issues/2043))
+- disable default UI when no components context is found ([#2611](https://github.com/TypeCellOS/BlockNote/pull/2611))
+- add .js extension to fast-deep-equal ESM import ([#2641](https://github.com/TypeCellOS/BlockNote/pull/2641))
+- placeholder when overflowing now wraps ([#2291](https://github.com/TypeCellOS/BlockNote/pull/2291))
+- **core:** fix unnesting blocks with siblings (BLO-1017) ([#2601](https://github.com/TypeCellOS/BlockNote/pull/2601))
+- **core:** backspace mid-text next to columnList moves block BLO-1126 ([#2629](https://github.com/TypeCellOS/BlockNote/pull/2629))
+
+### 🔥 Performance
+
+- optimize plugin traversals for large documents BLO-1111 ([#2600](https://github.com/TypeCellOS/BlockNote/pull/2600))
+
+### ❤️ Thank You
+
+- Claude Opus 4.6
+- Claude Opus 4.6 (1M context)
+- hedi-ghodhbane @hedi-ghodhbane
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Nick the Sick @nperez0111
+- Yousef
+
+## 0.47.3 (2026-03-25)
+
+### 🩹 Fixes
+
+- **core:** preserve whitespace edge cases but collapse html formatting newlines (BLO-1065) ([#2551](https://github.com/TypeCellOS/BlockNote/pull/2551), [#2230](https://github.com/TypeCellOS/BlockNote/issues/2230))
+
+### ❤️ Thank You
+
+- Yousef
+
+## 0.47.2 (2026-03-20)
+
+### 🩹 Fixes
+
+- use / for toggle block HTML export ([#2524](https://github.com/TypeCellOS/BlockNote/pull/2524))
+- remove @hocuspocus/provider peer dependency by inlining tiptap comment types BLO-1064 ([#2564](https://github.com/TypeCellOS/BlockNote/pull/2564))
+- **core:** slash menu fails in custom blocks after space BLO-1036 ([#2553](https://github.com/TypeCellOS/BlockNote/pull/2553))
+- **i18n:** fix typo in russian translation ([#2560](https://github.com/TypeCellOS/BlockNote/pull/2560))
+
+### ❤️ Thank You
+
+- Claude Opus 4.6
+- Drone
+- Yousef
+
+## 0.47.1 (2026-03-02)
+
+### 🩹 Fixes
+
+- typeerror cannot read properties of undefined ([#2522](https://github.com/TypeCellOS/BlockNote/pull/2522))
+- handle more delete key cases ([#2126](https://github.com/TypeCellOS/BlockNote/pull/2126))
+- add delay for `data-active` in collab cursors ([#2383](https://github.com/TypeCellOS/BlockNote/pull/2383))
+- disable slash menu in table content #2408 ([#2504](https://github.com/TypeCellOS/BlockNote/pull/2504), [#2408](https://github.com/TypeCellOS/BlockNote/issues/2408))
+- **ai:** selections broken due to floating-ui focus manager ([#2527](https://github.com/TypeCellOS/BlockNote/pull/2527))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Yousef
+
+## 0.47.0 (2026-02-23)
+
+### 🚀 Features
+
+- update suggestion menu component ([#2397](https://github.com/TypeCellOS/BlockNote/pull/2397))
+- **i18n:** add Persian (fa) localization support ([#2447](https://github.com/TypeCellOS/BlockNote/pull/2447))
+- **i18n:** add Uzbek (uz) localization support ([#2506](https://github.com/TypeCellOS/BlockNote/pull/2506))
+
+### 🩹 Fixes
+
+- prevent nested bullet list icon rendering as emoji on iOS 18+ ([#2394](https://github.com/TypeCellOS/BlockNote/pull/2394), [#2399](https://github.com/TypeCellOS/BlockNote/pull/2399))
+- ignore drag & drop from unrelated events #1968 ([#2346](https://github.com/TypeCellOS/BlockNote/pull/2346), [#1968](https://github.com/TypeCellOS/BlockNote/issues/1968))
+- disable checkbox when editor is not editable #2406 ([#2448](https://github.com/TypeCellOS/BlockNote/pull/2448), [#2406](https://github.com/TypeCellOS/BlockNote/issues/2406))
+- Backspace/enter behaviour in empty block with children ([#2451](https://github.com/TypeCellOS/BlockNote/pull/2451))
+- handle pasting into table cells better, by collapsing their content to inline #2410 ([#2449](https://github.com/TypeCellOS/BlockNote/pull/2449), [#2410](https://github.com/TypeCellOS/BlockNote/issues/2410))
+- **accessibility:** ai combobox aria-activedescendant ([#2413](https://github.com/TypeCellOS/BlockNote/pull/2413))
+- **ai:** no more scrolling to top when opening AI menu ([#2503](https://github.com/TypeCellOS/BlockNote/pull/2503))
+- **docs:** unicode char not rendered in bug template ([f13e270be](https://github.com/TypeCellOS/BlockNote/commit/f13e270be))
+
+### ❤️ Thank You
+
+- Cyril G @Ovgodd
+- Dex Devlon @bxff
+- Matthew Lipski @matthewlipski
+- MDSAM05 @MDSAM05
+- Mohammad RAHMANI @Mrahmani71
+- Nick Perez
+- Ogabek @OgabekYuldoshev
+- Wouter Vroege
+- Yousef
+
+## 0.46.2 (2026-01-27)
+
+### 🩹 Fixes
+
+- deep merge floatingUIOptions using nested spread operators ([#2310](https://github.com/TypeCellOS/BlockNote/pull/2310))
+- Visual differences between live editor and rendered exported HTML ([#2348](https://github.com/TypeCellOS/BlockNote/pull/2348))
+- `BlockNoteViewEditor` mismatched editable value ([#2357](https://github.com/TypeCellOS/BlockNote/pull/2357))
+- add `font-synthesis` for italic & bold in fonts that don't have them specified #2325 ([#2354](https://github.com/TypeCellOS/BlockNote/pull/2354), [#2325](https://github.com/TypeCellOS/BlockNote/issues/2325))
+- disable code block language selector when editor is not editable ([#2351](https://github.com/TypeCellOS/BlockNote/pull/2351))
+- table handles would crash ([#2384](https://github.com/TypeCellOS/BlockNote/pull/2384))
+- update CreateLinkButton to be able to toggle popover visibility ([#2316](https://github.com/TypeCellOS/BlockNote/pull/2316), [#2313](https://github.com/TypeCellOS/BlockNote/issues/2313))
+- add context,nestingLevel to toExternalHTML ([#2373](https://github.com/TypeCellOS/BlockNote/pull/2373))
+- **ai:** re-enable flipping the AIMenu when there is not enough space #2245 ([#2247](https://github.com/TypeCellOS/BlockNote/pull/2247), [#2245](https://github.com/TypeCellOS/BlockNote/issues/2245))
+- **link-toolbar:** prevent Enter from submitting during IME composition ([#2361](https://github.com/TypeCellOS/BlockNote/pull/2361))
+
+### ❤️ Thank You
+
+- hanios123
+- Jean-Baptiste PENRATH
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Shohei Yoshida @ysds
+- Yousef
+
+## 0.46.1 (2026-01-10)
+
+This was a version bump only, there were no code changes.
+
+## 0.46.0 (2026-01-08)
+
+### 🚀 Features
+
+- add data-nesting-level to HTML export ([#2329](https://github.com/TypeCellOS/BlockNote/pull/2329))
+- migrate to ai sdk 6 ([#2328](https://github.com/TypeCellOS/BlockNote/pull/2328))
+
+### 🩹 Fixes
+
+- emojipicker can sometimes fail to mount ([575b81cec](https://github.com/TypeCellOS/BlockNote/commit/575b81cec))
+- LinkToolbar Event Listener leak ([#2335](https://github.com/TypeCellOS/BlockNote/pull/2335))
+- when you convert a block into checkListItem via inputRule, it should transfer its content into checkListItem content ([#2331](https://github.com/TypeCellOS/BlockNote/pull/2331))
+- do not return focus back to menu ([484d7da36](https://github.com/TypeCellOS/BlockNote/commit/484d7da36))
+- arrow up on a checklist item should move to the element above BLO-362 ([#2306](https://github.com/TypeCellOS/BlockNote/pull/2306))
+- getPos race condition in React StrictMode ([#2311](https://github.com/TypeCellOS/BlockNote/pull/2311))
+- adjust input rules to be more tolerant to starting whitespace ([#2341](https://github.com/TypeCellOS/BlockNote/pull/2341))
+- **ai:** make sure ShowSelection works ([#2297](https://github.com/TypeCellOS/BlockNote/pull/2297))
+- **xl-email-exporter:** remove redundant sections in email export ([#2323](https://github.com/TypeCellOS/BlockNote/pull/2323))
+
+### ❤️ Thank You
+
+- Nick Perez
+- Nick the Sick @nperez0111
+- supernova @tmpluto
+- Yousef
+
+## 0.45.0 (2025-12-17)
+
+### 🚀 Features
+
+- **ai:** expand selections to contain words ([#2304](https://github.com/TypeCellOS/BlockNote/pull/2304))
+- **extensions:** extensions can now include other extensions for grouping into one extension ([#2284](https://github.com/TypeCellOS/BlockNote/pull/2284))
+
+### 🩹 Fixes
+
+- an invalidly specified table should not crash the editor ([#2255](https://github.com/TypeCellOS/BlockNote/pull/2255))
+- filter out invalid heading items based on the current block schema in the slash menu #2253 ([#2259](https://github.com/TypeCellOS/BlockNote/pull/2259), [#2253](https://github.com/TypeCellOS/BlockNote/issues/2253))
+- relax shiki package requirements #2279 ([#2280](https://github.com/TypeCellOS/BlockNote/pull/2280), [#2279](https://github.com/TypeCellOS/BlockNote/issues/2279))
+- filter the default tiptap extensions #2282 ([#2283](https://github.com/TypeCellOS/BlockNote/pull/2283), [#2282](https://github.com/TypeCellOS/BlockNote/issues/2282))
+- always include the cursor extension #2244 ([#2260](https://github.com/TypeCellOS/BlockNote/pull/2260), [#2244](https://github.com/TypeCellOS/BlockNote/issues/2244))
+- make `onBeforeChange` return the correct type again ([9009369b1](https://github.com/TypeCellOS/BlockNote/commit/9009369b1))
+- if there is no table block, there is no table handles to show #1055 ([#2281](https://github.com/TypeCellOS/BlockNote/pull/2281), [#1055](https://github.com/TypeCellOS/BlockNote/issues/1055))
+- pass dragHandleMenu prop to DragHandleButton ([#2254](https://github.com/TypeCellOS/BlockNote/pull/2254))
+- html diff error with whitespace ([#2230](https://github.com/TypeCellOS/BlockNote/pull/2230))
+- update regex for checklist items #2288 ([#2305](https://github.com/TypeCellOS/BlockNote/pull/2305), [#2288](https://github.com/TypeCellOS/BlockNote/issues/2288))
+- **email-exporter:** ReadableByteStreamController for safari react-email ([#2295](https://github.com/TypeCellOS/BlockNote/pull/2295))
+
+### ❤️ Thank You
+
+- Max @maqen
+- Nick Perez
+- Nick the Sick @nperez0111
+- Yousef
+
+## 0.44.2 (2025-12-09)
+
+### 🩹 Fixes
+
+- put back `onBeforeChange` method #2221 ([#2243](https://github.com/TypeCellOS/BlockNote/pull/2243), [#2221](https://github.com/TypeCellOS/BlockNote/issues/2221))
+- Improper accessing of editor DOM element ([#2234](https://github.com/TypeCellOS/BlockNote/pull/2234))
+- make validation errors recoverable by llm ([#2054](https://github.com/TypeCellOS/BlockNote/pull/2054))
+- shadowdom support and example ([#2223](https://github.com/TypeCellOS/BlockNote/pull/2223))
+- ensure numbered list start property always present ([#2241](https://github.com/TypeCellOS/BlockNote/pull/2241), [#2242](https://github.com/TypeCellOS/BlockNote/pull/2242))
+- Suggestion menu positioning ([#2232](https://github.com/TypeCellOS/BlockNote/pull/2232))
+- conditionally access the TableHandles extension from React ([#2248](https://github.com/TypeCellOS/BlockNote/pull/2248))
+- **ai:** upgrade prosemirror-suggest-changes ([#2235](https://github.com/TypeCellOS/BlockNote/pull/2235))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- wcyat @sdip15fa
+- Yousef
+
+## 0.44.1 (2025-12-08)
+
+### 🩹 Fixes
+
+- clearing selection was not being called when create link button is no longer rendered ([#2217](https://github.com/TypeCellOS/BlockNote/pull/2217))
+- AI menu not updating position on new line ([#2233](https://github.com/TypeCellOS/BlockNote/pull/2233))
+- UI elements not scrolling when editor DOM element is scrollable ([#2231](https://github.com/TypeCellOS/BlockNote/pull/2231))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+
+## 0.44.0 (2025-12-02)
+
+### 🚀 Features
+
+- **ai:** Abort requests ([#2213](https://github.com/TypeCellOS/BlockNote/pull/2213))
+
+### ❤️ Thank You
+
+- Yousef
+
+## 0.43.0 (2025-12-01)
+
+### 🚀 Features
+
+- Major Extensions & UI Refactor ([#2143](https://github.com/TypeCellOS/BlockNote/pull/2143))
+
+### 🩹 Fixes
+
+- allow configuring the email body's styles ([#2182](https://github.com/TypeCellOS/BlockNote/pull/2182))
+- **xl-docx-exporter:** improve OOXML interoperability ([#2206](https://github.com/TypeCellOS/BlockNote/pull/2206))
+
+### ❤️ Thank You
+
+- Nick Perez
+- Stephan Meijer @StephanMeijer
+
+## 0.42.3 (2025-11-19)
+
+### 🩹 Fixes
+
+- disallow access to the `domElement` or `isFocused` if the editor is unmounted ([#2187](https://github.com/TypeCellOS/BlockNote/pull/2187))
+
+### ❤️ Thank You
+
+- Nick Perez
+
+## 0.42.2 (2025-11-19)
+
+### 🩹 Fixes
+
+- put back mounting system ([#2183](https://github.com/TypeCellOS/BlockNote/pull/2183))
+
+### ❤️ Thank You
+
+- Nick Perez
+
+## 0.42.1 (2025-11-18)
+
+### 🩹 Fixes
+
+- do not error on invalid `backgroundColor` or `textColor` #2176 ([#2179](https://github.com/TypeCellOS/BlockNote/pull/2179), [#2176](https://github.com/TypeCellOS/BlockNote/issues/2176))
+- remove dependency array from comments re-rendering ([#2177](https://github.com/TypeCellOS/BlockNote/pull/2177))
+
+### ❤️ Thank You
+
+- Nick Perez
+
+## 0.42.0 (2025-11-11)
+
+### 🚀 Features
+
+- **yjs:** expose Y.js BlockNote conversion primitives #1866 ([#2166](https://github.com/TypeCellOS/BlockNote/pull/2166), [#1866](https://github.com/TypeCellOS/BlockNote/issues/1866))
+
+### 🩹 Fixes
+
+- Emoji picker issues ([#2092](https://github.com/TypeCellOS/BlockNote/pull/2092))
+- set a default for `blocksToFullHTML` #2100 ([#2101](https://github.com/TypeCellOS/BlockNote/pull/2101), [#2100](https://github.com/TypeCellOS/BlockNote/issues/2100))
+- correctly index blocks that have children fixes #2115 ([#2116](https://github.com/TypeCellOS/BlockNote/pull/2116), [#2115](https://github.com/TypeCellOS/BlockNote/issues/2115))
+- add more lenient parsing for code blocks, to accept newlines #2105 ([#2108](https://github.com/TypeCellOS/BlockNote/pull/2108), [#2105](https://github.com/TypeCellOS/BlockNote/issues/2105))
+- Firefox invisible text cursor after dropping blocks ([#2128](https://github.com/TypeCellOS/BlockNote/pull/2128))
+- parsing `priority` for custom inline content and styles ([#2119](https://github.com/TypeCellOS/BlockNote/pull/2119))
+- `BlockTypeSelect` item filtering based on schema ([#2112](https://github.com/TypeCellOS/BlockNote/pull/2112))
+- deleting last block in column ([#2110](https://github.com/TypeCellOS/BlockNote/pull/2110))
+- **comments:** update the styles for the cursor to be the default cursor ([#2163](https://github.com/TypeCellOS/BlockNote/pull/2163))
+- **comments:** always surface the closest mark to the current position ([#2164](https://github.com/TypeCellOS/BlockNote/pull/2164))
+- **comments:** scrolling bug when clicking comment marks ([#2165](https://github.com/TypeCellOS/BlockNote/pull/2165))
+- **react:** destroy editor instances after two ticks ([#2121](https://github.com/TypeCellOS/BlockNote/pull/2121))
+- **schema-migration:** more robust migration of background-color & text-color attributes ([#2154](https://github.com/TypeCellOS/BlockNote/pull/2154))
+- **unique-id:** do not attempt to append to y-sync plugin transactions ([#2153](https://github.com/TypeCellOS/BlockNote/pull/2153))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+
+## 0.41.1 (2025-10-09)
+
+This was a version bump only, there were no code changes.
+
+## 0.41.0 (2025-10-08)
+
+### 🚀 Features
+
+- AI menu auto scrolling ([#2039](https://github.com/TypeCellOS/BlockNote/pull/2039))
+- Shortcut to delete empty table while cells are selected ([#2052](https://github.com/TypeCellOS/BlockNote/pull/2052))
+- **divider:** add a divider block ([#2014](https://github.com/TypeCellOS/BlockNote/pull/2014))
+
+### 🩹 Fixes
+
+- Code block language select value not updating properly ([#2050](https://github.com/TypeCellOS/BlockNote/pull/2050))
+- disable input rules for numbered headings #1789 ([#2032](https://github.com/TypeCellOS/BlockNote/pull/2032), [#1789](https://github.com/TypeCellOS/BlockNote/issues/1789))
+- video parsing and export for markdown ([#1955](https://github.com/TypeCellOS/BlockNote/pull/1955))
+- Reaction picker shown for users who can't react ([#2061](https://github.com/TypeCellOS/BlockNote/pull/2061))
+- Add Mantine dependency to individual examples ([#2070](https://github.com/TypeCellOS/BlockNote/pull/2070))
+- allow listening to `onChange` and other events before the underlying editor is initialized ([#2063](https://github.com/TypeCellOS/BlockNote/pull/2063))
+- toggle and check list item blocks ([#2071](https://github.com/TypeCellOS/BlockNote/pull/2071))
+- added missing fields to implementations in editor schema block specs ([#2046](https://github.com/TypeCellOS/BlockNote/pull/2046))
+
+### ❤️ Thank You
+
+- Héctor Zhuang @Hector-Zhuang
+- Matthew Lipski @matthewlipski
+- Nick Perez
+
+## 0.40.0 (2025-09-30)
+
+### 🚀 Features
+
+- Mantine v8 upgrade ([#2028](https://github.com/TypeCellOS/BlockNote/pull/2028), [#2029](https://github.com/TypeCellOS/BlockNote/issues/2029))
+- Update Mantine setup ([#2033](https://github.com/TypeCellOS/BlockNote/pull/2033))
+- **ai:** SDK 5, tool calling, custom backends ([#2007](https://github.com/TypeCellOS/BlockNote/pull/2007))
+- **core:** add the ability to autofocus on the editor element ([#2018](https://github.com/TypeCellOS/BlockNote/pull/2018))
+
+### 🩹 Fixes
+
+- Block colors menu not always showing ([#2027](https://github.com/TypeCellOS/BlockNote/pull/2027))
+- Update remianing examples to Mantine v8 ([#2031](https://github.com/TypeCellOS/BlockNote/pull/2031))
+- ShadCN example Tailwind setup ([#2042](https://github.com/TypeCellOS/BlockNote/pull/2042))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Yousef
+
+## 0.39.1 (2025-09-19)
+
+### 🩹 Fixes
+
+- cleanup accesses to prosemirrorView to account for tiptap 3 behavior ([#2017](https://github.com/TypeCellOS/BlockNote/pull/2017))
+- **core:** input rules can handle when a new block is empty now ([#2013](https://github.com/TypeCellOS/BlockNote/pull/2013))
+
+### ❤️ Thank You
+
+- Nick Perez
+
+## 0.39.0 (2025-09-18)
+
+### 🚀 Features
+
+- move all blocks to use the custom blocks API ([#1904](https://github.com/TypeCellOS/BlockNote/pull/1904))
+- **core:** support for Tiptap V3 ([#2001](https://github.com/TypeCellOS/BlockNote/pull/2001))
+
+### ❤️ Thank You
+
+- Nick Perez
+
+## 0.38.0 (2025-09-16)
+
+### 🚀 Features
+
+- Custom schemas for comment editors ([#1976](https://github.com/TypeCellOS/BlockNote/pull/1976))
+
+### 🩹 Fixes
+
+- Suggestion menu positioning ([#1975](https://github.com/TypeCellOS/BlockNote/pull/1975))
+- doLLMRequest fails when deleting a non-existent block ([#1982](https://github.com/TypeCellOS/BlockNote/pull/1982))
+- file block resize handles not working with touch inputs ([#1981](https://github.com/TypeCellOS/BlockNote/pull/1981))
+- get pdf example working again ([a90ae4d58](https://github.com/TypeCellOS/BlockNote/commit/a90ae4d58))
+- better markdown & html paste, make methods synchronous ([#1957](https://github.com/TypeCellOS/BlockNote/pull/1957))
+- Improve setting text for custom file blocks ([#1984](https://github.com/TypeCellOS/BlockNote/pull/1984))
+- **react:** close link popover on submit in static formatting toolbar #1696 ([#1997](https://github.com/TypeCellOS/BlockNote/pull/1997), [#1696](https://github.com/TypeCellOS/BlockNote/issues/1696))
+
+### ❤️ Thank You
+
+- dsriva03 @dsriva03
+- Héctor Zhuang @Hector-Zhuang
+- Matthew Lipski @matthewlipski
+- Nick the Sick
+
+## 0.37.0 (2025-08-29)
+
+### 🚀 Features
+
+- export `ShadCNComponentsContext` ([#1965](https://github.com/TypeCellOS/BlockNote/pull/1965))
+
+### 🩹 Fixes
+
+- Typing in empty table cells ([#1973](https://github.com/TypeCellOS/BlockNote/pull/1973))
+
+### ❤️ Thank You
+
+- Héctor Zhuang @Hector-Zhuang
+- Matthew Lipski @matthewlipski
+
+## 0.36.1 (2025-08-27)
+
+### 🩹 Fixes
+
+- table column widths not being set in exported HTML ([#1947](https://github.com/TypeCellOS/BlockNote/pull/1947))
+- Minor change to formatting toolbar extension logic ([#1963](https://github.com/TypeCellOS/BlockNote/pull/1963))
+- **core:** report block moves in `getBlocksChangedByTransaction` #1924 ([#1960](https://github.com/TypeCellOS/BlockNote/pull/1960), [#1924](https://github.com/TypeCellOS/BlockNote/issues/1924))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+
+## 0.36.0 (2025-08-25)
+
+### 🚀 Features
+
+- **docx:** add locale configuration for docx export ([#1937](https://github.com/TypeCellOS/BlockNote/pull/1937))
+
+### 🩹 Fixes
+
+- Editors in comments not inheriting theme ([#1890](https://github.com/TypeCellOS/BlockNote/pull/1890))
+- Minor drag & drop changes ([#1891](https://github.com/TypeCellOS/BlockNote/pull/1891))
+- Overflow on table blocks ([#1892](https://github.com/TypeCellOS/BlockNote/pull/1892))
+- Suggestion menu closing when clicking scroll bar ([#1899](https://github.com/TypeCellOS/BlockNote/pull/1899))
+- Table padding ([#1906](https://github.com/TypeCellOS/BlockNote/pull/1906))
+- Formatting toolbar getting wrong bounding box when updating React inline content ([#1908](https://github.com/TypeCellOS/BlockNote/pull/1908))
+- Vanilla blocks return true for editor.isEditable on initial render ([#1925](https://github.com/TypeCellOS/BlockNote/pull/1925))
+- table cell menu styling ([#1945](https://github.com/TypeCellOS/BlockNote/pull/1945))
+- Missing internationalization for toggle wrapper ([#1946](https://github.com/TypeCellOS/BlockNote/pull/1946))
+- parse image alt text for image blocks ([#1883](https://github.com/TypeCellOS/BlockNote/pull/1883))
+- initialize esm deps before copy extension uses it ([#1951](https://github.com/TypeCellOS/BlockNote/pull/1951))
+- error when dragging a block from one editor to another with multiple column extension ([#1950](https://github.com/TypeCellOS/BlockNote/pull/1950))
+- prevent infinite render loop when selecting all content ([#1956](https://github.com/TypeCellOS/BlockNote/pull/1956))
+- **core:** maintain text selection across table updates ([#1894](https://github.com/TypeCellOS/BlockNote/pull/1894))
+- **locales:** ko locale fix ([#1902](https://github.com/TypeCellOS/BlockNote/pull/1902))
+- **react:** add data attribute for correct react rendering ([#1954](https://github.com/TypeCellOS/BlockNote/pull/1954))
+- **xl-email-exporter:** better defaults, customize textStyles, output inline styles ([#1856](https://github.com/TypeCellOS/BlockNote/pull/1856))
+
+### ❤️ Thank You
+
+- Brad Greenlee
+- Cyril G @Ovgodd
+- Héctor Zhuang @Hector-Zhuang
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Nick the Sick
+
+## 0.35.0 (2025-07-25)
+
+### 🚀 Features
+
+- use fumadocs for website ([#1654](https://github.com/TypeCellOS/BlockNote/pull/1654))
+- llms.mdx routes ([cea93840e](https://github.com/TypeCellOS/BlockNote/commit/cea93840e))
+
+### 🩹 Fixes
+
+- insert file upload before block if it is closer to the top of the block ([#1857](https://github.com/TypeCellOS/BlockNote/pull/1857))
+- rename albert model ([3b0ba8d25](https://github.com/TypeCellOS/BlockNote/commit/3b0ba8d25))
+- resolve some minor drag & drop regressions ([#1862](https://github.com/TypeCellOS/BlockNote/pull/1862))
+- blockquote HTML parsing #1762 ([#1877](https://github.com/TypeCellOS/BlockNote/pull/1877), [#1762](https://github.com/TypeCellOS/BlockNote/issues/1762))
+
+### ❤️ Thank You
+
+- Brad Greenlee
+- Nick Perez
+- Nick the Sick
+- yousefed
+
+## 0.34.0 (2025-07-17)
+
+### 🚀 Features
+
+- support multi-column block in PDF, DOCX & ODT exporters ([#1781](https://github.com/TypeCellOS/BlockNote/pull/1781))
+- support react 19 ([f7b3466d3](https://github.com/TypeCellOS/BlockNote/commit/f7b3466d3))
+- disable conversion of headings to list items ([#1799](https://github.com/TypeCellOS/BlockNote/pull/1799))
+- report `moves` (indents and outdents) as changes when using `getChanges` #1757 ([#1786](https://github.com/TypeCellOS/BlockNote/pull/1786), [#1757](https://github.com/TypeCellOS/BlockNote/issues/1757))
+- allow inline content to be `draggable` ([#1818](https://github.com/TypeCellOS/BlockNote/pull/1818))
+- added type guards, types, and `editor` prop to custom inline content rendering ([#1736](https://github.com/TypeCellOS/BlockNote/pull/1736))
+- **block-change:** adds a new API for blocking changes to editor state, by filtering transactions ([#1750](https://github.com/TypeCellOS/BlockNote/pull/1750))
+
+### 🩹 Fixes
+
+- remove lookbehind regex for browser compat ([#1827](https://github.com/TypeCellOS/BlockNote/pull/1827))
+- `ToggleWrapper` button defaulting to `submit` type ([#1823](https://github.com/TypeCellOS/BlockNote/pull/1823))
+- disable $ref in AI schemas (html format) ([#1819](https://github.com/TypeCellOS/BlockNote/pull/1819))
+- re-evaluate side-menu on scroll ([#1830](https://github.com/TypeCellOS/BlockNote/pull/1830))
+- hide table extend buttons when not editable #1848 ([#1850](https://github.com/TypeCellOS/BlockNote/pull/1850), [#1848](https://github.com/TypeCellOS/BlockNote/issues/1848))
+- resolve several drag & drop issues ([#1845](https://github.com/TypeCellOS/BlockNote/pull/1845))
+
+### ❤️ Thank You
+
+- Arek Nawo @areknawo
+- Gonçalo Basto @gbasto
+- Héctor Zhuang @Hector-Zhuang
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Nick the Sick @nperez0111
+- Yousef
+
+## 0.33.0 (2025-07-03)
+
+### 🚀 Features
+
+- FloatingUI options prop for `BlockPositioner` ([#1801](https://github.com/TypeCellOS/BlockNote/pull/1801))
+- Support Google Gemini AI ([#1805](https://github.com/TypeCellOS/BlockNote/pull/1805))
+
+### 🩹 Fixes
+
+- support multi-character suggestions ([#1734](https://github.com/TypeCellOS/BlockNote/pull/1734))
+- switch foreground color based on selected user color dynamically #1785 ([#1787](https://github.com/TypeCellOS/BlockNote/pull/1787), [#1785](https://github.com/TypeCellOS/BlockNote/issues/1785))
+- mark react package as external in email exporter ([#1807](https://github.com/TypeCellOS/BlockNote/pull/1807))
+- Duplicate `formatConversionTest` files ([#1798](https://github.com/TypeCellOS/BlockNote/pull/1798))
+- AI empty document handling ([#1810](https://github.com/TypeCellOS/BlockNote/pull/1810))
+- `bn-inline-content` class name getting duplicated ([#1794](https://github.com/TypeCellOS/BlockNote/pull/1794))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Yousef
+
+## 0.32.0 (2025-06-24)
+
+### 🚀 Features
+
+- toggle blocks ([#1707](https://github.com/TypeCellOS/BlockNote/pull/1707))
+- **core:** support h4, h5, and h6 ([#1634](https://github.com/TypeCellOS/BlockNote/pull/1634))
+- **xl-email-exporter:** add email exporter ([#1768](https://github.com/TypeCellOS/BlockNote/pull/1768))
+
+### 🩹 Fixes
+
+- react 19 strict mode compatibility ([#1726](https://github.com/TypeCellOS/BlockNote/pull/1726))
+- add keys to pdf exporter ([#1739](https://github.com/TypeCellOS/BlockNote/pull/1739))
+- only listten for left click on formatting toolbar ([#1774](https://github.com/TypeCellOS/BlockNote/pull/1774))
+- prevent formatting toolbar from closing if click was from inside the editor ([#1775](https://github.com/TypeCellOS/BlockNote/pull/1775))
+- **locales:** add Hebrew translations for various components ([#1779](https://github.com/TypeCellOS/BlockNote/pull/1779))
+
+### ❤️ Thank You
+
+- Aslam @Aslam97
+- Drew Johnson
+- Jonathan Marbutt @jmarbutt
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Samuel Bisberg
+- Yousef
+
+## 0.31.3 (2025-06-18)
+
+### 🩹 Fixes
+
+- AI generation with empty document ([#1740](https://github.com/TypeCellOS/BlockNote/pull/1740))
+- do not send a welcome email if magic link was used on an account older than a minute ago ([db88fe4aa](https://github.com/TypeCellOS/BlockNote/commit/db88fe4aa))
+- AI system messages should always be at start of prompt ([#1741](https://github.com/TypeCellOS/BlockNote/pull/1741))
+- Selection clicking editor padding ([#1717](https://github.com/TypeCellOS/BlockNote/pull/1717))
+- preserve marks across a shift+enter #1672 ([#1743](https://github.com/TypeCellOS/BlockNote/pull/1743), [#1672](https://github.com/TypeCellOS/BlockNote/issues/1672))
+- **ai:** undo-redo after accepting/rejecting changes will undo as expected ([#1752](https://github.com/TypeCellOS/BlockNote/pull/1752))
+- **locales:** add translations for some comment strings ([#1764](https://github.com/TypeCellOS/BlockNote/pull/1764))
+- **website:** log in bug fixes ([#1742](https://github.com/TypeCellOS/BlockNote/pull/1742))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Nick the Sick
+- Vinicius Fernandes @ViniCleFer
+- Yousef
+
+## 0.31.2 (2025-06-05)
+
+### 🩹 Fixes
+
+- re-release ([0bc546e18](https://github.com/TypeCellOS/BlockNote/commit/0bc546e18))
+- ignore falsy values in boolean prop schema ([#1730](https://github.com/TypeCellOS/BlockNote/pull/1730))
+
+### ❤️ Thank You
+
+- Nick Perez
+- Nick the Sick
+
+## 0.31.1 (2025-05-23)
+
+### 🩹 Fixes
+
+- backwards-compat for `_extensions` ([#1708](https://github.com/TypeCellOS/BlockNote/pull/1708))
+
+### ❤️ Thank You
+
+- Nick Perez
+
+## 0.31.0 (2025-05-20)
+
+### 🩹 Fixes
+
+- Playwright flaky keyboard handler test ([#1704](https://github.com/TypeCellOS/BlockNote/pull/1704))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+
+## 0.30.1 (2025-05-20)
+
+### 🩹 Fixes
+
+- better type-safety ([678086d4d](https://github.com/TypeCellOS/BlockNote/commit/678086d4d))
+- do not use `editor.dispatch` ([#1698](https://github.com/TypeCellOS/BlockNote/pull/1698))
+- re-added `display: flex` to blocks without inline content ([#1702](https://github.com/TypeCellOS/BlockNote/pull/1702))
+- **react:** add missing exports ([#1689](https://github.com/TypeCellOS/BlockNote/pull/1689))
+
+### ❤️ Thank You
+
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Nick the Sick
+
+## 0.30.0 (2025-05-09)
+
+### 🚀 Features
+
+- expose `editor.prosemirrorState` again ([#1615](https://github.com/TypeCellOS/BlockNote/pull/1615))
+- add `undo` and `redo` methods to editor API ([#1592](https://github.com/TypeCellOS/BlockNote/pull/1592))
+- new auth & payment system ([#1617](https://github.com/TypeCellOS/BlockNote/pull/1617))
+- re-implement Y.js collaboration as BlockNote plugins ([#1638](https://github.com/TypeCellOS/BlockNote/pull/1638))
+- **file:** `previewWidth` prop now defaults to `undefined` ([#1664](https://github.com/TypeCellOS/BlockNote/pull/1664))
+- **locales:** add zh-TW i18n ([#1668](https://github.com/TypeCellOS/BlockNote/pull/1668))
+
+### 🩹 Fixes
+
+- Formatting toolbar regression ([#1630](https://github.com/TypeCellOS/BlockNote/pull/1630))
+- provide `blockId` to `uploadFile` in UploadTab ([#1641](https://github.com/TypeCellOS/BlockNote/pull/1641))
+- do not close the menu on content/selection change ([#1644](https://github.com/TypeCellOS/BlockNote/pull/1644))
+- keep file panel open during collaboration ([#1646](https://github.com/TypeCellOS/BlockNote/pull/1646))
+- force pasting plain text into code block ([#1663](https://github.com/TypeCellOS/BlockNote/pull/1663))
+- updating HTML parsing rules to account for `prosemirror-model@1.25.1` ([#1661](https://github.com/TypeCellOS/BlockNote/pull/1661))
+- **code-block:** handle unknown languages better ([#1626](https://github.com/TypeCellOS/BlockNote/pull/1626))
+- **locales:** add slovak i18n ([#1649](https://github.com/TypeCellOS/BlockNote/pull/1649))
+
+### ❤️ Thank You
+
+- l0st0 @l0st0
+- Lawrence Lin @linyiru
+- Matthew Lipski @matthewlipski
+- Nick Perez
+- Quentin Nativel
+
+## 0.29.1 (2025-04-17)
+
+### 🩹 Fixes
+
+- try not to always use workspace version ([7af344ea9](https://github.com/TypeCellOS/BlockNote/commit/7af344ea9))
+
+### ❤️ Thank You
+
+- Nick the Sick
+
+## 0.29.0 (2025-04-17)
+
+### 🚀 Features
+
+- `change` event allows getting a list of the block changed ([#1585](https://github.com/TypeCellOS/BlockNote/pull/1585))
+
+### 🩹 Fixes
+
+- allow opening another suggestion menu if another is triggered #1473 ([#1591](https://github.com/TypeCellOS/BlockNote/pull/1591), [#1473](https://github.com/TypeCellOS/BlockNote/issues/1473))
+- add quote to schema ([aa16b15fe](https://github.com/TypeCellOS/BlockNote/commit/aa16b15fe))
+- update y-prosemirror to fix #1462 ([#1608](https://github.com/TypeCellOS/BlockNote/pull/1608), [#1462](https://github.com/TypeCellOS/BlockNote/issues/1462))
+- dispatch suggestion menu as a separate transaction ([#1614](https://github.com/TypeCellOS/BlockNote/pull/1614))
+
+### ❤️ Thank You
+
+- Nick Perez
+- Nick the Sick
+
+## 0.28.0 (2025-04-07)
+
+### 🚀 Features
+
+- position storage ([#1529](https://github.com/TypeCellOS/BlockNote/pull/1529))
+
+### ❤️ Thank You
+
+- Nick Perez
+
+## 0.27.2 (2025-04-05)
+
+### 🩹 Fixes
+
+- minor update for publishing ([c2820fdac](https://github.com/TypeCellOS/BlockNote/commit/c2820fdac))
+
+### ❤️ Thank You
+
+- Nick the Sick
+
+## 0.27.1 (2025-04-05)
+
+### 🚀 Features
+
+- **nx-cloud:** set up nx workspace ([#1586](https://github.com/TypeCellOS/BlockNote/pull/1586))
+
+### 🩹 Fixes
+
+- update packages to use correct react versions ([ea11ebce0](https://github.com/TypeCellOS/BlockNote/commit/ea11ebce0))
+
+### ❤️ Thank You
+
+- Nick Perez
+- Nick the Sick
+
## 0.27.0 (2025-04-04)
### 🚀 Features
@@ -21,4 +855,8 @@
- Martinrsts @Martinrsts
- Matthew Lipski @matthewlipski
-- Nick Perez
\ No newline at end of file
+- Nick Perez
+
+## Previous Versions
+
+See [Github Releases](https://github.com/TypeCellOS/BlockNote/releases) for previous versions.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 37d7f716e6..8fe42686f0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -39,10 +39,49 @@ pnpm start
## Packages
| Package | Size | Version |
-|--------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
+| ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| [@blocknote/core](https://github.com/TypeCellOS/BlockNote/tree/main/packages/core) | | |
| [@blocknote/react](https://github.com/TypeCellOS/BlockNote/tree/main/packages/react) | | |
| [@blocknote/ariakit](https://github.com/TypeCellOS/BlockNote/tree/main/packages/ariakit) | | |
| [@blocknote/mantine](https://github.com/TypeCellOS/BlockNote/tree/main/packages/mantine) | | |
| [@blocknote/shadcn](https://github.com/TypeCellOS/BlockNote/tree/main/packages/shadcn) | | |
| [@blocknote/server-util](https://github.com/TypeCellOS/BlockNote/tree/main/packages/server-util) | | |
+
+## Releasing
+
+This diagram illustrates the release workflow for the BlockNote monorepo.
+
+
+
+Essentially, when the maintainers have decided to release a new version of BlockNote, they will:
+
+ 1. Check that the `main` branch is in a releasable state:
+ - CI status of main branch is green
+ - Builds are passing
+ 2. Bump the package versions using the `pnpm run deploy` command. This command will:
+ 1. Based on semantic versioning, determine the next version number.
+ 2. Apply the new version number to all publishable packages within the monorepo.
+ 3. Generate a changelog for the new version.
+ 4. Commit the changes to the `main` branch.
+ 5. Create a new git tag for the new version.
+ 6. Push the changes to the `origin` remote.
+ 7. Create a new GitHub Release with the same name as the new version.
+ 8. Trigger a release workflow.
+
+The release workflow will:
+
+1. Checkout the `main` branch.
+2. Install the dependencies.
+3. Build the project.
+4. Login to npm.
+5. Publish the packages to npm.
+
+### Publishing a new package
+
+From time to time, you may need to publish a new package to npm. To do this, you cannot just deploy the package to npm, you need to:
+
+ 1. Run `nx release version --dry-run` and check that the version number is correct for the package.
+ - Once this is done, you can run `nx release version` to actually apply the version bump locally (staged to your local git repo).
+ 2. Run `nx release changelog --from --dry-run` and check that the changelog is correct for the package.
+ - Once this is done, you can run the same command without the `--dry-run` flag to actually apply the changelog, commit & push the changes to the `main` branch.
+ 3. The release workflow will automatically publish the package to npm.
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index a612ad9813..0000000000
--- a/LICENSE
+++ /dev/null
@@ -1,373 +0,0 @@
-Mozilla Public License Version 2.0
-==================================
-
-1. Definitions
---------------
-
-1.1. "Contributor"
- means each individual or legal entity that creates, contributes to
- the creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
- means the combination of the Contributions of others (if any) used
- by a Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
- means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
- means Source Code Form to which the initial Contributor has attached
- the notice in Exhibit A, the Executable Form of such Source Code
- Form, and Modifications of such Source Code Form, in each case
- including portions thereof.
-
-1.5. "Incompatible With Secondary Licenses"
- means
-
- (a) that the initial Contributor has attached the notice described
- in Exhibit B to the Covered Software; or
-
- (b) that the Covered Software was made available under the terms of
- version 1.1 or earlier of the License, but not also under the
- terms of a Secondary License.
-
-1.6. "Executable Form"
- means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
- means a work that combines Covered Software with other material, in
- a separate file or files, that is not Covered Software.
-
-1.8. "License"
- means this document.
-
-1.9. "Licensable"
- means having the right to grant, to the maximum extent possible,
- whether at the time of the initial grant or subsequently, any and
- all of the rights conveyed by this License.
-
-1.10. "Modifications"
- means any of the following:
-
- (a) any file in Source Code Form that results from an addition to,
- deletion from, or modification of the contents of Covered
- Software; or
-
- (b) any new file in Source Code Form that contains any Covered
- Software.
-
-1.11. "Patent Claims" of a Contributor
- means any patent claim(s), including without limitation, method,
- process, and apparatus claims, in any patent Licensable by such
- Contributor that would be infringed, but for the grant of the
- License, by the making, using, selling, offering for sale, having
- made, import, or transfer of either its Contributions or its
- Contributor Version.
-
-1.12. "Secondary License"
- means either the GNU General Public License, Version 2.0, the GNU
- Lesser General Public License, Version 2.1, the GNU Affero General
- Public License, Version 3.0, or any later versions of those
- licenses.
-
-1.13. "Source Code Form"
- means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
- means an individual or a legal entity exercising rights under this
- License. For legal entities, "You" includes any entity that
- controls, is controlled by, or is under common control with You. For
- purposes of this definition, "control" means (a) the power, direct
- or indirect, to cause the direction or management of such entity,
- whether by contract or otherwise, or (b) ownership of more than
- fifty percent (50%) of the outstanding shares or beneficial
- ownership of such entity.
-
-2. License Grants and Conditions
---------------------------------
-
-2.1. Grants
-
-Each Contributor hereby grants You a world-wide, royalty-free,
-non-exclusive license:
-
-(a) under intellectual property rights (other than patent or trademark)
- Licensable by such Contributor to use, reproduce, make available,
- modify, display, perform, distribute, and otherwise exploit its
- Contributions, either on an unmodified basis, with Modifications, or
- as part of a Larger Work; and
-
-(b) under Patent Claims of such Contributor to make, use, sell, offer
- for sale, have made, import, and otherwise transfer either its
- Contributions or its Contributor Version.
-
-2.2. Effective Date
-
-The licenses granted in Section 2.1 with respect to any Contribution
-become effective for each Contribution on the date the Contributor first
-distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
-The licenses granted in this Section 2 are the only rights granted under
-this License. No additional rights or licenses will be implied from the
-distribution or licensing of Covered Software under this License.
-Notwithstanding Section 2.1(b) above, no patent license is granted by a
-Contributor:
-
-(a) for any code that a Contributor has removed from Covered Software;
- or
-
-(b) for infringements caused by: (i) Your and any other third party's
- modifications of Covered Software, or (ii) the combination of its
- Contributions with other software (except as part of its Contributor
- Version); or
-
-(c) under Patent Claims infringed by Covered Software in the absence of
- its Contributions.
-
-This License does not grant any rights in the trademarks, service marks,
-or logos of any Contributor (except as may be necessary to comply with
-the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-No Contributor makes additional grants as a result of Your choice to
-distribute the Covered Software under a subsequent version of this
-License (see Section 10.2) or under the terms of a Secondary License (if
-permitted under the terms of Section 3.3).
-
-2.5. Representation
-
-Each Contributor represents that the Contributor believes its
-Contributions are its original creation(s) or it has sufficient rights
-to grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-This License is not intended to limit any rights You have under
-applicable copyright doctrines of fair use, fair dealing, or other
-equivalents.
-
-2.7. Conditions
-
-Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
-in Section 2.1.
-
-3. Responsibilities
--------------------
-
-3.1. Distribution of Source Form
-
-All distribution of Covered Software in Source Code Form, including any
-Modifications that You create or to which You contribute, must be under
-the terms of this License. You must inform recipients that the Source
-Code Form of the Covered Software is governed by the terms of this
-License, and how they can obtain a copy of this License. You may not
-attempt to alter or restrict the recipients' rights in the Source Code
-Form.
-
-3.2. Distribution of Executable Form
-
-If You distribute Covered Software in Executable Form then:
-
-(a) such Covered Software must also be made available in Source Code
- Form, as described in Section 3.1, and You must inform recipients of
- the Executable Form how they can obtain a copy of such Source Code
- Form by reasonable means in a timely manner, at a charge no more
- than the cost of distribution to the recipient; and
-
-(b) You may distribute such Executable Form under the terms of this
- License, or sublicense it under different terms, provided that the
- license for the Executable Form does not attempt to limit or alter
- the recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-You may create and distribute a Larger Work under terms of Your choice,
-provided that You also comply with the requirements of this License for
-the Covered Software. If the Larger Work is a combination of Covered
-Software with a work governed by one or more Secondary Licenses, and the
-Covered Software is not Incompatible With Secondary Licenses, this
-License permits You to additionally distribute such Covered Software
-under the terms of such Secondary License(s), so that the recipient of
-the Larger Work may, at their option, further distribute the Covered
-Software under the terms of either this License or such Secondary
-License(s).
-
-3.4. Notices
-
-You may not remove or alter the substance of any license notices
-(including copyright notices, patent notices, disclaimers of warranty,
-or limitations of liability) contained within the Source Code Form of
-the Covered Software, except that You may alter any license notices to
-the extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-You may choose to offer, and to charge a fee for, warranty, support,
-indemnity or liability obligations to one or more recipients of Covered
-Software. However, You may do so only on Your own behalf, and not on
-behalf of any Contributor. You must make it absolutely clear that any
-such warranty, support, indemnity, or liability obligation is offered by
-You alone, and You hereby agree to indemnify every Contributor for any
-liability incurred by such Contributor as a result of warranty, support,
-indemnity or liability terms You offer. You may include additional
-disclaimers of warranty and limitations of liability specific to any
-jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
----------------------------------------------------
-
-If it is impossible for You to comply with any of the terms of this
-License with respect to some or all of the Covered Software due to
-statute, judicial order, or regulation then You must: (a) comply with
-the terms of this License to the maximum extent possible; and (b)
-describe the limitations and the code they affect. Such description must
-be placed in a text file included with all distributions of the Covered
-Software under this License. Except to the extent prohibited by statute
-or regulation, such description must be sufficiently detailed for a
-recipient of ordinary skill to be able to understand it.
-
-5. Termination
---------------
-
-5.1. The rights granted under this License will terminate automatically
-if You fail to comply with any of its terms. However, if You become
-compliant, then the rights granted under this License from a particular
-Contributor are reinstated (a) provisionally, unless and until such
-Contributor explicitly and finally terminates Your grants, and (b) on an
-ongoing basis, if such Contributor fails to notify You of the
-non-compliance by some reasonable means prior to 60 days after You have
-come back into compliance. Moreover, Your grants from a particular
-Contributor are reinstated on an ongoing basis if such Contributor
-notifies You of the non-compliance by some reasonable means, this is the
-first time You have received notice of non-compliance with this License
-from such Contributor, and You become compliant prior to 30 days after
-Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-infringement claim (excluding declaratory judgment actions,
-counter-claims, and cross-claims) alleging that a Contributor Version
-directly or indirectly infringes any patent, then the rights granted to
-You by any and all Contributors for the Covered Software under Section
-2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all
-end user license agreements (excluding distributors and resellers) which
-have been validly granted by You or Your distributors under this License
-prior to termination shall survive termination.
-
-************************************************************************
-* *
-* 6. Disclaimer of Warranty *
-* ------------------------- *
-* *
-* Covered Software is provided under this License on an "as is" *
-* basis, without warranty of any kind, either expressed, implied, or *
-* statutory, including, without limitation, warranties that the *
-* Covered Software is free of defects, merchantable, fit for a *
-* particular purpose or non-infringing. The entire risk as to the *
-* quality and performance of the Covered Software is with You. *
-* Should any Covered Software prove defective in any respect, You *
-* (not any Contributor) assume the cost of any necessary servicing, *
-* repair, or correction. This disclaimer of warranty constitutes an *
-* essential part of this License. No use of any Covered Software is *
-* authorized under this License except under this disclaimer. *
-* *
-************************************************************************
-
-************************************************************************
-* *
-* 7. Limitation of Liability *
-* -------------------------- *
-* *
-* Under no circumstances and under no legal theory, whether tort *
-* (including negligence), contract, or otherwise, shall any *
-* Contributor, or anyone who distributes Covered Software as *
-* permitted above, be liable to You for any direct, indirect, *
-* special, incidental, or consequential damages of any character *
-* including, without limitation, damages for lost profits, loss of *
-* goodwill, work stoppage, computer failure or malfunction, or any *
-* and all other commercial damages or losses, even if such party *
-* shall have been informed of the possibility of such damages. This *
-* limitation of liability shall not apply to liability for death or *
-* personal injury resulting from such party's negligence to the *
-* extent applicable law prohibits such limitation. Some *
-* jurisdictions do not allow the exclusion or limitation of *
-* incidental or consequential damages, so this exclusion and *
-* limitation may not apply to You. *
-* *
-************************************************************************
-
-8. Litigation
--------------
-
-Any litigation relating to this License may be brought only in the
-courts of a jurisdiction where the defendant maintains its principal
-place of business and such litigation shall be governed by laws of that
-jurisdiction, without reference to its conflict-of-law provisions.
-Nothing in this Section shall prevent a party's ability to bring
-cross-claims or counter-claims.
-
-9. Miscellaneous
-----------------
-
-This License represents the complete agreement concerning the subject
-matter hereof. If any provision of this License is held to be
-unenforceable, such provision shall be reformed only to the extent
-necessary to make it enforceable. Any law or regulation which provides
-that the language of a contract shall be construed against the drafter
-shall not be used to construe this License against a Contributor.
-
-10. Versions of the License
----------------------------
-
-10.1. New Versions
-
-Mozilla Foundation is the license steward. Except as provided in Section
-10.3, no one other than the license steward has the right to modify or
-publish new versions of this License. Each version will be given a
-distinguishing version number.
-
-10.2. Effect of New Versions
-
-You may distribute the Covered Software under the terms of the version
-of the License under which You originally received the Covered Software,
-or under the terms of any subsequent version published by the license
-steward.
-
-10.3. Modified Versions
-
-If you create software not governed by this License, and you want to
-create a new license for such software, you may create and use a
-modified version of this License if you rename the license and remove
-any references to the name of the license steward (except to note that
-such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
-Licenses
-
-If You choose to distribute Source Code Form that is Incompatible With
-Secondary Licenses under the terms of this version of the License, the
-notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
--------------------------------------------
-
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular
-file, then You may include the notice in a location (such as a LICENSE
-file in a relevant directory) where a recipient would be likely to look
-for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
----------------------------------------------------------
-
- This Source Code Form is "Incompatible With Secondary Licenses", as
- defined by the Mozilla Public License, v. 2.0.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000000..35a742ce7e
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,5 @@
+BlockNote is 100% Open Source Software.
+
+Source code in this repository is covered by the "Mozilla Public License Version 2.0" (MPL-2.0) license, except for the XL packages. The MPL-2.0 license allows you to use BlockNote in commercial (and closed-source) applications. If you make changes to the BlockNote source files, you're expected to publish these changes so the wider community can benefit as well.
+
+The XL packages (source code in the `packages/xl-*` directories and published in NPM as `@blocknote/xl-*`) are licensed under the "GNU General Public License Version 3" (GPL-3.0). Additionally, a commercial license is available. See our website (https://www.blocknotejs.org/pricing) for more information and the commercial license terms.
\ No newline at end of file
diff --git a/README.md b/README.md
index 6ad9973798..f391efb3f3 100644
--- a/README.md
+++ b/README.md
@@ -9,16 +9,12 @@ Welcome to BlockNote! The open source Block-Based
React rich text editor. Easily add a modern text editing experience to your app.
-
- );
-}
diff --git a/docs/app/pricing/PricingTiers.tsx b/docs/app/pricing/PricingTiers.tsx
new file mode 100644
index 0000000000..0c7c1c9d48
--- /dev/null
+++ b/docs/app/pricing/PricingTiers.tsx
@@ -0,0 +1,59 @@
+"use client";
+
+import { cn } from "@/lib/fumadocs/cn";
+import { useState } from "react";
+import { Tier, Tiers } from "./tiers";
+
+type Frequency = "month" | "year";
+
+export function PricingTiers({ tiers }: { tiers: Tier[] }) {
+ const [frequency, setFrequency] = useState("year");
+
+ return (
+ <>
+ {/* Frequency Toggle */}
+
+
+ Monthly
+
+
+
+ Yearly
+
+
+ Save 50%
+
+
+
+
+ >
+ );
+}
diff --git a/docs/app/pricing/faq.tsx b/docs/app/pricing/faq.tsx
new file mode 100644
index 0000000000..a7acc4b98f
--- /dev/null
+++ b/docs/app/pricing/faq.tsx
@@ -0,0 +1,140 @@
+import { Accordion, Accordions } from "fumadocs-ui/components/accordion";
+import { Heading } from "fumadocs-ui/components/heading";
+import Link from "next/link";
+
+const faqs = [
+ {
+ question:
+ "What license is BlockNote using? Do I need a subscription to use BlockNote?",
+ answer: (
+ <>
+ We're proud to say that BlockNote is 100% open source software. The
+ core library is licensed under the{" "}
+ MPL 2.0 license,
+ which allows you to use BlockNote in commercial and closed-source
+ applications - even without a subscription. If you make changes to the
+ BlockNote source files, you're expected to publish these changes so
+ the wider community can benefit as well.
+
+ The XL packages (like AI integration, multi-column layouts, and
+ exporters) are dual-licensed and available under{" "}
+ GPL-3.0, or -
+ for closed-source projects - a commercial license as part of the
+ BlockNote Business subscription or above. See the{" "}
+
+ commercial license terms
+ {" "}
+ for the exact details.
+ >
+ ),
+ },
+ {
+ question: "When do I need a commercial license?",
+ answer: (
+ <>
+ Only when you use any of the XL packages (like AI integration,
+ multi-column layouts, and exporters) and you cannot comply with the
+ GPL-3.0 license you'll need a{" "}
+
+ commercial license
+
+ . This is likely to be the case when you're building closed-source
+ applications. The BlockNote Business subscription and above includes a
+ commercial license.
+ >
+ ),
+ },
+ {
+ question: "Why did you choose to dual-license the XL packages?",
+ answer: (
+ <>
+ We’ve built BlockNote as open source from day one and remain committed
+ to keeping the core library licensed under the MPL 2.0. That means it’s
+ free to use—even in commercial and closed-source projects.
+
+ To sustainably support ongoing development, we offer a small set of
+ advanced features (the XL packages) under a dual-license model:
+
+
GPL-3.0 for open-source projects
+
+ Commercial license (included in the BlockNote Business tier and
+ above) for closed-source use
+
+
+ This approach allows us to fund a full-time team while keeping 100% of
+ the code we build open source. It’s our way of balancing community
+ accessibility with long-term sustainability.
+ >
+ ),
+ },
+ {
+ question: "What kind of support is included in a license?",
+ answer: (
+ <>
+ We have you covered! All BlockNote subscriptions come with prioritized
+ support. See the{" "}
+
+ Service Level Agreement
+ {" "}
+ for the exact details.
+ >
+ ),
+ },
+ {
+ question:
+ "Is there any limit to the number of documents or users I can have?",
+ answer: `With BlockNote, there are no limits on the number of documents or users you can have.
+ You're free to run the software on your own infrastructure, and none of your data passes through our servers — your documents and users remain entirely your business.`,
+ },
+ {
+ question: "What if I have more than one SaaS or Web application?",
+ answer: (
+ <>
+ The BlockNote Commercial license (included in the Business tier and
+ above) for XL packages covers one application per license. See the{" "}
+
+ commercial license terms
+ {" "}
+ for the exact details.
+
+ If you want to use XL packages in more than one app, contact us at
+ team@blocknotejs.org; we're happy to work with you on a custom
+ license.
+ >
+ ),
+ },
+ {
+ question: "Do you offer any discounts for startups?",
+ answer: (
+ <>
+ Yes! We offer a discount for startups with less than 5 employees. See
+ the{" "}
+
+ commercial license terms
+ {" "}
+ for the exact details.
+ >
+ ),
+ },
+ {
+ question: "What payment methods do you accept?",
+ answer: `We accept all major credit cards. If you require a different payment method, please contact us.`,
+ },
+];
+
+export function FAQ() {
+ return (
+
+ );
+}
diff --git a/docs/app/pricing/layout.tsx b/docs/app/pricing/layout.tsx
new file mode 100644
index 0000000000..bbe4b9a500
--- /dev/null
+++ b/docs/app/pricing/layout.tsx
@@ -0,0 +1,6 @@
+import { HomeLayout } from "@/components/fumadocs/layout/home";
+import { baseOptions } from "@/lib/layout.shared";
+
+export default function Layout({ children }: LayoutProps<"/pricing">) {
+ return {children};
+}
diff --git a/docs/app/pricing/page.tsx b/docs/app/pricing/page.tsx
new file mode 100644
index 0000000000..ae4e110756
--- /dev/null
+++ b/docs/app/pricing/page.tsx
@@ -0,0 +1,213 @@
+import { FAQ } from "@/app/pricing/faq";
+import { Tier } from "@/app/pricing/tiers";
+import { InfiniteSlider } from "@/components/InfiniteSlider";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/components/ui/tooltip";
+import { getFullMetadata } from "@/lib/getFullMetadata";
+import Link from "next/link";
+import { PricingTiers } from "./PricingTiers";
+
+export const metadata = getFullMetadata({
+ title: "Pricing",
+ path: "/pricing",
+});
+
+const sponsors = [
+ // { name: "Semrush", logo: "/img/sponsors/semrush.light.png" },
+ // { name: "NLnet", logo: "/img/sponsors/nlnetLight.svg" },
+ { name: "DINUM", logo: "/img/sponsors/dinumLight.svg" },
+ { name: "ZenDiS", logo: "/img/sponsors/zendis.svg" },
+ { name: "OpenProject", logo: "/img/sponsors/openproject.svg" },
+ { name: "Poggio", logo: "/img/sponsors/poggioLight.svg" },
+ { name: "Capitol", logo: "/img/sponsors/capitolLight.svg" },
+ { name: "Twenty", logo: "/img/sponsors/twentyLight.png" },
+ { name: "Deep Origin", logo: "/img/sponsors/deepOrigin.svg" },
+ // { name: "Krisp", logo: "/img/sponsors/krisp.svg" },
+];
+
+const tiers: Tier[] = [
+ {
+ id: "free",
+ title: "Community",
+ icon: "💚",
+ tagline: "Get Started",
+ description: (
+ <>
+ Everything you need to get started.{" "}
+
+
+
+ Liberally licensed
+
+
+ BlockNote is MPL-licensed. This is close to MIT and free for any
+ use. The key difference is a "share-alike" requirement:
+ if you modify BlockNote's internal files, you must share
+ those specific changes.
+
+
+ {" "}
+ and free for any project.
+ >
+ ),
+ price: "Free",
+ features: [
+ "All blocks & UI components",
+
+ "Drag-and-drop editing",
+ "Slash commands & menus",
+ "Real-time collaboration",
+ "Comments",
+
+ XL Packages free for OSS under GPL-3.0
+ ,
+ ],
+ cta: "get-started",
+ href: "/docs",
+ },
+ {
+ id: "business",
+ title: "Business",
+ icon: "⚡",
+ tagline: "Go premium",
+ mostPopular: true,
+ badge: "Recommended",
+ description:
+ "Commercial license for access to advanced features and technical support.",
+ price: { month: 390, year: 2340 },
+ features: [
+
+ Commercial license for XL packages:
+ ,
+
+ • AI integration
+ ,
+
+ • Multi-column layouts
+ ,
+
+ • Export to PDF, Docx, ODT, Email
+ ,
+ "Logo on website and repositories",
+
+ Standard Support (
+
+ see SLA
+
+ )
+ ,
+ ],
+ cta: "buy",
+ },
+ {
+ id: "enterprise",
+ title: "Enterprise",
+ icon: "🏢",
+ tagline: "Sustainable partnerships",
+ description: "Custom licensing, dedicated support, and design partnership.",
+ price: "Custom",
+ features: [
+
+ Everything in Business, plus:
+ ,
+ "Custom BlockNote feature development",
+ "Private Slack channel with maintainers",
+ "Onboarding and integration guidance",
+
+ Priority Support (
+
+ see SLA
+
+ )
+ ,
+ ],
+ href: "mailto:team@blocknotejs.org",
+ cta: "contact",
+ },
+];
+
+export default function Pricing() {
+ return (
+
+
+ {/* Header */}
+
+
+ Pricing
+
+
+ 100% Open Source.
+
+
+ Fair Pricing.
+
+
+
+ The majority of BlockNote is liberally licensed and free to use for
+ any purpose. The dual-licensed XL features (like AI) are free for
+ open source projects, but require a commercial license for
+ closed-source applications.
+
+
+
+ {/* Pricing Tiers with Toggle */}
+
+
+ {/* Social proof */}
+
+
+ Trusted by teams building the future of collaboration
+
+
+ {sponsors.map((sponsor) => (
+
+
+
+ ))}
+
+
+
+ {/* Startup Discounts */}
+
+
+ Discounts for Startups
+
+
+ Building the next big thing? We love supporting early-stage
+ companies. If you're a seed-stage startup or non-profit, get in
+ touch for special pricing on our Business plan.
+
- “Vel ultricies morbi odio facilisi ultrices accumsan donec
- lacus purus. Lectus nibh ullamcorper ac dictum justo in
- euismod. Risus aenean ut elit massa. In amet aliquet eget
- cras. Sem volutpat enim tristique.”
-
-
-
-
-
-
- Maria Hill
- {" "}
- – Marketing Manager
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/docs/components/Footer.tsx b/docs/components/Footer.tsx
index 9652ea79dc..15094b1e2b 100644
--- a/docs/components/Footer.tsx
+++ b/docs/components/Footer.tsx
@@ -1,11 +1,14 @@
-import cn from "classnames";
+import { cn } from "@/lib/fumadocs/cn";
+import LogoDark from "@/public/img/logos/banner.dark.svg";
+import LogoLight from "@/public/img/logos/banner.svg";
import Link from "next/link";
-import { ThemeSwitch } from "nextra-theme-docs";
import type { ReactElement, ReactNode } from "react";
-import { Logo } from "./Logo";
+
+import ThemedImage from "@/components/ThemedImage";
+
function FooterLink({ href, children }: { href: string; children: ReactNode }) {
const classes =
- "text-sm text-[#666666] dark:text-[#888888] no-underline betterhover:hover:text-gray-700 betterhover:hover:dark:text-white transition";
+ "text-sm text-stone-500 no-underline transition-colors hover:text-purple-600 block py-1";
if (href.startsWith("http")) {
return (
@@ -21,7 +24,9 @@ function FooterLink({ href, children }: { href: string; children: ReactNode }) {
}
function FooterHeader({ children }: { children: ReactNode }) {
- return