Skip to content

Notion Integration

YapHub maintains a bidirectional sync with Notion, using it as a secondary data store and collaboration layer. Every action in Slack is automatically reflected in Notion, and changes made in Notion can be pulled back into the system.

Notion Databases

The system connects to four Notion databases:

DatabasePurposeSync Direction
KnowledgeKnowledge items with content, tags, AI summariesBidirectional
CategoriesThematic lists with settings and target groupsBidirectional
DigestsGenerated digest reports with statisticsLocal → Notion
SubscriptionsUser category subscriptionsBidirectional

Sync Architecture

Outbound Sync (Slack → Notion)

Triggered immediately when entities are created or updated:

  • Knowledge — A Notion page is created with properties for title, content, tags, status, URL, AI summary, highlight, and category relation
  • Categories — Properties include name, description, icon, target groups, digest settings
  • Digests — Full Markdown content is embedded as page content (not just properties), plus statistics and linked knowledge items
  • Subscriptions — User ID, category, active status, and timestamps

The NotionMarkdownContentService handles embedding full digest content (Markdown) into Notion pages via the Notion API's block children endpoints.

Inbound Sync (Notion → Local)

Triggered via API endpoints, typically from an admin action or scheduled job:

  • POST /api/notion/sync/from-notion — Pulls knowledge items from Notion, creating or updating local records
  • POST /api/notion/sync/categories-from-notion — Pulls categories including target groups
  • POST /api/notion/sync/to-notion — Pushes local knowledge items to Notion (bulk)

Inbound sync includes a force parameter to overwrite local changes with Notion data.

Notion Service Layer

The Notion integration is built on a layered architecture:

ComponentResponsibility
NotionSyncServiceCoordinates bidirectional sync for all entity types
NotionRepositoryManagerResolves the correct repository for a given entity class and ID format
NotionKnowledgeRepositoryCRUD operations on the Notion Knowledge database
NotionCategoryRepositoryCRUD operations on the Notion Categories database
NotionDigestRepositoryCRUD operations on the Notion Digests database
NotionSubscriptionRepositoryCRUD operations on the Notion Subscriptions database
NotionPageBuilderFluent builder for constructing Notion page properties
NotionPropertyExtractorReads and extracts typed values from Notion page properties
NotionMarkdownContentServiceEmbeds Markdown content as Notion blocks via HTTP API

Dual-ID Resolution

The system maintains two ID systems:

  • Local ID — Auto-incrementing integer (SQLite primary key)
  • Notion ID — UUID string (Notion page ID)

The DatabaseResolverInterface implemented by each repository handles this duality: it can look up entities by either local ID or Notion UUID, routing to the correct repository via NotionRepositoryManager.

Property Mapping

Notion properties are mapped to and from local entities using dedicated mappers:

MapperHandles
KnowledgeMapperKnowledge entity ↔ Notion page ↔ KnowledgeDTO
CategoryMapperCategory entity ↔ Notion page
DigestMapperDigest entity ↔ Notion page
SubscriptionMapperSubscription entity ↔ Notion page

Each mapper handles type conversions (e.g., Notion rich text → PHP string, Notion multi-select → PHP array, Notion date → DateTimeImmutable).

Offline Resilience

The system uses SQLite as its primary database. Notion is treated as a sync target, not the source of truth. If Notion is unavailable:

  • Knowledge items, categories, digests, and subscriptions are still created locally
  • Sync failures are logged but don't block user operations
  • Data is synced to Notion when connectivity is restored