| name | logseq-db-plugin-api |
| description | Essential knowledge for developing Logseq plugins for DB (database) graphs. Layered: (1) authoritative upstream docs mirrored from logseq/logseq master, (2) production-tested patterns from logseq-checklist v1.0.0, (3) related skills (Datascript schema, Electron debugging). Covers core APIs, event-driven updates, multi-layered tag detection, property iteration, advanced query patterns. |
Logseq DB Plugin API Skill
Comprehensive guidance for building Logseq plugins for DB (database) graphs, organized into three layers: authoritative upstream documentation, production-tested patterns, and related sibling skills.
Overview
This skill provides essential knowledge for building Logseq plugins that work with the new DB graph architecture. It covers:
- Core APIs: Tag/class management, property handling, block operations
- Production Patterns: Event-driven updates, tag detection, property iteration
- Plugin Architecture: File organization, settings, error handling, testing
- Common Pitfalls: Validation errors, query issues, property dereferencing
When to Use This Skill
Use this skill when developing Logseq plugins that:
- Work with DB graphs (not markdown graphs)
- Need to create/manage tags and properties programmatically
- Respond to database changes in real-time (DB.onChanged)
- Query the graph database with Datalog
- Handle complex tag detection or property iteration
- Require production-ready architecture patterns
Key Differences: DB vs. Markdown Plugins
| Aspect | Markdown Graphs | DB Graphs |
|---|
| Data Storage | Files (.md) | Database (SQLite) |
| Properties | YAML frontmatter | Typed database entities |
| Tags | Simple text markers | Classes with schemas |
| Queries | File-based attributes | Datalog / Database relationships |
| Property Access | Text parsing | Namespaced keys (:user.property/name) |
Prerequisites
- Logseq: 0.11.0+ (for full DB graph support)
- @logseq/libs: 0.3.0+ (minimum for DB graphs)
- Node.js: 18+ recommended
- Build tools: Vite + vite-plugin-logseq
Layer 1: Authoritative Upstream Docs
Precedence: Layer 1 is authoritative ground truth for API contracts. Layer 2 adds production-validated context and patterns not covered by official docs. When they conflict, Layer 1 wins on API facts; Layer 2 wins on real-world pitfalls (things that work on paper but fail in practice).
Source: mirrored verbatim from logseq/logseq libs/development-notes/ via scripts/sync-logseq-docs.sh. Each file carries a footer recording upstream commit SHA and fetch timestamp. License: AGPL-3.0 (see references/logseq-official/LICENSE).
| File | Covers |
|---|
references/logseq-official/AGENTS.md | AI-agent development guide — SDK repo structure, core patterns, conventions |
references/logseq-official/starter_guide.md | Plugin setup walkthrough: Node/TypeScript install, Logseq dev environment, hello world |
references/logseq-official/db_properties_skill.md | DB properties SDK reference — schema definition, tags-as-classes, property operations |
references/logseq-official/db_properties_guide.md | File graph vs DB graph properties — text vs typed entities, SDK API differences |
references/logseq-official/db_query_guide.md | Datascript query guide — logseq.DB.q, datascriptQuery, parameterized Datalog |
references/logseq-official/db_tag_property_idents_notes.md | Ident system — namespace conventions (:logseq.property/, :plugin.property.*), when idents apply |
references/logseq-official/experiments_api_guide.md | logseq.Experiments — React integration, custom renderers, script loading, ClojureScript interop |
Refresh: bash scripts/sync-logseq-docs.sh from repo root. Idempotent — no-op if upstream HEAD matches .last-synced-sha.
Layer 2: Production Patterns
Battle-tested code from real-world plugin development. All patterns validated through logseq-checklist v1.0.0.
Unique contributions (not in official docs)
Tag Detection — Reliable multi-layered detection
Three-tier approach (content → datascript → properties) for maximum reliability when block.properties.tags fails.
Search for: hasTag, block.properties.tags undefined, multi-layered
Pitfalls & Solutions — Errors and fixes discovered in production
Tag creation validation, property conflicts, query syntax mistakes, or-join variable mismatches, method-name errors.
Search for: validation errors, query returns no results, addTag not a function
Supplementary (may overlap with Layer 1 — cross-linked where relevant)
Event Handling — DB.onChanged patterns
Database change detection, datom filtering, debouncing strategies. Essential for plugins that maintain derived state.
Search for: DB.onChanged, debouncing, transaction datoms
Property Management — Reading property values
Iteration patterns for unknown property names, type-based detection, namespaced key access.
Search for: property iteration, namespaced keys, :user.property/
Core APIs — Essential methods
Tag/class management, page/block creation, property operations, icons, utilities.
Search for: createTag, addBlockTag, upsertProperty, createPage
Queries and Database — Datalog patterns
Query syntax, common patterns, caching strategies, tag inheritance with or-join, :block/title vs :block/name.
Search for: datascriptQuery, datalog, caching, or-join, tag inheritance
Plugin Architecture — Best practices
File organization, settings registration, error handling, testing strategy, deployment checklist.
Search for: file organization, settings schema, production patterns
Layer 3: Related Skills
For specialized concerns, defer to sibling skills with their own activation triggers:
| Skill | Use for |
|---|
logseq-schema (RCmerci) | Authoritative Datascript schema reference when writing Datalog queries — covers entity attributes, relationships, cardinality. Install from github.com/RCmerci/skills. |
logseq-electron-debug (RCmerci) | Chrome DevTools against a running Logseq app — useful when debugging your plugin's runtime behavior. Install from github.com/RCmerci/skills. |
logseq-db-knowledge | Foundational DB graph concepts — use alongside this skill for understanding why DB graphs work the way they do. |
logseq-cli-skill | Logseq CLI usage — Datalog queries run from shell, useful for bulk operations outside plugins. |
Quick Start
1. Project Setup
mkdir my-logseq-plugin
cd my-logseq-plugin
pnpm init
pnpm add @logseq/libs
pnpm add -D typescript vite vite-plugin-logseq @types/node
mkdir src
2. Essential Files
src/index.ts — Entry point:
import '@logseq/libs'
async function main() {
console.log('Plugin loaded')
}
logseq.ready(main).catch(console.error)
vite.config.ts:
import { defineConfig } from 'vite'
import logseqDevPlugin from 'vite-plugin-logseq'
export default defineConfig({
plugins: [logseqDevPlugin()],
build: { target: 'esnext', minify: 'esbuild', sourcemap: true }
})
package.json:
{
"name": "my-logseq-plugin",
"version": "0.0.1",
"main": "dist/index.js",
"scripts": { "build": "vite build", "dev": "vite build --watch" },
"logseq": { "id": "my-logseq-plugin", "title": "My Logseq Plugin", "main": "dist/index.html" }
}
3. Development Workflow
pnpm run dev
pnpm run build
Core Concepts
Property Storage
Properties in DB graphs are stored as namespaced keys on block objects:
const block = await logseq.Editor.getBlock(uuid)
const value = block[':user.property/myProperty']
for (const [key, value] of Object.entries(block)) {
if (key.startsWith(':user.property/')) { }
}
CRITICAL: block.properties.tags and block.properties[name] are often unreliable. Use direct key access or iteration instead.
Tag Detection
Simple property checks fail. Use multi-layered detection — see references/tag-detection.md for the full pattern.
if (block.content.includes('#mytag')) return true
const results = await logseq.DB.datascriptQuery(
`[:find (pull ?b [*]) :where [?b :block/tags ?t] [?t :block/title "mytag"]]`
)
if (block.properties?.tags?.includes('mytag')) return true
Event-Driven Updates
For plugins that maintain derived state:
if (logseq.DB?.onChanged) {
logseq.DB.onChanged((changeData) => {
const { txData } = changeData
for (const [entityId, attribute, value, txId, added] of txData) {
if (attribute.includes('property')) scheduleUpdate(entityId)
}
})
}
See references/event-handling.md for debouncing strategies.
Property Type Definition
Always define property types before using them:
await logseq.Editor.upsertProperty('title', { type: 'string' })
await logseq.Editor.upsertProperty('year', { type: 'number' })
await logseq.Editor.upsertProperty('published', { type: 'checkbox' })
await logseq.Editor.upsertProperty('modifiedAt', { type: 'datetime' })
await logseq.Editor.createPage('Item', {
title: 'My Item',
year: 2024,
published: true,
modifiedAt: Date.now()
})
Essential Workflows
Creating Tagged Pages with Properties
const tag = await logseq.Editor.createTag('zot')
await logseq.Editor.upsertProperty('title', { type: 'string' })
await logseq.Editor.upsertProperty('author', { type: 'string' })
await logseq.Editor.upsertProperty('year', { type: 'number' })
const parentLogseq = (window as any).parent?.logseq
await parentLogseq.api.add_tag_property(tag.uuid, 'title')
await parentLogseq.api.add_tag_property(tag.uuid, 'author')
await parentLogseq.api.add_tag_property(tag.uuid, 'year')
await logseq.Editor.createPage('My Item', {
tags: ['zot'],
title: 'Paper Title',
author: 'Jane Doe',
year: 2024
})
Querying Tagged Items
const query = `
{:query [:find (pull ?b [*])
:where
[?b :block/tags ?t]
[?t :block/title "zot"]]}
`
const results = await logseq.DB.datascriptQuery(query)
Tag Hierarchies (items tagged with #task OR any tag extending #task):
const query = `
{:query [:find (pull ?b [*])
:where
(or-join [?b]
(and [?b :block/tags ?t]
[?t :block/title "task"])
(and [?b :block/tags ?child]
[?child :logseq.property.class/extends ?parent]
[?parent :block/title "task"]))]}
`
See references/queries-and-database.md for advanced patterns.
Responding to Database Changes
const pendingUpdates = new Set<string>()
let updateTimer: NodeJS.Timeout | null = null
function handleDatabaseChanges(changeData: any): void {
const txData = changeData?.txData || []
for (const [entityId, attribute, value, txId, added] of txData) {
if (attribute.includes('property')) {
pendingUpdates.add(String(entityId))
if (updateTimer) clearTimeout(updateTimer)
updateTimer = setTimeout(async () => {
for (const id of pendingUpdates) await updateBlock(id)
pendingUpdates.clear()
}, 300)
}
}
}
Architecture Recommendations
File Structure:
src/
├── index.ts # Entry point, initialization
├── events.ts # DB.onChanged handlers, debouncing
├── logic.ts # Pure business logic (testable)
├── settings.ts # Settings schema and accessors
└── types.ts # TypeScript interfaces
Settings Registration:
import { SettingSchemaDesc } from '@logseq/libs/dist/LSPlugin.user'
const settings: SettingSchemaDesc[] = [
{
key: 'tagName',
type: 'string',
title: 'Tag Name',
description: 'Tag to monitor',
default: 'mytag'
}
]
logseq.useSettingsSchema(settings)
See references/plugin-architecture.md for error handling, testing, and deployment.
Common Mistakes to Avoid
- Wrong method names: Use
addBlockTag() not addTag()
- Property access: Don't rely on
block.properties.tags — iterate namespaced keys
- Query syntax: Use
:block/title not :db/ident for custom tags
- Type definition: Define property types before using them
- Reserved names: Avoid
created, modified — use dateAdded, dateModified
- Date format: Use
YYYY-MM-DD for date properties
- Entity references: Use Datalog queries to dereference, not
getPage()
See references/pitfalls-and-solutions.md for detailed solutions.
Version Requirements
- Logseq: 0.11.0+ (for full DB graph support)
- @logseq/libs: 0.3.0+ (minimum for DB graphs), 0.2.8+ recommended
- Graph type: Database graphs only (not markdown/file-based graphs)
Getting Help
When encountering issues:
- Check Layer 1 first — official upstream docs are authoritative for API contracts
- Check Common Pitfalls (references/pitfalls-and-solutions.md) — production-observed gotchas not in official docs
- Search Reference Files — grep patterns listed above
- Check logseq-checklist source — real working implementation
- DevTools Console — Cmd/Ctrl+Shift+I for runtime errors
- Invoke
logseq-electron-debug skill (RCmerci) — for debugging Logseq itself
Summary
Three layers, in order of priority:
- Layer 1 — Official upstream docs (ground truth for API contracts)
- Layer 2 — Production patterns (tag-detection + pitfalls are unique contributions; others supplement Layer 1)
- Layer 3 — Related skills (logseq-schema, logseq-electron-debug, logseq-db-knowledge, logseq-cli-skill)
Load the files you need for the current task. Layer 1 answers "what does the API do"; Layer 2 answers "what breaks in practice"; Layer 3 answers adjacent concerns that deserve their own skill activation.