Debugging Wippy FE
Use these checks to isolate common Wippy frontend failures before changing application code.
Blank screen on load
1. Check the Console first:
Failed to resolve module specifier 'vue'— the page externalized a specifier that its active import map does not provide. In hosted mode inspect the import map actually served by the target Web Host release; in host-less mode inspect the map inapp.html. Compare every Rollup external against that exact map instead of assuming a canonical package list or merge precedence.Proxy globals not found(or your@wippy-fe/proxyimports come back undefined) —proxy.js/dev-proxy.jsdid not load before your app script ran, so the runtime never installed its internal globals. Check thatdev-proxy.jsis referenced withdata-role="@wippy/scripts"inapp.html.- Silent hang (no errors, no app) — in host-less mode, the dev overlay may be waiting for you to click Accept. Confirm that its FAB (floating button) appeared. If it did not,
proxy.js/dev-proxy.jsfailed to load or install its globals; follow theProxy globals not foundcheck above.
Hosted iframe pages and host-less pages receive config synchronously before the
proxy boots. Web Fragment pages use the fragment adapter's
GetConfig/SetConfig handshake, as does the host-level manual
iframe.html?waitForCustomConfig embedding.
2. Check the Network tab:
- Confirm
dev-proxy.js(host-less) orproxy.js(hosted) loaded with status 200. - If 404: the
srcin your<script data-role="@wippy/scripts">tag points to the wrong URL.
3. Check the runtime installed its globals (internal diagnostic):
// Internal globals — app code never reads these; this is only a console smoke test
// that the proxy runtime mounted. App/WC code uses `import { ... } from '@wippy-fe/proxy'`.
window.$W // should be an object, not undefined
window.__WIPPY_APP_API__ // the resolved proxy instance — present once the runtime installed
The @wippy-fe/proxy getters read these globals (window.__WIPPY_APP_API__ is the live host instance); that is separate from how the module URL resolves. If the globals exist but imports fail, inspect the active import map and the network response for the exact @wippy-fe/proxy specifier. Fix the map or externalization decision in the environment that serves the page; do not infer hosted behavior from a successful host-less boot.
Web component never appears
1. Verify the three gates:
Run from your backend:
curl /api/public/components/list?auto_register=true
Your component's tag_name must appear in the response. If not:
announced: truemissing in_index.yaml→ add itauto_register: truemissing → add it- Component is not registered with
wippy/views→ check your module deps
2. Check the Console:
customElements.get('your-tag-name') // undefined means the element was not registered
3. Check the Network tab:
- Filter for your component's
index.jsURL - The URL should contain
?declare-tag=your-tag-name— this is how the element registers itself - If the URL has no
?declare-tag=query:define(import.meta.url, MyElement)was not retained in the entry chunk. Setbuild.rollupOptions.preserveEntrySignaturesto'strict';falsecan move the registration side effect out of the entry. See Build System
API calls failing / 401
1. In host-less mode:
- The
dev-tokenstub in the proxy config is not a real credential and normally must be replaced before calling an authenticated backend - Open the dev overlay → find the
auth.tokenfield in the JSON config → paste a real bearer token - Confirm
APP_API_URLin the overlay config points to the running backend (not localhost if your backend is elsewhere)
2. In hosted mode:
- Use the proxy
apiclient. For eligible same-origin 401 responses it single-flights and callshost.handleError('auth-expired', error)automatically. - If all API calls 401, check the Host config and session-token injection. Call
host.handleErrormanually only for a request path that deliberately bypasses the standard proxy client and therefore cannot receive its automatic handling.
Theme looks wrong
1. In host-less mode:
The dev overlay starts with themeConfig, primevue, markdown, and iframe
injection disabled by default. The base theme, PrimeVue, Markdown, and
scrollbar sheets are therefore absent until you enable them; customCss and
customVariables remain enabled by default.
Open the dev overlay FAB → toggle the CSS injections you need → check "Auto-accept on reload".
2. Compare the complete effective chain:
A non-empty token is not sufficient. Use distinct values so a stock-palette reset or accidental family alias is obvious:
css_variables:
"--p-primary": "#dc2626"
"--p-secondary": "#7c3aed"
"--p-accent": "#0d9488"
"--p-danger": "#be123c"
"--p-success": "#15803d"
"--p-warn": "#c2410c"
"--p-info": "#0369a1"
"--p-help": "#9333ea"
"--theme-diagnostic-sentinel": "#123456"
Then compare, in this order:
- Effective configured map: inspect
config.theming.global.cssVariablesand confirm the base plus the active@light/@darkreplacements. - Page root: read the exact token with
getComputedStyle(document.documentElement).getPropertyValue(name).trim(). - WC host: read the same token from
getComputedStyle(customElement). - WC inner root: read it from
getComputedStyle(customElement.shadowRoot.querySelector('[data-wippy-theme-root]')). - Rendered semantic color: put
background-color: var(--p-<family>-color)on a probe and compare its computedbackgroundColor; this resolvescolor-mix()in the browser.
Repeat in Auto-light, Auto-dark, forced Light, and forced Dark. For each configured family verify its base, all 50–950 shades, color, contrast-color, hover-color, and active-color; also verify a direct shade/alias override, a surface token, and the sentinel. Page, host, and inner values must agree.
Interpret the first divergence: wrong effective map means configuration/merge; wrong page root means variable compilation/injection; correct page but wrong WC host means host propagation; correct WC host but wrong inner root means the forced-theme bridge or local defaults; equal tokens but wrong rendered color means the consuming selector or semantic alias is wrong.
3. Web component specific:
- If the platform defaults are absent, check that
hostCssKeysincludes'themeConfigUrl'. - If the host is correct but the inner root resets to stock values, verify a current
@wippy-fe/webcomponent-core; do not copy a palette into component CSS. - If PrimeVue components render unstyled, add
'primeVueCssUrl'tohostCssKeys.
See Theming: Micro Frontend Apps or Theming: Web Components for the full injection pipeline.
Host URL bar doesn't update
Portable micro frontend apps must use the createAppRouter() factory from @wippy-fe/router. The package owns both directions of host synchronization; application code must not reproduce router.afterEach and @history wiring.
Check:
import { createAppRouter } from '@wippy-fe/router'
import { config } from '@wippy-fe/proxy'
import { routes } from './routes'
const router = createAppRouter(routes, {
initialPath: config.context?.route ?? '/',
})
If the host URL still does not update, confirm the current @wippy-fe/router family is installed coherently and that no local wrapper replaces the factory. In host-less mode, the dev overlay Monitor tab shows the route the package reports.
Works locally, breaks when hosted
1. Check relative asset resolution for the selected engine:
For iframe delivery, inspect:
document.baseURI // should be <url>/<base_path>/ from your registry entry
If it is wrong, the <base> tag was not injected correctly. Check that
base_path in _index.yaml matches the actual directory structure of the
built output.
Web Fragment delivery deliberately does not inject a <base> element. Inspect
the reflected head and body instead: relative href="./…" and src="./…"
attributes should be rewritten to the fragment gateway's asset URLs.
2. Check proxy globals (internal diagnostic):
window.__WIPPY_PROXY_CONFIG__ // internal — must exist in iframe-hosted mode
Undefined means the proxy was not injected before your app ran. App code never reads this directly; see Proxy & Isolation § Internals.
3. Confirm base: '' in vite.config.ts:
Without base: '', Vite emits absolute asset paths. The app loads fine on your local dev server (which serves from /) but 404s when served from a CDN subdirectory.
4. Import map mismatch:
Re-fetch <version-tag>/import-map.json from the Web Host release pinned by
fe_facade_url. Replace the complete imports object in host-less app.html
and regenerate Vite externals from all of its keys. Do not remove the host-less
map or patch individual entries. Bundle a newly imported exact specifier only
when it is absent from the fetched map.
Using the logger as a debugging tool
logger.debug() and logger.info() output appears in the browser Console during development — not just in production transports. Use it to trace the boot sequence:
import { logger, config, host, api } from '@wippy-fe/proxy'
export function createMainApp() {
logger.debug('App bootstrap started')
logger.debug('Host services resolved', { hasConfig: !!config })
// ... use config, host, api directly
}
logger.captureException(error) also logs to Console in dev mode and is caught by the host's error capture system in production.