Datasette gives plugins a place in its navigation
Datasette 0.51 combines a visual refresh with navigation hooks and URL helpers. Plugins can expose their tools within the application and respect its deployment prefix.
A plugin can add a useful page and still leave users unable to find it. Datasette 0.51 addresses that problem with hooks for application-menu links and table-specific actions. Its October 31 release announcement places those additions alongside a visual refresh by Natalie Downe. The practical connection is that extensions now have defined locations within the interface, rather than requiring users to know their URLs.
The announcement describes existing plugins that upload CSV data, edit table schemas and configure full-text search. Those tools already have pages. The missing part is navigation from the database views where their operations become relevant. A link attached to a table can carry more useful context than a general list of installed packages.
I like SQLite tools that keep the relationship between the stored data and the available operation clear. These hooks help Datasette extensions present that relationship without each inventing a separate navigation system. Their value depends on both where the link appears and whether it points to the correct deployed location.
The application menu receives structured links
The 0.51 hook documentation defines menu_links(datasette, actor). It receives the application object and the currently authenticated actor, which can be absent. The hook returns a list of dictionaries containing href and label fields. Datasette adds those entries to its top-right application menu.
The documented example exposes a schema-editing link only to the root actor. Its important mechanisms are the actor check and use of the URL helper. An illustrative version follows the release's pattern.
from datasette import hookimpl
@hookimpl
def menu_links(datasette, actor):
if actor and actor.get("id") == "root":
return [{
"href": datasette.urls.path("/-/edit-schema"),
"label": "Edit schema",
}]
This fragment assumes a plugin supplies the linked destination. Adding a menu entry does not create its handler. The actor check determines whether the entry appears, while the destination still needs its own authorization behavior. Hiding a navigation link cannot establish that a caller is unable to request the URL directly.
The hook may alternatively return an awaitable function that supplies the list. That lets a plugin perform asynchronous work where necessary without changing the shape of the menu entries. The interface remains a collection of destinations and labels, so the application owns the common presentation of the menu.
Table actions receive the table's identity
The companion table_actions(datasette, actor, database, table) hook adds entries to an action menu at the top of a table page. It receives database and table names in addition to the application and actor. A plugin therefore has the context needed to expose an operation for the table the user is viewing.
That is a different scope from the application menu. An instance-wide tool can belong in global navigation, while a table operation can appear beside its subject. The distinction reduces the amount of context a user needs to reconstruct after following the link. It also makes the plugin's intended target visible to its implementation.
The table hook uses the same href and label entry shape and also supports an awaitable result. Plugin authors do not need a separate rendering mechanism for each placement. They supply the context-sensitive links, while Datasette provides the relevant menu in the interface.
A visible link still needs the right prefix
The release also introduces the datasette.urls family of helpers for generating addresses of application pages. The hook documentation specifically recommends using these helpers so links account for the base_url setting. An extension can be discoverable in the menu yet still fail in a deployment under a URL prefix if it constructs the wrong address.
That makes the URL helper part of the navigation change's practical value. A plugin should not need to know whether Datasette occupies a host's root or a path beneath another website. The helper lets the application apply its location configuration when building the destination. Version 0.51 also improves proxy-prefix support and adds deployment guidance for that arrangement.
I prefer this shared responsibility because deployment details otherwise become repeated assumptions in unrelated extensions. A plugin describes its internal destination, and the application's URL builder applies the configured prefix. The menu can then present links that agree with where the instance is actually served.
The refresh also changes how data is presented
The announcement describes horizontal scrolling for wide tables and notes a new table-wrapper element that can affect plugins. That is a reminder that visual changes can alter extension integration even when the database behavior stays the same. Plugins interacting with the table's markup have a different dependency from plugins that merely return menu links.
Binary values also gain direct download links, and Datasette uses those links to make BLOB data available through CSV exports. This keeps a binary value accessible without pretending it is ordinary CSV text. The release's interface work therefore includes both finding operations and reaching data that needs a different representation from the surrounding table cells.