Command palette
The command palette is the site’s one modal entry point: searching pages,
copying this page’s Markdown, switching language, switching version and jumping
to a site’s own links all happen in one dialog. It is assembled together with
local search: with params.offline_search off, the palette, the index and Lunr
all stay out of the page — see Search.
Opening the palette
| How to open it | What opens |
|---|---|
| Click the search box in the navbar or sidebar | Full search mode |
| ⌘ / Ctrl + K | Full search mode; press again to close |
| / | Full search mode |
| The backslash key | Command-only mode (equivalent to a prefilled >) |
| f / c | The same two, provided by keyboard navigation |
Typing a query beginning with > in the box |
Command-only mode |
/, backslash, f and c are all bare single keys
and stand down for typing: while focus is in an input, textarea, select or
contenteditable, and while an input method is composing, they type an ordinary
character. The modified ⌘/Ctrl + K can open the
palette from a text box, but also stands down during input-method composition.
All opening shortcuts yield to another open native dialog or visible ARIA
dialog, including a fixed-position dialog; a hidden ARIA dialog does not block
them.
Inside the palette: ↑ ↓ select, Enter runs, and Esc closes and returns focus to whatever opened it.
What the palette holds
With nothing typed, the palette lists four groups in a fixed order:
| Group | Contents | Decided by |
|---|---|---|
| Quick links | A few entry points chosen from the navbar’s top-level menu | params.ui.quick_links |
| Page actions | Copy Markdown, view Markdown source, edit this page, view history, create a child page, open an issue, print the section | Repository configuration and whether this page has a Markdown output |
| Preferences | Switch version → switch language → switch theme | Whether the site configures versions, languages and the light/dark menu |
| Commands | Open the GitHub repository, then the site’s own commands | params.github_project_repo (falling back to github_repo) and ui.command_palette.commands |
The three preferences follow the same order as the navbar controls (version, language, theme); palette and navbar share one ordering. Choosing something like “switch language” does not jump immediately — the palette expands the options in place for a second choice.
As soon as text is typed, page results come first, grouped by content root (the group name is the first breadcrumb segment, and the groups follow the navbar’s top-level menu order), with commands and actions merged into one group at the end.
A query starting with > lists commands and actions only and searches no pages.
Use it when you are unsure which menu holds a feature.
An unavailable item is still listed when the reason can be stated. With no repository configured, “edit this page” stays in the list with an “unavailable” note rather than disappearing.
Quick links
Quick links are selected from Hugo’s main menu by identifier rather than written out a second time:
The values are the identifier of entries in menus.main. Left unset, it
defaults to the documentation and blog sections (params.ui.docs_section and
blog_section). Configuring the menu itself is in
Navigation and menus.
Custom commands
A site’s own commands go under params.ui.command_palette.commands, after the
built-in ones, in the order written:
That is the one this site uses. There are seven fields. An unsupported key or invalid record warns and drops that command during ordinary preview; strict publishing rejects the warning:
idis required, starts with a lowercase letter, and holds only lowercase letters, digits, underscores and hyphens; it must not collide with a built-in action ID.titleis what the palette shows;descriptionis the smaller line beneath it;iconis one Font Awesome class pair.keywordsis an array that takes part in matching without being displayed, for the search terms a reader might type.urlandactionare mutually exclusive and one is required.urlaccepts a fullhttp/httpsaddress, a site path, or an in-page anchor beginning with#; an address with a host opens in a new tab.actionreferences a built-in action ID.
action:Built-in actions are already in the palette, and wrapping one makes the same feature appear twice under two names.
A multilingual site writes the commands under
languages.<lang>.params.ui.command_palette.commands so titles and keywords can
be localized. The order comes from the default language’s list: an entry with
the same id in another language overrides fields only, and a new id is
appended at the end. Command order is therefore identical across languages, and
nothing moves when a reader switches.
Configuration can only supply a link or reference a built-in action; it cannot inject a JavaScript callback. What the palette reads is a plain data manifest.
Page actions
The palette’s “page actions” and the split button beside a documentation title are one implementation: the same action descriptors, the same URL generation, the same executor. The button’s left half copies this page’s Markdown, and the arrow on the right expands every action.
To hide the button beside the title, set page_context_menu: false. The
corresponding actions stay in the palette:
To hide the button on just one page, use page_context_menu: false in that
page’s front matter instead.
assistant_links is off by default because clicking one sends the current
page’s full URL — including query string and anchor — to a third party, while
the body is never uploaded. Enable it site-wide through
params.ui.page_context_menu.assistant_links. A page can only narrow that
policy with the following front matter:
Check both the title menu and the palette: neither should offer the assistant links on that page. AI-agent support explains the handoff behavior.
links adds external actions that appear only in the menu beside the title, not
in the palette:
The three placeholders {url}, {title} and {markdown_url} are replaced with
the current page’s values.
Whether “edit this page”, “view history” and “open an issue” are available
depends on the repository configuration — see
Repository links and page info. “Copy Markdown”
and “view Markdown source” need the page to have the markdown output — see
AI-agent support.
How it relates to full-text search
One dialog, two independent data sources:
- Page results come from the local search index. When the index was never generated or fails to download, the palette still opens and still runs commands, and the page section reads “the page index is unavailable; actions still work”.
- Commands and actions come from a JSON manifest embedded in the page and need no network.
The palette is not assembled in print state, so print output has none of it.
With offline_search off there is likewise no palette, and f and
c stay silent without disturbing normal typing.
Query-aware site actions
The runtime hook for trusted site JavaScript is available since OINK 1.1.
Feature-detect it: v1.0.0 and pages without local search do not provide it.
Load the integration after the theme scripts, for example through
layouts/_partials/hooks/body-end.html. This example assumes the site
implements openSiteAssistant and owns its provider settings:
Rows follow native results and actions, including empty/error searches. They
are absent in empty, command, choice, and loading states. Keep rows() pure
and synchronous; all strings render as text. Activation receives the query
used to create the row, not a newer input value. Use handoff() before opening
another coordinated surface; the site then owns its focus and failure UI.
For non-UI actions, return the operation without calling handoff.
The Shell contract defines fields, cancellation, validation, and lifecycle. YAML still cannot contain callbacks, and OINK adds no remote service or telemetry by default.
Verify
Run from your site’s root after a strict build. In the commands below, replace
public/docs/getting-started/index.html with an actual generated documentation
page in your site (including a language prefix if needed).
-
After a build, confirm the command manifest reached the page:
This confirms the action data reached the HTML; the remaining steps check the palette interface with local search enabled.
-
Open the site and press ⌘/Ctrl + K without typing: quick links, page actions, preferences and commands should appear in that order.
-
Type
>: only commands and actions remain. A newly added command should sit after “open the GitHub repository”. -
Repeat step 3 in another language, and confirm the command titles changed while the order did not.
-
A print preview (⌘/Ctrl + P) should show no trace of the palette.
Related
- Search — where the palette’s page results come from
- Keyboard navigation — f, c and the other single keys
- Navigation and menus — the source of quick links and group order
- Repository links and page info — prerequisites for the edit, history and issue actions
- Configuration — full definitions of
ui.command_paletteandui.page_context_menu