### Install and Run Development Server
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-imdb-top250-importer/README.md
Install project dependencies and start the Vite development server for live preview. This is used for developing the Logseq plugin.
```bash
npm install # or yarn install
npm run dev # or yarn run dev
```
--------------------------------
### Install and Build Plugin
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-awesome-fonts/README.md
Install dependencies and build the plugin using npm. This is a prerequisite for loading the plugin.
```bash
npm install && npm run build
```
--------------------------------
### Development Build Command
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Command to install dependencies and start the development server for a Logseq plugin. Assumes a build tool like Vite or Rollup is configured.
```bash
cd logseq-plugin-name
npm install
npm run dev
```
--------------------------------
### Example: Insert Template Slash Command
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
An example of registering a slash command to insert a predefined daily template into the current editing block.
```javascript
logseq.Editor.registerSlashCommand('📋 Daily Template', async () => {
const template = `
## Morning
- [ ] Review goals
## Evening
- [ ] Reflect on day
`
await logseq.Editor.insertAtEditingCursor(template)
})
```
--------------------------------
### Pomodoro Timer Macro Renderer
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Example of a macro renderer that displays a start button or a timer based on whether the pomodoro has started. It uses `logseq.provideUI` to render the button or timer.
```javascript
logseq.App.onMacroRendererSlotted(({ slot, payload }) => {
const [type, startTime, durationMins] = payload.arguments
if (type?.startsWith(':pomodoro_')) {
const identity = type.split('_')[1].trim()
const pomoId = 'pomodoro-timer-start_' + identity
if (!startTime?.trim()) {
// Not started - show START button
logseq.provideUI({
key: pomoId,
slot,
reset: true,
template: "`
`"
})
} else {
// Started - show timer
renderTimer({
pomoId,
slotId: slot,
startTime,
durationMins
})
}
}
})
```
--------------------------------
### Example: Pin Block Context Menu Action
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
An example of registering a context menu item to pin or unpin a block by adding/removing a 'pinned' property.
```javascript
logseq.Editor.registerBlockContextMenuItem('📌 Pin Block', ({ blockId }) => {
logseq.Editor.getBlock(blockId).then(block => {
if (block?.properties?.pinned) {
logseq.App.showMsg('Already pinned')
} else {
logseq.Editor.upsertBlockProperty(blockId, 'pinned', true)
logseq.App.showMsg('Block pinned!')
}
})
})
```
--------------------------------
### Example: Data Fetching Slash Command
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Demonstrates registering a slash command that fetches data from a user-provided URL and inserts a formatted link into the current editing block.
```javascript
logseq.Editor.registerSlashCommand('🔗 Fetch URL', async () => {
const url = prompt('Enter URL:')
if (!url) return
const response = await fetch(url)
const title = response.headers.get('content-type')
await logseq.Editor.insertAtEditingCursor(`[${url}](${url})`)
})
```
--------------------------------
### Access and Update Plugin Settings
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Access the current plugin settings and update them using `logseq.updateSettings()`. This example shows how to read settings and listen for changes.
```javascript
const [settings, setSettings] = useState(logseq.settings)
useEffect(() => {
logseq.on('settings:changed', (a) => {
setSettings(a)
})
}, [])
return (
)
```
--------------------------------
### Logseq Plugin: Async Data Loading and UI Setup
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Initialization pattern for Logseq plugins that involves asynchronous data loading before setting up the UI and providing a model. Includes updating settings with new data.
```javascript
async function main() {
// Load data
const data = await fetchPluginData()
// Set up UI with data
logseq.provideUI({
key: 'dashboard',
template: renderDashboard(data)
})
// Register model with data access
logseq.provideModel({
updateData: async () => {
const newData = await fetchPluginData()
logseq.updateSettings({ cachedData: newData })
}
})
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Svelte Plugin Entry Point
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Example of a Svelte component used as a Logseq plugin entry point. It registers a UI item in the toolbar and sets up the main UI.
```typescript
import "@logseq/libs"
import App from "./App.svelte"
function createModel() {
return {
openQueryPlayground() {
logseq.showMainUI()
}
}
}
function main() {
new App({
target: document.querySelector("#app")
})
logseq.setMainUIInlineStyle({
zIndex: 11
})
logseq.App.registerUIItem('toolbar', {
key: "open-query-playground",
template: `🗄`
})
}
logseq.ready(createModel()).then(main).catch(console.error)
```
--------------------------------
### Render React App at Document Root
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md
Demonstrates mounting a React application to the '#app' element, which is typically at the document root. This setup is suitable for complex UI frameworks and includes registering a toolbar item to toggle the main UI.
```javascript
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
let reactRoot = null
function mountApp() {
const el = document.getElementById('app')
if (!el) return
if (!reactRoot) {
reactRoot = createRoot(el)
}
reactRoot.render()
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', mountApp)
} else {
mountApp()
}
function main() {
logseq.App.registerUIItem('toolbar', {
key: 'my-plugin',
template: '🎨'
})
logseq.provideModel({
toggle() {
logseq.toggleMainUI()
}
})
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Vue Plugin with UI Integration
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Demonstrates integrating a Vue application into a Logseq plugin. This example shows how to mount a Vue app and register a UI item in the toolbar to trigger a UI action.
```javascript
import '@logseq/libs'
import { createApp } from 'vue'
import App from './App.vue'
function createModel() {
return {
openCalendar() {
logseq.showMainUI()
}
}
}
function main() {
logseq.setMainUIInlineStyle({
position: 'fixed',
zIndex: 11
})
logseq.App.registerUIItem('toolbar', {
key: 'open-calendar',
template: '📅'
})
// Mount Vue app to #app element
createApp(App).mount('#app')
}
logseq.ready(createModel()).then(main).catch(console.error)
```
--------------------------------
### Preact Plugin Entry Point
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Example of a Preact component used as a Logseq plugin entry point. It registers a UI item in the toolbar and provides a model for UI interaction.
```javascript
import '@logseq/libs'
import { h, render } from 'preact'
import { useState, useEffect } from 'preact/hooks'
function App(props) {
const [count, setCount] = useState(0)
return (
)
}
function main() {
const doc = document
render(, doc.querySelector('#app'))
logseq.provideModel({
showPanel() {
logseq.toggleMainUI()
}
})
logseq.App.registerUIItem('toolbar', {
key: 'my-btn',
template: '🎨'
})
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Create and Get Tag
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md
Demonstrates creating a new tag and retrieving an existing tag by its name. Useful for managing tags within Logseq.
```javascript
const movieTag = await logseq.Editor.createTag('movie')
const existingTag = await logseq.Editor.getTag('important')
```
--------------------------------
### Logseq Plugin Initialization Error Handling
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Example of robust error handling for Logseq plugin initialization. Logs errors to the console and displays a message to the user if loading fails.
```javascript
logseq.ready(main).catch(error => {
console.error('Plugin initialization failed:', error)
logseq.App.showMsg('Failed to load plugin', 'error')
})
```
--------------------------------
### Real-time Counter Macro Renderer
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
This example demonstrates a real-time counter using a macro renderer. It utilizes `localStorage` to store and update the count, and `logseq.provideUI` to render the counter and increment button. The UI updates automatically when the model's `increment` function is called.
```javascript
logseq.App.onMacroRendererSlotted(({ slot, payload }) => {
const [type] = payload.arguments
if (!type?.startsWith(':counter_')) return
const counterId = type.split('_')[1]
const key = `counter-${counterId}`
function render() {
const count = localStorage.getItem(key) || '0'
logseq.provideUI({
key,
slot,
reset: true,
template: "`
${count}
`"
})
}
render()
})
```
```javascript
logseq.provideModel({
increment({ dataset }) {
const counterId = dataset.counterId
const key = `counter-${counterId}`
const count = parseInt(localStorage.getItem(key) || '0') + 1
localStorage.setItem(key, count)
// UI re-renders automatically
}
})
```
--------------------------------
### React Plugin with State Management
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Example of a Logseq plugin built with React, demonstrating state management using useState and rendering a button that updates a count. Ensure React and ReactDOM are correctly set up for the plugin environment.
```typescript
import React from 'react'
import { createRoot } from 'react-dom/client'
import '@logseq/libs'
const App: React.FC = () => {
const [count, setCount] = React.useState(0)
return
}
let reactRoot: Root | null = null
function mountAppIfNeeded() {
const el = document.getElementById('app')
if (!el) return
if (!reactRoot) {
reactRoot = createRoot(el)
}
reactRoot.render()
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => mountAppIfNeeded())
} else {
mountAppIfNeeded()
}
function main() {
logseq.App.registerUIItem('toolbar', {
key: 'my-plugin',
template: '🎨'
})
logseq.provideModel({
toggleUI() {
logseq.toggleMainUI()
}
})
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### API Reference
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/MANIFEST.txt
Provides access to the complete API documentation, including method signatures, parameter tables, return types, usage examples, and source file references.
```APIDOC
## API Reference
This section provides comprehensive documentation for the Logseq plugin API. It includes detailed information on all public APIs, method signatures, parameter tables, return types, usage examples, and source file references with line numbers.
### Key Documentation Files:
- **logseq-api.md**: Contains the complete API documentation.
- **editor-operations.md**: Details block and page operations.
- **ui-management.md**: Covers UI rendering functionalities.
- **plugin-entry-points.md**: Provides patterns for plugin bootstrapping.
### Type Reference:
- **types.md**: Lists and describes all core and custom types used within the Logseq API, including blocks, pages, tags, properties, event types, and configuration types.
```
--------------------------------
### Theme Plugin Manifest Configuration
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Example JSON snippet for the 'package.json' file, defining theme properties for a Logseq theme plugin. Specifies theme name, CSS URL, description, and mode.
```json
{
"logseq": {
"themes": [
{
"name": "base16-default-dark",
"url": "./css/base16-default-dark.css",
"description": "/* Base16 Default Dark theme */",
"mode": "dark"
}
]
}
}
```
--------------------------------
### Create Tag in Logseq
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Creates a new tag with an optional set of properties. The example shows how to create a 'movie' tag and log its UUID if successful.
```typescript
const tag = await logseq.Editor.createTag(tagName, properties)
// Example: Create 'movie' tag
const movieTag = await logseq.Editor.createTag('movie')
if (movieTag?.uuid) {
console.log('Tag created:', movieTag.uuid)
}
```
--------------------------------
### Register Block Context Menu Items
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
Add custom items to the block context menu for specific actions. This example shows how to pin a block and copy its link.
```javascript
logseq.Editor.registerBlockContextMenuItem(
'📌 Pin Block',
async ({ blockId }) => {
const block = await logseq.Editor.getBlock(blockId)
if (block?.properties?.pinned) {
logseq.App.showMsg('Already pinned', 'warning')
return
}
await logseq.Editor.upsertBlockProperty(blockId, 'pinned', true)
logseq.App.showMsg('Block pinned!', 'success')
}
)
logseq.Editor.registerBlockContextMenuItem(
'🔗 Share Link',
async ({ blockId }) => {
const block = await logseq.Editor.getBlock(blockId)
const link = `logseq://block/${block.uuid}`
if (navigator.clipboard) {
await navigator.clipboard.writeText(link)
logseq.App.showMsg('Link copied!', 'success')
}
}
)
```
--------------------------------
### Complete Block Workflow in Logseq
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Demonstrates how to insert, update, and retrieve block details using the Logseq Editor API. Also shows how to get the currently active editing block.
```javascript
// Insert a new block after current
const newBlock = await logseq.Editor.insertBlock(
currentBlockUuid,
'New block content',
{ before: false, sibling: true }
)
// Update existing block
await logseq.Editor.updateBlock(blockUuid, 'Updated content')
// Get block details
const block = await logseq.Editor.getBlock(blockUuid)
console.log(block.uuid, block.content, block.properties)
// Get current editing block
const current = await logseq.Editor.getCurrentBlock()
```
--------------------------------
### Register Toolbar Button
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md
Register a UI item to the Logseq toolbar using `logseq.App.registerUIItem`. This example shows how to add a button with an icon and attach a click handler.
```typescript
logseq.App.registerUIItem(
'toolbar',
{
key: 'awesome-fonts-btn',
template: (
``
)
}
)
logseq.provideModel({
openFontsPanel(e) {
const { rect } = e
logseq.setMainUIInlineStyle({
top: `${rect.top + 20}px`,
left: `${rect.right - 10}px`
})
logseq.toggleMainUI()
}
})
```
--------------------------------
### Render Macro with Parameters and Actions
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
Handles macros that accept parameters like duration and task name, and provides a button to trigger model actions. The macro type should start with ':timer_'.
```javascript
logseq.App.onMacroRendererSlotted(({ slot, payload }) => {
const [type, duration, taskName] = payload.arguments
if (!type?.startsWith(':timer_')) return
const timerId = type.split('_')[1]
logseq.provideUI({
key: `timer-${timerId}`,
slot,
reset: true,
template: `
Task: ${taskName}
Duration: ${duration} minutes
`
})
})
logseq.provideModel({
startTimer({ dataset }) {
const timerId = dataset.timerId
// Start timer logic...
}
})
```
--------------------------------
### Initialize Plugin Settings with Defaults
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md
Initializes plugin settings with default values and demonstrates how to access them, providing fallbacks for undefined settings.
```javascript
// Initialize with default settings
function main() {
const defaults = {
googleFontFamily: 'Noto Serif SC',
contentWidthMode: 'normal',
zoomFactor: 100
}
// Settings available at logseq.settings
const currentFontFamily = logseq.settings?.googleFontFamily || defaults.googleFontFamily
}
```
--------------------------------
### logseq.ready() - Bootstrap
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/MANIFEST.txt
Initializes the plugin and provides access to the Logseq API once the application is ready. This is the primary entry point for plugin execution.
```APIDOC
## logseq.ready()
### Description
Bootstrap function to ensure the Logseq API is available before executing plugin code. It takes a callback function that will be executed once the Logseq application is ready.
### Method
Function Call
### Endpoint
N/A (JavaScript function)
### Parameters
#### Callback Function
- **callback** (function) - Required - The function to execute once Logseq is ready.
### Request Example
```javascript
logseq.ready(() => {
console.log('Logseq is ready!');
// Plugin initialization code here
}).catch(err => {
console.error('Error initializing plugin:', err);
});
```
### Response
#### Success Response
N/A (Executes callback)
#### Response Example
N/A
```
--------------------------------
### Initialize Plugin with Bootstrap
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Initializes the plugin using `logseq.ready`. The optional model parameter can provide event handlers and callback methods. This is the core entrypoint for all plugins.
```typescript
logseq.ready(model?: object): Promise
```
```javascript
import '@logseq/libs'
async function main() {
logseq.App.showMsg('Plugin loaded')
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Get Tag in Logseq
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Retrieves a tag by its name. This is typically used to check for the existence of a tag before creating it or to get its properties.
```javascript
const tag = await logseq.Editor.getTag('tagName')
if (tag?.uuid) {
// Tag exists, use it
logseq.App.pushState('page', { name: tag.uuid })
}
```
--------------------------------
### Build for Production
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-imdb-top250-importer/README.md
Compile the plugin for production deployment. This command bundles the application for distribution.
```bash
npm run build # or yarn run build
```
--------------------------------
### Retrieve and Apply User Configurations
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md
Fetches the user's configuration and applies a dark theme if the preferred theme mode is 'dark'. Demonstrates accessing and acting on user settings.
```javascript
const config = await logseq.App.getUserConfigs()
if (config.preferredThemeMode === 'dark') {
applyDarkTheme()
}
```
--------------------------------
### getEditingCursorPosition
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Gets the current editing cursor position and DOM rect. This is useful for positioning UI elements relative to the cursor.
```APIDOC
## getEditingCursorPosition
### Description
Gets the current editing cursor position and DOM rect.
### Method
GET (conceptual)
### Endpoint
logseq.Editor.getEditingCursorPosition()
### Return Type
```typescript
interface CursorPosition {
left: number
top: number
rect: DOMRect
}
```
### Example
```javascript
const { left, top, rect } = await logseq.Editor.getEditingCursorPosition()
// Position UI at cursor location
element.style.left = (left + rect.left) + 'px'
element.style.top = (top + rect.top) + 'px'
```
```
--------------------------------
### Render Simple Macro
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
Renders custom content for a simple macro based on its identity. Ensure the macro type starts with ':my-macro_'.
```javascript
logseq.App.onMacroRendererSlotted(({ slot, payload }) => {
const [type] = payload.arguments
if (!type?.startsWith(':my-macro_')) return
const identity = type.split('_')[1]
logseq.provideUI({
key: `my-macro-${identity}`,
slot,
reset: true,
template: `
Custom macro content
`
})
})
```
--------------------------------
### Get Current Page Blocks Tree
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Retrieves the block tree structure of the current page. This can be used to access and manipulate existing blocks.
```javascript
const blocks = await logseq.Editor.getCurrentPageBlocksTree()
const firstBlock = blocks[0]
await logseq.Editor.insertBlock(firstBlock.uuid, 'New content', { before: true })
```
--------------------------------
### Listen to Logseq Events
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
Demonstrates how to subscribe to various Logseq events, including settings changes, UI visibility, theme mode, text selection, and macro rendering. Ensure necessary functions like applySettings, initializeUI, cleanup, applyTheme, handleSelection, and renderMacro are defined elsewhere.
```javascript
// Settings change
logseq.on('settings:changed', (settings) => {
console.log('Settings updated:', settings)
applySettings(settings)
})
// UI visibility
logseq.on('ui:visible:changed', ({ visible }) => {
if (visible) {
initializeUI()
} else {
cleanup()
}
})
// Theme change
logseq.App.onThemeModeChanged(({ mode }) => {
applyTheme(mode)
})
// Text selection end
logseq.Editor.onInputSelectionEnd((e) => {
handleSelection(e.text, e.point)
})
// Macro rendering
logseq.App.onMacroRendererSlotted(({ slot, payload }) => {
renderMacro(slot, payload)
})
```
--------------------------------
### Get Editing Cursor Position
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Retrieves the current cursor position and its DOM rect. Useful for positioning UI elements relative to the cursor.
```javascript
const { left, top, rect } = await logseq.Editor.getEditingCursorPosition()
// Position UI at cursor location
element.style.left = (left + rect.left) + 'px'
element.style.top = (top + rect.top) + 'px'
```
--------------------------------
### Get Current Editing Block
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Retrieves the block that is currently being edited by the user. Returns an object containing the block's content and UUID.
```javascript
const { content, uuid } = await logseq.Editor.getCurrentBlock()
logseq.App.showMsg(`Block #${uuid}: ${content}`)
```
--------------------------------
### Logseq Ready Function
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-hello-world/README.md
The `ready` function is an entry point for plugins, often used to register callbacks or initialize plugin functionality when Logseq is ready.
```APIDOC
## `ready`
### Description
Initializes the plugin or registers a callback function to be executed when Logseq is ready.
### Signature
`ready(callback?: (e: any) => void | {}): Promise`
### Parameters
* `callback` (function | object) - Optional. A function to be called when Logseq is ready, or an object.
### Returns
A Promise that resolves with any relevant data upon completion.
```
--------------------------------
### Get Block by UUID
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Retrieves a specific block using its unique identifier (UUID). Returns the block object if found, otherwise returns null.
```javascript
const block = await logseq.Editor.getBlock(blockUuid)
if (block) {
const newContent = block.content.replace(/oldText/, 'newText')
await logseq.Editor.updateBlock(blockUuid, newContent)
}
```
--------------------------------
### Get Cursor Position
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Retrieves the current cursor's position within the editor. Useful for positioning UI elements like context menus.
```typescript
const position = await logseq.Editor.getEditingCursorPosition()
// Returns:
// {
// left: number, // X offset in editor
// top: number, // Y offset in editor
// rect: DOMRect // Editor container bounds
// }
```
```javascript
const { left, top, rect } = await logseq.Editor.getEditingCursorPosition()
logseq.provideUI({
key: 'my-popup',
template: '
Quick action menu
',
style: {
position: 'fixed',
left: (left + rect.left) + 'px',
top: (top + rect.top + 30) + 'px'
}
})
```
--------------------------------
### Configure Development Entry Point
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md
Set the `devEntry` in the `package.json` file to specify a URL for hot-reload development. This allows the plugin to load from a development server instead of built files.
```json
{
"logseq": {
"devEntry": "http://localhost:5173"
}
}
```
--------------------------------
### Create and Log New Page
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md
Creates a new page with a specified name and logs its name if the creation was successful. Demonstrates basic page creation workflow.
```javascript
const page = await logseq.Editor.createPage('My Notes')
if (page?.uuid) {
console.log('Created page:', page.name)
}
```
--------------------------------
### Get Cursor Position
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Retrieves the current editing cursor's position within the editor, including its X/Y coordinates and the bounding box of the editor container.
```APIDOC
## Get Cursor Position
### Description
Retrieves the current editing cursor position.
### Method
```typescript
const position = await logseq.Editor.getEditingCursorPosition()
```
### Response
#### Success Response
- **position** (object) - An object containing the cursor's position.
- **left** (number) - The X offset of the cursor within the editor.
- **top** (number) - The Y offset of the cursor within the editor.
- **rect** (DOMRect) - The bounding box of the editor container.
### Use Case
Position context menu or overlay at cursor
### Example: Show Popup at Cursor
```javascript
const { left, top, rect } = await logseq.Editor.getEditingCursorPosition()
logseq.provideUI({
key: 'my-popup',
template: '
Quick action menu
',
style: {
position: 'fixed',
left: (left + rect.left) + 'px',
top: (top + rect.top + 30) + 'px'
}
})
```
```
--------------------------------
### Get and Walk Current Page Blocks Tree in Logseq
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
Retrieves all blocks from the current page as a tree structure and provides a function to recursively traverse and process them.
```javascript
const blocks = await logseq.Editor.getCurrentPageBlocksTree()
// Walk the tree structure
function walkBlocks(blocks, depth = 0) {
blocks.forEach(block => {
console.log(' '.repeat(depth) + block.content)
if (block.children?.length) {
walkBlocks(block.children, depth + 1)
}
})
}
walkBlocks(blocks)
```
--------------------------------
### Import Item with Multiple Properties
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
This pattern demonstrates creating a Logseq page for an item and populating it with various properties, including simple key-value pairs and references to other pages.
```javascript
async function importMovie(movie) {
// Create page
const page = await logseq.Editor.createPage(
movie.title,
{},
{ createFirstBlock: true }
)
if (!page?.uuid) {
throw new Error(`Failed to create page: ${movie.title}`)
}
try {
// Tag the page
await logseq.Editor.addBlockTag(page.uuid, 'movie')
// Simple properties
await logseq.Editor.upsertBlockProperty(page.uuid, 'cover', movie.image || '')
await logseq.Editor.upsertBlockProperty(page.uuid, 'url', movie.url || '')
await logseq.Editor.upsertBlockProperty(page.uuid, 'rating', movie.rating || 0)
// Create related pages for references
const directorPages = []
if (movie.directors?.length) {
for (const directorName of movie.directors) {
const directorPage = await logseq.Editor.createPage(directorName)
if (directorPage?.uuid) {
await logseq.Editor.addBlockTag(directorPage.uuid, 'director')
directorPages.push(directorPage)
}
}
}
// Link references
if (directorPages.length) {
await logseq.Editor.upsertBlockProperty(
page.uuid,
'director',
directorPages.map(p => p.id),
{ reset: true }
)
}
// Add description as content
await logseq.Editor.appendBlockInPage(page.uuid, movie.description)
return page
} catch (error) {
console.error(`Failed to import ${movie.title}:`, error)
throw error
}
}
```
--------------------------------
### provideUI
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Provides dynamic UI content, allowing plugins to replace or create UI elements. It requires a configuration object with a key, and optionally accepts a slot, template, and reset flag.
```APIDOC
## provideUI
### Description
Provides dynamic UI content (replaces or creates UI).
### Method
void
### Endpoint
logseq.provideUI(config: UIConfig)
### Parameters
#### Request Body
- **config.key** (string) - Required - Unique identifier for this UI
- **config.slot** (string) - Optional - Renderer slot name
- **config.template** (string) - Required - HTML template
- **config.reset** (boolean) - Optional - If true, clear previous content
### Request Example
```javascript
logseq.provideUI({
key: 'my-overlay',
template: `
Hello from plugin
`,
reset: true
})
```
### Response
None
```
--------------------------------
### Popup at Cursor Position on Selection End
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
Display a popup near the cursor when text selection ends. This example shows how to capture selected text and display it in a custom UI.
```javascript
logseq.Editor.onInputSelectionEnd((e) => {
const { x, y } = e.point
const selectedText = e.text
logseq.provideUI({
key: 'selection-popup',
template: `
${selectedText}
Translation: ...
`,
style: {
position: 'fixed',
left: x + 'px',
top: y + 30 + 'px',
zIndex: '1000',
backgroundColor: 'var(--ls-primary-background-color)',
color: 'var(--ls-primary-text-color)',
padding: '10px',
borderRadius: '4px'
}
})
logseq.showMainUI()
})
```
--------------------------------
### logseq.ready
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Initializes the plugin. The optional model parameter provides event handlers and callback methods that can be invoked from UI templates.
```APIDOC
## logseq.ready
### Description
Initializes the plugin. The optional model parameter provides event handlers and callback methods.
### Method
```typescript
logseq.ready(model?: object): Promise
```
### Parameters
#### Path Parameters
- **model** (object) - Optional - Object containing methods callable from UI templates via `data-on-click`
### Request Example
```javascript
import '@logseq/libs'
async function main() {
logseq.App.showMsg('Plugin loaded')
}
logseq.ready(main).catch(console.error)
```
### Source
Core entrypoint, used in all samples
```
--------------------------------
### Simple Function-based Plugin Initialization
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Initializes a plugin using a simple async function and displays a message. Wrap the call with .catch(console.error) for robust error handling.
```javascript
import '@logseq/libs'
async function main() {
logseq.App.showMsg('Plugin initialized!')
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Get and Use Editing Cursor Position
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md
Retrieves the current editing cursor's position and dimensions, then uses these values to style an element. Useful for UI elements that follow the cursor.
```javascript
const { left, top, rect } = await logseq.Editor.getEditingCursorPosition()
element.style.left = (left + rect.left) + 'px'
element.style.top = (top + rect.top) + 'px'
```
--------------------------------
### Full package.json Configuration for Logseq Plugin
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md
Includes all available configuration options in package.json for a Logseq plugin, such as development server entry point, icon, and repository URL.
```json
{
"name": "logseq-plugin-example",
"version": "0.0.1",
"main": "index.html",
"logseq": {
"id": "logseq-plugin-example",
"title": "Example Plugin",
"description": "A sample plugin",
"author": "author name",
"version": "0.0.1",
"minAppVersion": "0.9.0",
"devEntry": "http://localhost:5173",
"icon": "icon.png",
"repo": "https://github.com/user/repo",
"themes": []
}
}
```
--------------------------------
### Logseq Plugin with Settings Persistence
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
This plugin demonstrates how to load default settings, merge them with user-defined preferences, and react to setting changes. It also includes a toolbar button to open a settings UI.
```javascript
import '@logseq/libs'
function main() {
// Load default settings
const defaults = {
fontSize: 14,
darkMode: false
}
const settings = {
...defaults,
...logseq.settings
}
// Watch for setting changes
logseq.on('settings:changed', (newSettings) => {
applySettings(newSettings)
})
// UI for changing settings
logseq.App.registerUIItem('toolbar', {
key: 'settings-btn',
template: '⚙️'
})
logseq.provideModel({
openSettings() {
logseq.showMainUI()
}
})
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Vanilla JavaScript Plugin DOM Manipulation
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
A basic plugin example using vanilla JavaScript to directly manipulate the DOM. This is suitable for plugins that primarily interact with the page's structure.
```javascript
import '@logseq/libs'
function main() {
// Direct DOM access
const app = document.getElementById('app')
const button = document.createElement('button')
button.textContent = 'Click me'
app.appendChild(button)
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Logseq Plugin Bootstrap Pattern
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/OVERVIEW.md
This is the basic structure for all Logseq plugins, demonstrating the entry point and initialization process.
```javascript
async function main() {
// Initialize plugin
// Register commands, handlers, UI items
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Minimal Logseq Plugin Initialization
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md
The simplest Logseq plugin structure. It loads the necessary libraries and displays a message upon successful initialization.
```javascript
import '@logseq/libs'
function main() {
logseq.App.showMsg('Plugin loaded')
}
logseq.ready(main).catch(console.error)
```
--------------------------------
### Get User Configuration Settings
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Retrieves the user's current Logseq configuration settings, including preferred theme mode. This is useful for adapting plugin behavior based on user preferences.
```typescript
const config = await logseq.App.getUserConfigs()
if (config.preferredThemeMode === 'dark') {
// Apply dark theme
}
```
--------------------------------
### Portal-Based UI Rendering
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md
Demonstrates how to render complex UI applications (React, Vue, Svelte) into a specific DOM element, typically the '#app' element, for root-level rendering.
```APIDOC
## Portal-Based UI Rendering
### Description
For complex React/Vue/Svelte applications, this pattern allows rendering your UI directly to a designated DOM element, such as `#app`, enabling root-level rendering.
### Example: Rendering React App
```javascript
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
let reactRoot = null
function mountApp() {
const el = document.getElementById('app')
if (!el) return
if (!reactRoot) {
reactRoot = createRoot(el)
}
reactRoot.render()
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', mountApp)
} else {
mountApp()
}
function main() {
logseq.App.registerUIItem('toolbar', {
key: 'my-plugin',
template: '🎨'
})
logseq.provideModel({
toggle() {
logseq.toggleMainUI()
}
})
}
logseq.ready(main).catch(console.error)
```
### Key Concepts
- **`mountApp()`**: Function to find the target DOM element and render the application.
- **`logseq.App.registerUIItem()`**: Used to add custom UI elements, like a toolbar button.
- **`logseq.provideModel()`**: Exposes functions to the Logseq UI for interaction.
- **`logseq.ready()`**: Ensures Logseq is ready before executing the main function.
```
--------------------------------
### Provide Dynamic UI Content
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Use `provideUI` to dynamically render HTML content. It requires a unique key and an HTML template, and can optionally specify a slot and reset behavior.
```javascript
logseq.provideUI({
key: 'my-overlay',
template: `
Hello from plugin
`,
reset: true
})
```
--------------------------------
### Logseq Plugin: Register Commands and UI
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Common initialization pattern for Logseq plugins. Registers slash commands first, then registers UI items and provides a model for interaction.
```javascript
function main() {
// Register all commands
logseq.Editor.registerSlashCommand('🔍 Search', handleSearch)
logseq.Editor.registerSlashCommand('📝 Note', handleNote)
// Then register UI
logseq.App.registerUIItem('toolbar', {
key: 'search-btn',
template: '🔍'
})
logseq.provideModel({
openSearch() { logseq.showMainUI() }
})
}
```
--------------------------------
### React to Setting Changes in a React Component
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md
Demonstrates how to use `useState` and `useEffect` in a React component to display and react to changes in Logseq plugin settings.
```javascript
function App() {
const [settings, setSettings] = useState(logseq.settings)
useEffect(() => {
logseq.on('settings:changed', (newSettings) => {
setSettings(newSettings)
})
}, [])
return (
Current font: {settings.googleFontFamily}
)
}
```
--------------------------------
### Show Main UI
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md
Displays the plugin's main UI panel. Optionally, it can auto-focus the panel when shown.
```APIDOC
## Show Main UI
### Description
Displays the plugin's main UI panel. Optionally, it can auto-focus the panel when shown.
### Method
```typescript
logseq.showMainUI(options?: { autoFocus?: boolean }): void
```
### Parameters
#### Query Parameters
- **autoFocus** (boolean) - Optional - Auto-focus the UI panel when shown. Defaults to `false`.
### Request Example
```javascript
logseq.Editor.registerSlashCommand('⚙️ Settings', async () => {
logseq.showMainUI({ autoFocus: true })
})
```
```
--------------------------------
### Minimal package.json Configuration for Logseq Plugin
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md
Defines the essential metadata for a Logseq plugin, including its ID, title, description, and minimum required Logseq version.
```json
{
"name": "logseq-plugin-name",
"version": "0.0.1",
"main": "index.html",
"logseq": {
"id": "logseq-plugin-name",
"title": "Plugin Title",
"description": "Plugin description",
"author": "Your Name",
"version": "0.0.1",
"minAppVersion": "0.9.0"
}
}
```
--------------------------------
### Object-based Plugin Initialization with Model
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md
Initializes a plugin by providing a model object with methods callable from UI templates. This pattern is useful for managing plugin settings and UI interactions.
```javascript
import '@logseq/libs'
function createModel() {
return {
openSettings() {
logseq.showMainUI()
},
saveSetting(name, value) {
logseq.updateSettings({ [name]: value })
}
}
}
function main() {
// Initialize UI, register commands, etc.
logseq.App.registerUIItem('toolbar', {
key: 'my-plugin-btn',
template: '⚙️'
})
}
logseq.ready(createModel()).then(main).catch(console.error)
```
--------------------------------
### Create Page with Properties
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md
This function demonstrates how to create a new page in Logseq, add tags, set properties like cover and rating, and link to other pages (e.g., director). It also appends the description as the first block of the new page.
```javascript
async function createMoviePage(movieData) {
// Create page
const page = await logseq.Editor.createPage(movieData.title)
if (!page?.uuid) throw new Error('Failed to create page')
// Add tags
await logseq.Editor.addBlockTag(page.uuid, 'movie')
// Set properties
await logseq.Editor.upsertBlockProperty(page.uuid, 'cover', movieData.image)
await logseq.Editor.upsertBlockProperty(page.uuid, 'rating', movieData.rating)
await logseq.Editor.upsertBlockProperty(page.uuid, 'year', movieData.year)
// Create director page and link
const director = await logseq.Editor.createPage(movieData.director)
if (director?.uuid) {
await logseq.Editor.upsertBlockProperty(page.uuid, 'director', director.id)
}
// Add description as first block content
await logseq.Editor.appendBlockInPage(page.uuid, movieData.description)
return page
}
```
--------------------------------
### Import All Movies with Throttling
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-imdb-top250-importer/README.md
Illustrates how to import all movies from the list, including progress messages and a throttle to prevent overwhelming Logseq. This function manages the bulk import process.
```typescript
importAllToLogseq()
Shows progress messages during import
Navigates to `#movie` tag page after completion
100ms throttle between imports to avoid overwhelming Logseq
```
--------------------------------
### ShowUIOptions
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md
Options for the `logseq.showMainUI()` function, enabling control over whether the UI panel should automatically receive focus.
```APIDOC
## ShowUIOptions
### Description
Options for showing the main UI. This allows for controlling whether the UI panel should automatically gain focus upon being shown.
### Fields
- **autoFocus** (boolean) - If true, auto-focus the UI panel
### Used by
`logseq.showMainUI()`
### Example
```javascript
logseq.showMainUI({ autoFocus: true })
```
```
--------------------------------
### showMainUI
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Shows the plugin's main UI panel. Optionally allows auto-focusing the UI.
```APIDOC
## showMainUI
### Description
Shows the plugin's main UI panel.
### Method
(Not specified, likely an SDK function call)
### Parameters
- **options.autoFocus** (boolean) - Optional - Auto-focus the UI.
### Example
```javascript
logseq.showMainUI({ autoFocus: true })
```
```
--------------------------------
### on
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md
Registers a listener for plugin events. It takes an event name and a callback function that will be executed when the event occurs.
```APIDOC
## on
### Description
Registers a listener for plugin events.
### Method
void
### Endpoint
logseq.on(eventName: string, callback: (data: any) => void)
### Parameters
#### Request Body
- **eventName** (string) - Required - Event name, e.g., 'settings:changed', 'ui:visible:changed'
- **callback** (function) - Required - Handler function
### Request Example
```javascript
logseq.on('settings:changed', (settings) => {
setSettings(settings)
})
logseq.on('ui:visible:changed', async ({ visible }) => {
if (visible) {
const blocks = await logseq.Editor.getCurrentPageBlocksTree()
// Render mind map
}
})
```
### Response
None
```
--------------------------------
### UI Show Message for Progress Updates
Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md
Demonstrates using `logseq.UI.showMsg` to display progress updates during a bulk import process. Messages are configured with `timeout: 0` to remain visible and use the `key` option for updates and closing.
```javascript
async function importBulkData(items) {
const msgKey = await logseq.UI.showMsg(
'Starting import...',
'info',
{ timeout: 0 }
)
for (let i = 0; i < items.length; i++) {
await logseq.UI.showMsg(
`Importing ${i + 1}/${items.length}...`,
'info',
{ timeout: 0, key: msgKey }
)
await importItem(items[i])
}
logseq.UI.closeMsg(msgKey)
logseq.UI.showMsg('Import complete!', 'success')
}
```