Files
plainleaf/website/Virtual Pages.md
T

76 lines
3.0 KiB
Markdown

---
description: A page generated dynamically by code rather than stored as a file.
tags: glossary
---
Virtual pages are read-only pages that don't exist as files in your space. Instead, they are generated dynamically when you navigate to them. This is useful for building pages whose content is computed on-the-fly — for example, pages that show all objects with a particular tag.
# How it works
You define a virtual page by calling `virtualPage.define` with a Lua pattern and a function. When someone navigates to a page name matching the pattern, SilverBullet calls your function instead of loading a file from disk.
The function receives the captured groups from the pattern as arguments, and returns the markdown content to display.
```lua
virtualPage.define {
pattern = "greeting:(.+)",
run = function(name)
return "# Hello, " .. name .. "!\nWelcome to this virtual page."
end
}
```
Navigating to `greeting:World` renders a page with the heading "Hello, World!" — but no file is created.
Virtual pages are always **read-only**. The editor disables editing controls automatically.
# Built-in virtual pages
## Tag pages
The most commonly used virtual pages are **tag pages**. When you click a hashtag like `#project`, SilverBullet navigates to `tag:project`, which is a virtual page that lists all objects with that tag — grouped by type (pages, tasks, items, data, etc.).
Tag pages are defined in the standard library and work out of the box. You can override the default tag page by defining your own `virtualPage.define` with the pattern `tag:(.+)`.
## URI pages
Navigating to a page named `uri:https://example.com/page` fetches and displays the content from that URL. This is useful for pulling in external markdown content.
# Defining your own virtual pages
Here's a more complete example that queries the object index:
```lua
virtualPage.define {
pattern = "recent:(%d+)",
run = function(count)
local n = tonumber(count)
local pages = query[[
from index.tag "page"
order by lastModified desc
limit n
]]
local result = "# " .. count .. " Most Recent Pages\n"
for _, page in ipairs(pages) do
result = result .. "* [[" .. page.name .. "]]\n"
end
return result
end
}
```
Navigate to `recent:10` to see the 10 most recently modified pages.
# Multiple capture groups
Patterns can capture multiple groups, each passed as a separate argument:
```lua
virtualPage.define {
pattern = "lookup:(.+):(.+)",
run = function(type, id)
return "# " .. type .. "\nLooking up: " .. id
end
}
```
# How it works under the hood
Virtual page definitions are stored in the config system under the `virtualPages` key. When a page is being created, SilverBullet fires the `editor:pageCreating` event. The standard library's event listener checks all registered patterns against the page name. If a match is found, the corresponding `run` function is called, and its return value becomes the page content with read-only permissions.
See also: [[API/event]], [[API/config]]