Overview
This guide covers both sides of the integration:
- Host (HouseOfApps shell) — catalog, install state, dashboard route, iframe embed, auth/theme handshake, optional API proxy.
- Child (MFE) — a separate Next.js or SPA app: embed mode, boot from host-provided URL params,
postMessagehandshake, and API calls against a host-provided base URL.
Current host behavior:
- Catalog is static in
lib/addons/catalog.ts. There is no remote discovery API. - Install state is client-only (
localStorage). There is no backend install API. - Apps render as cross-origin iframes. Host cookies are not available to the child.
- Auth and other embed context are passed through URL query params and
postMessage— each app defines its own param names and message types (viabuildSrcandreadyMessageTypes).
End-to-end flow
- User installs the app on Marketplace.
- Host writes the addon id to
localStorage["installed_addons"]and shows a sidebar Addons link. - User opens
/your-app. InstalledAddonPageredirects to/marketplaceif not installed.MicroFrontendFrameloads the child iframe. The host passes whatever query params that app needs (auth, API base, parent origin, theme, feature flags, etc.) — typically via a custombuildSrchelper. There is no fixed param list for every Marketplace app.- Child signals ready with app-specific
postMessagetypes (configured asreadyMessageTypes). Host replies with updates the child agreed to handle (e.g. auth refresh, theme changes). - Optional: child calls
/api/<app>/…on HouseOfApps; the proxy forwards to the upstream backend.
Reference implementations
- HTML Editor —
/html-editorwith proxy/api/html-editor. Recommended default for a new proxied MFE. - WhatsApp Automation —
/whatsapp-automation. Catalog + iframe only; child calls its own APIs. - Blogs (Mavik) —
/blogswith proxy/api/mavikto the main HouseOfApps API. Use when you need a custom entry path.
Prefer a proxied reference app as the template unless you have a clear reason not to.
Part A — Host (HouseOfApps) changes
1. Origin module
Create lib/microfrontends/<app>.ts with NEXT_PUBLIC_MY_APP_ORIGIN and ready message types that the child will emit (whatever names that app uses).
2. Catalog entry
Add the app to lib/addons/catalog.ts with id, title, href, microfrontendOrigin, icon, and category. You do not need to change navigationConfig.tsx.
3. Dashboard route
Create app/(dashboard)/my-app/page.tsx that renders InstalledAddonPage with the addon id, ready message types, and optional buildSrc.
4. Full-bleed layout
Include the pathname in isAddonMicroFrontendPage inside AdminLayout so the iframe gets a full-height, padding-free content area.
5. Optional same-origin API proxy
Add a proxy when the child needs host-mediated API access (CORS, cookies, or org headers). Copy the pattern from any existing proxied Marketplace app:
lib/microfrontends/<app>ProxyCors.tsapp/api/<app>/[...path]/route.ts
In buildSrc, pass an API base of {parentOrigin}/api/<app> using whatever query-param name the child expects. The proxy should resolve CORS origin, forward Authorization (or map the access_token cookie), forward org headers, and return the upstream response with CORS headers.
Part B — Child MFE requirements
The child is a normal web app that also supports embed mode inside HouseOfApps.
Boot contract (generic)
Agree on a small embed contract between host and child. The host puts values on the iframe URL (and/or sends them via postMessage). Param names and message types are per app — not a global HouseOfApps standard. Define them in the child’s docs and mirror them in the host buildSrc / readyMessageTypes.
Typical capabilities (name them however you like):
- Flag that the app is running inside an iframe (hide marketing chrome)
- Initial auth credential (JWT or opaque token)
- Parent origin for secure
postMessage - API base URL (often a HouseOfApps proxy path, or a direct upstream)
- UI theme or other host preferences
- Any other app-specific bootstrap data
Example convention (optional — only if you choose these names):
embed=truetokenparentOriginthemeapiBaseUrl
Existing reference apps use names like these; a new app may use different keys as long as host and child match.
Handshake
Parent → child (fixed today)
{ type: 'auth_token_update', token }— store and use for API auth{ type: 'theme_update', theme }—light|dark
Always validate event.origin against the expected parent origin before handling.
Child → parent (configurable)
Emit a ready / auth-request type and register it on the host as readyMessageTypes. Do not spam these messages — aggressive polling can create refresh loops.
APIs
Call APIs against the base URL the host provided (proxy or direct), with the auth credential the host supplied. Prefer that over hardcoding backends in the child.
New app checklist
Host
- Origin module + ready message types
- Catalog entry
- Dashboard page using
InstalledAddonPage - Full-bleed path in
AdminLayout - Optional proxy + CORS allowlist + env vars
Child
- Parse host URL params and apply theme / auth on first paint
- Emit ready messages sparingly (app-specific types)
- Handle host update messages your app agreed to
- Route API traffic through the host-provided API base URL
- Embed layout: no marketing chrome, full viewport
Smoke test
- Marketplace → Install → sidebar link appears
- Open the route → iframe loads in embed mode
- Host preferences (e.g. theme) sync to the child if supported
- Authenticated API call succeeds
- Uninstall → opening the route redirects to
/marketplace
Environment variables and key files
Add only the env vars your app needs. There is no shared fixed list. Typical patterns:
NEXT_PUBLIC_<APP>_ORIGIN— child MFE origin (required for most iframe apps)NEXT_PUBLIC_<APP>_API_BASE_URL(or similar) — upstream API for an optional shell proxy- Any other app-specific public config the host
buildSrcor proxy needs
Proxy CORS allowlists should include the child origin, local HouseOfApps origins, and your deployed shell URL(s) — configure those however your proxy helper already does (hardcoded defaults, env, or both).
Key host files (same pattern for every app):
lib/addons/catalog.tslib/microfrontends/<app>.tscomponents/addons/InstalledAddonPage.tsxcomponents/microfrontends/MicroFrontendFrame.tsx- Optional:
lib/microfrontends/<app>ProxyCors.ts+app/api/<app>/[...path]/route.ts
FAQ
Does HouseOfApps need RTK Query for the child?
No. The child owns its data layer. HouseOfApps only embeds the app and optionally proxies API traffic.
Can the child rely on the HouseOfApps session cookie alone?
Not across origins. Pass auth through the embed URL and/or postMessage updates that your app defines.
Does every app need a proxy?
No. WhatsApp-style apps call their own backends. Add a proxy when CORS, cookies, or org headers make direct calls difficult.
Where is the app registered for users?
Add it to ADDON_CATALOG. Users install it from /marketplace in HouseOfApps at https://app.houseofapps.ai.