What's Changed
New Features
-
Add Notion as a fourth database provider — fields-only sync (page properties ↔ frontmatter) (#125)
- Supports pull, push, and bidirectional sync for Notion databases via an internal integration token
notion-value-converterflattens property values on pull and wraps them back into typed payloads on push (title/rich_text, select/status/multi_select, date, and''→null to clear); people/files/relation fields are read-only- Schema is fetched via
NotionSchemaCacheand used by both the settings UI (data source dropdown, title-property filename auto-fill, field dropdowns) and the push path — schema-load failure fails fast since Notion's PATCH API requires typed payloads - Rate-limited to 3 rps via the existing
RateLimiter; push uses sequential per-pagePATCH /v1/pages/{id}(Notion has no batch endpoint)
-
Add pull-only Notion page-body sync — blocks to Markdown (#128)
- Opt-in per config (
Sync page body, default off): fetches the page content below the properties into the note body on every pull - Converts headings (toggleable → foldable callouts), lists/to-dos, toggles, quotes, callouts (emoji → callout type), code, equations, tables, columns, and synced blocks; media and attachments arrive as links
- New
{{body}}template variable (a realbodyfield still wins for backward compatibility); per-note request budget and depth caps degrade oversized pages to truncation markers instead of failing the sync - Body is pull-only in v1 — Notion is the source of truth; local body edits are overwritten on pull (follows Allow overwrite)
- Opt-in per config (
Bug Fixes
- Preserve ISO datetimes when writing frontmatter (#128)
- The shared YAML formatter clipped any ISO datetime to its date part, so datetime fields lost their time on pull and bidirectional pushes overwrote remote timestamps with midnight — affected Airtable, SeaTable, and Notion alike
- Guard object-shaped attachment and link field types from being pushed to remote (#121)
- Adds
multipleAttachmentsto Airtable'sOBJECT_SHAPED_TYPES— previously pushed stringified garbage to the write API (422 errors / value corruption) - Adds
file,digital-sign, andlinkto SeaTable'sOBJECT_SHAPED_TYPESto match their API value shapes - Enforces the push guard at runtime in
SeaTableClient.batchUpdatevia a lazily-cached column-type map — the prior Airtable-onlyFieldCachegate was not reached on the SeaTable push path image(URL-string array) andmultipleRecordLinks(id-string array) remain pushable as they round-trip correctly through YAML frontmatter
- Adds
- Guard trashed Notion pages and coerce numeric checkbox values on push (#126)
fetchNotesandfetchRecordnow skip pages wherein_trash: true, preventing trashed content from being re-synced or used in conflict resolution- Checkbox push now accepts
0/1in addition to booleans and"true"/"false"strings — some editors round-trip YAML booleans as integers
- Fix false conflict detection over computed/non-pushable columns for all providers (#127)
- SeaTable, Supabase, and Notion no longer raise spurious conflicts (or fail records in manual mode) over formula, rollup, and other non-writable fields
- Push filtering now runs for every provider via a new
fetchFieldMetadata()contract onDatabaseProvider, replacing an Airtable-only gate in the orchestrator - Supabase preserves the existing non-updatable-view guard; Notion retains its documented fail-fast push behavior
Documentation
- Rebuild README around a 4-provider support matrix and collapsible per-provider guides (#130)
- Adds a capability matrix (Pull / Push / Computed / Body) as the opening reference, making provider coverage visible at a glance
- Rewrites Quick Start as collapsible
<details>sections per provider, including a new Notion setup guide (integration token → share via Connections → data source → body-sync toggle) - Replaces the ASCII sync diagram with Mermaid and converts the troubleshooting section to a symptom → check table
- Moves contributor-only content (Supabase demo SQL, e2e env keys, Notion test schema) to
tests/e2e/README.md