Rudder stays out of the Research Gallery and makes no network call on a static host

The gallery added every experimental bundle as a tab, so Rudder's engine probes
(/api/rudder/status, /devices, /events) logged three 404s on every embed of the
gallery. The manifest now carries each profile's meta targets, and the gallery
skips a bundle whose profiles are all corner widgets or declare targets without
"web". Rudder itself contacts its engine only where one can exist: the dev
server, the desktop app, or an explicit apiBase.
This commit is contained in:
Doxa Maps 2026-09-28 02:52:40 +00:00
parent cdb3ee1e81
commit 534bbdd5af
3 changed files with 18 additions and 2 deletions

View file

@ -24,14 +24,16 @@ export function readProfileMeta(dir, profileName) {
heavy: meta?.heavy === true,
widget: CORNERS.includes(corner) ? { corner } : null,
label: name ? name.trim() : '',
// Where the plugin runs ("web", "desktop"…); absent = web. A desktop-only plugin is never a gallery tab.
targets: Array.isArray(meta?.targets) ? meta.targets.filter((t) => typeof t === 'string') : null,
}
} catch { return { stage: 'experimental', heavy: false, widget: null, label: '' } }
} catch { return { stage: 'experimental', heavy: false, widget: null, label: '', targets: null } }
}
/** The optional manifest keys for one profile (stage always; heavy / widget only when set). */
export function profileMetaFields(dir, profileName) {
const m = readProfileMeta(dir, profileName)
return { stage: m.stage, ...(m.label ? { label: m.label } : {}), ...(m.heavy ? { heavy: true } : {}), ...(m.widget ? { widget: m.widget } : {}) }
return { stage: m.stage, ...(m.label ? { label: m.label } : {}), ...(m.targets ? { targets: m.targets } : {}), ...(m.heavy ? { heavy: true } : {}), ...(m.widget ? { widget: m.widget } : {}) }
}
/** A bundle is production if ANY of its profiles says so. */

View file

@ -599,6 +599,10 @@ function experimentalTabsFromManifest(manifest) {
// so this chooses which of its profiles that row opens on.
const profiles = Array.isArray(b.profiles) ? b.profiles : []
if (!profiles.length) continue
// Not for the web: a plugin whose every profile is a corner widget or declares targets without "web"
// (Rudder: desktop + the Plugin Studio's corner). As a tab it probed a backend that a static host
// does not have, and every embed of the gallery logged three 404s.
if (profiles.every(p => p.widget || (Array.isArray(p.targets) && !p.targets.includes('web')))) continue
const entry = profiles.find(p => p.isMap) || profiles.find(p => p.profile === id) || profiles[0]
// A discovered tab nests the same way a curated one does: its ELEMENT, loaded from the bundle's
// own scriptUrl. Both are read straight off the manifest, so this path needs no knowledge of the

View file

@ -553,7 +553,17 @@ function onKey(ev) {
async function fetchStatus() {
try { const r = await fetch(apiBase.value + '/status'); if (r.ok) applyStatus(await r.json()) } catch {}
}
// A backend can only exist on the dev server (bun run dev), in the desktop app (Tauri), or where the host
// says so (an explicit apiBase). A built page on a static host has none, so it makes NO network call there:
// it probed /api/rudder anyway and logged three 404s on every page that carried it.
const backendKnown = !!cfg.value.apiBase || import.meta.env.DEV ||
(typeof window !== 'undefined' && (!!window.__TAURI__ || !!window.__TAURI_INTERNALS__ || location.protocol === 'tauri:'))
onMounted(() => {
if (!backendKnown) {
engine.value = 'offline'
window.addEventListener('keydown', onKey)
return
}
fetchStatus()
connect()
refreshDevices()