skills/c0ntr0lledcha0s/building-logseq-plugins/SKILL.md
Expert guidance for building Logseq plugins compatible with the new DB architecture. Auto-invokes when users want to create Logseq plugins, work with the Logseq Plugin API, extend Logseq functionality, or need help with plugin development for DB-based graphs. Covers plugin structure, API usage, and DB-specific considerations.
npx skillsauth add aiskillstore/marketplace building-logseq-pluginsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill auto-invokes when:
You are an expert in Logseq plugin development, with special focus on DB-version compatibility.
Logseq plugins run in sandboxed iframes and communicate with the main app via the Plugin API.
my-logseq-plugin/
├── package.json # Plugin manifest
├── index.html # Entry point
├── index.js # Main logic (or TypeScript)
├── icon.png # Plugin icon (optional)
└── README.md # Documentation
{
"name": "logseq-my-plugin",
"version": "1.0.0",
"main": "index.html",
"logseq": {
"id": "my-plugin-id",
"title": "My Plugin",
"icon": "./icon.png",
"description": "Plugin description"
}
}
import '@logseq/libs'
async function main() {
console.log('Plugin loaded')
// Register commands, settings, etc.
logseq.Editor.registerSlashCommand('My Command', async () => {
// Command logic
})
}
logseq.ready(main).catch(console.error)
| Namespace | Purpose |
|-----------|---------|
| logseq.Editor | Block/page manipulation |
| logseq.DB | Database queries |
| logseq.App | App-level operations |
| logseq.UI | UI components |
| logseq.Settings | Plugin settings |
// Get block with properties (DB version)
const block = await logseq.Editor.getBlock(blockUuid, {
includeChildren: true
})
// Properties are structured differently in DB version
// Access via block.properties object
const author = block.properties?.author
// Set property value
await logseq.Editor.upsertBlockProperty(blockUuid, 'author', 'John Doe')
// Get blocks with a specific tag/class
const books = await logseq.DB.datascriptQuery(`
[:find (pull ?b [*])
:where
[?b :block/tags ?t]
[?t :block/title "Book"]]
`)
// Add tag to block
await logseq.Editor.upsertBlockProperty(blockUuid, 'tags', ['Book', 'Fiction'])
// New APIs for DB version
await logseq.Editor.getBlockProperties(blockUuid)
await logseq.Editor.setBlockProperties(blockUuid, {
author: 'Jane Doe',
rating: 5,
published: '2024-01-15'
})
const results = await logseq.DB.datascriptQuery(`
[:find ?title
:where
[?p :block/title ?title]
[?p :block/tags ?t]
[?t :db/ident :logseq.class/Page]]
`)
const results = await logseq.DB.datascriptQuery(`
[:find (pull ?b [*])
:in $ ?tag-name
:where
[?b :block/tags ?t]
[?t :block/title ?tag-name]]
`, ['Book'])
// MD version - file-based queries
const mdQuery = `
[:find ?content
:where
[?b :block/content ?content]
[?b :block/page ?p]
[?p :block/name "my-page"]]
`
// DB version - entity-based queries
const dbQuery = `
[:find ?title
:where
[?b :block/title ?title]
[?b :block/tags ?t]
[?t :block/title "My Tag"]]
`
logseq.Editor.registerSlashCommand('Insert Book Template', async () => {
await logseq.Editor.insertAtEditingCursor(`
- [[New Book]] #Book
author::
rating::
status:: To Read
`)
})
logseq.Editor.registerBlockContextMenuItem('Convert to Task', async (e) => {
const block = await logseq.Editor.getBlock(e.uuid)
await logseq.Editor.upsertBlockProperty(e.uuid, 'tags', ['Task'])
await logseq.Editor.upsertBlockProperty(e.uuid, 'status', 'Todo')
})
logseq.useSettingsSchema([
{
key: 'apiKey',
type: 'string',
title: 'API Key',
description: 'Your API key for the service',
default: ''
},
{
key: 'enableFeature',
type: 'boolean',
title: 'Enable Feature',
default: true
},
{
key: 'theme',
type: 'enum',
title: 'Theme',
enumChoices: ['light', 'dark', 'auto'],
default: 'auto'
}
])
When building plugins for DB version:
:block/title instead of :block/content for page namesasync function isDBGraph() {
// Check if current graph is DB-based
const graph = await logseq.App.getCurrentGraph()
return graph?.name?.includes('db-') || graph?.type === 'db'
}
async function main() {
const isDB = await isDBGraph()
if (isDB) {
// DB-specific initialization
} else {
// MD-specific initialization
}
}
function formatPropertyValue(value, type) {
switch (type) {
case 'date':
return new Date(value).toISOString().split('T')[0]
case 'number':
return Number(value)
case 'checkbox':
return Boolean(value)
case 'node':
return `[[${value}]]`
default:
return String(value)
}
}
npm run dev for hot reloadnpm run build for productionLogseq > Settings > Advanced > Developer Mode: ON
Logseq > Plugins > Load unpacked plugin > Select folder
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.