Appearance
Turn on the read-only site metadata API and build a launcher for a site's apps.
A site can expose a small, read-only metadata API: a directory of the apps published on that site. Turn it on, and a "root" app can fetch the list and render a launcher, with no backend of its own. It is off by default and enabled per site.
What you get
When enabled, the site serves one document on its own host at /__meta/v1/directory.json.
It lists the site's published apps (an app with no live release does not appear), and looks like this:
json
{
"version": "v1",
"site": { "name": "Acme Internal" },
"apps": [
{ "pathPrefix": "/", "name": "Home" },
{ "pathPrefix": "/docs", "name": "Docs" }
]
}The endpoint lives behind the site's existing sign-in: every app is gated, so a viewer must be signed in to read it (app names never leak to anonymous visitors). Every signed-in viewer sees every app.
Turn it on
- Open the site in the dashboard.
- From Actions for {site}, choose Turn on metadata API….
- Confirm in the dialog.
The dialog explains what will be served:
This site will serve a read-only directory of its published apps at /__meta/v1/directory.json, behind the site's existing sign-in. Use it to build an app launcher.
Choose Turn off metadata API from the same menu to stop serving it. When you do, the confirmation notes that The /__meta directory will stop being served for this site.
Build the launcher
The launcher is just an ordinary app deployed at the site root (/). On load it fetches the directory and renders a tile per app, each linking to that app's pathPrefix. Because it runs on the same host, the request carries the viewer's session automatically.
js
const res = await fetch("/__meta/v1/directory.json", { credentials: "same-origin" });
if (!res.ok) {
// Not signed in, or the directory isn't available for this site.
return;
}
const { site, apps } = await res.json();
// Render `site.name` as a heading and one linked tile per app in `apps`.Start from a prompt
If you use an AI coding tool, this prompt scaffolds a launcher that matches the contract above. Keep the version pinned to /__meta/v1.
text
Build a single-page static site that acts as an app launcher.
On load, fetch('/__meta/v1/directory.json') on the same origin, sending
credentials so the viewer's session cookie is included. The JSON response is:
{ "version": "v1",
"site": { "name": "..." },
"apps": [ { "pathPrefix": "/docs", "name": "Docs" } ] }
Render site.name as a heading and one tile per entry in `apps`, each linking to
its pathPrefix. Show an empty state when `apps` is empty, and an error state if
the fetch fails (a signed-out viewer, or the directory being unavailable).
Output plain static HTML/CSS/JS with no build step and no backend, so it can be
deployed as a static folder and mounted at the site root.Notes
- The API is versioned: a future change to the document shape ships under a new path (for example
/__meta/v2/...) so an existing launcher keeps working. - The directory always reflects published releases, so it never advertises an app that a viewer can't actually open.