A single-page HTML+JavaScript tool for interactively exploring the ?_extra=
options available on any Datasette JSON endpoint. No build step, no server
component, no dependencies that require bundling - one .html file that can
be opened from disk or served from anywhere.
- The user pastes a URL to a Datasette
.jsonendpoint into an input field - a table page, a row page, or a query page, with or without existing query string parameters or the.jsonextension. Examples:http://127.0.0.1:7777/fixtures/facetable.jsonhttp://127.0.0.1:7777/fixtures/facetablehttp://127.0.0.1:7777/fixtures/simple_primary_key/1.jsonhttp://127.0.0.1:7777/fixtures/-/query.json?sql=select+:greeting+as+msg&greeting=hello
- The tool fetches that URL with
_extra=extrasappended and reads theextraskey from the response: a list of{name, description, toggle_url, selected}objects. This is the discovery step - the list differs by page type (TABLE / ROW / QUERY scope) and the tool makes no assumptions about which names exist. - The discovered extras render as a checkbox list. Toggling checkboxes
re-fetches the endpoint with the selected names and displays the resulting
JSON - minus the
extraskey, which exists to drive the UI and would otherwise drown the interesting output.
+--------------------------------------------------------------+
| Datasette extras explorer |
| [ URL input................................. ] [ Explore ] |
+----------------------+---------------------------------------+
| Extras | Response |
| | |
| [x] columns | GET /fixtures/facetable.json?_extra= |
| Column names | columns,count [copy URL] |
| returned by... | 200 - 1.2 KB - 45ms |
| [x] count | |
| Total count of | { |
| rows matching... | "ok": true, |
| [ ] count_sql | "rows": [...], |
| SQL query used | "columns": ["pk", "created", ...], |
| to calculate... | "count": 15 |
| [ ] facet_results | } |
| ... | |
+----------------------+---------------------------------------+
- Left panel: one checkbox per discovered extra, with its
namein monospace and itsdescriptionunderneath in smaller muted text. Sorted alphabetically. Theextrasentry itself is not shown (it is always requested, never displayed). - Right panel: the constructed request line with a copy button, response status / size / elapsed time, then the response JSON pretty-printed with 2-space indentation. Keys contributed by currently-selected extras are visually marked (e.g. a subtle background tint on the line containing the top-level key) so it is obvious what each toggle added; this is computed by comparing top-level keys against the selected extra names, not by diffing responses.
- Parse the user's URL with the
URLAPI. Preserve every existing query parameter (sql=, named parameters,_size=,_shape=etc.) on every request - the tool only manages the_extraparameter. - If the pasted URL already contains
_extra=values (comma-separated or repeated), those names start out checked. - Every request includes
extrasplus the checked names, as a single comma-separated parameter:_extra=extras,columns,count. Requestingextrasevery time keeps the checkbox list andselectedstates current and costs little. - In-flight requests are aborted (
AbortController) when a new toggle happens; rapid toggling coalesces to one request via a ~200ms debounce. - Explorer state (endpoint URL + checked names) is mirrored into the page's
location.hashso a session can be bookmarked or shared; on load, a hash takes precedence over the empty input.
- The
extraskey is deleted from the response object before rendering. Everything else renders exactly as returned, pretty-printed. - JSON is rendered as text in a
<pre>with lightweight syntax highlighting (strings/numbers/keys/booleans via a small regex highlighter - no library). Longrowsarrays are not truncated; readability of large responses is the user's responsibility via_size=. - A "raw" toggle shows the unmodified response including the
extrasblock, for the skeptics.
- Non-200 responses: show the status code and the response body (Datasette
returns JSON error objects with
ok: falseanderrorkeys - render them in the same JSON view, tinted red). - Network/CORS failures: show a hint that the target Datasette must either be
same-origin or started with
--cors(the discovery fetch failing entirely is almost always CORS). - A checked extra whose key is absent from the response (scope mismatch or an older Datasette) renders its checkbox with a warning marker and tooltip "requested but not returned" rather than erroring.
- A URL whose discovery response has no
extraskey is reported as "this endpoint does not support ?_extra= - is it a Datasette 1.0a33+ JSON endpoint?".
- One self-contained
.htmlfile: inline<style>and<script>, vanilla ES2020+, no frameworks, no build step, no external requests other than to the target Datasette. fetch()withcredentials: "same-origin"so cookie-authenticated Datasette instances work when the tool is served from the same origin.- Works when opened via
file://against a--corsinstance. - Keyboard accessible: checkboxes are real
<input type="checkbox">elements with<label>s; the URL form submits on Enter. - No state outside the DOM and the URL hash.
- No authentication UI (tokens, sign-in) - rely on cookies/same-origin.
- No editing of non-
_extraparameters - paste a different URL instead. - No awareness of which extras are "expensive"; the
extraslisting does not expose that flag. (Possible future Datasette enhancement: includeexpensivein theExtrasExtraoutput, at which point the UI can badge those entries.) - No handling of
?_shape=variants that change the top-level structure (array,arrayfirst,object) - extras only appear in the default object shape, so the tool strips_shapefrom pasted URLs and says so.
Tested against the fixtures instance at http://127.0.0.1:7777:
- Pasting
/fixtures/facetable.jsonlists the TABLE-scope extras (count,facet_results,next_url, ...); checkingcountshows"count": 15in the response panel; noextraskey is visible. - Pasting
/fixtures/simple_primary_key/1.jsonlists the 14 ROW-scope extras; checkingforeign_key_tablesshows the five inbound references. - Pasting the
:greetingquery URL above lists the 10 QUERY-scope extras; checkingqueryshowsparams: {"greeting": "hello"}. - Checking then unchecking an extra returns the display to its prior state,
and the copy-URL button reproduces the current view when opened in a new
tab - the copied URL is exactly the URL the tool requested, including the
extrasname. - Requesting an HTML-only extra like
filtersby hand-editing the URL produces a 200 whose response simply lacks the key, surfaced via the "requested but not returned" marker rather than an error.