Example micro-frontend package that:
- follows the Suncoast UI module contract (
module.definition.json) - includes a host adapter for the current shell
CmsModuleDefinitioncontract - builds to a single browser JS file (
dist/example-mfe.js) - provides Directus seed data for
cms_modules - demonstrates GraphQL async communication:
- submit via GraphQL HTTP mutation
- receive streamed response via GraphQL WS subscription
npm install
npm run devLocal preview URL:
http://localhost:4173/preview/(default)
Build production artifact:
npm run buildBuild output:
dist/example-mfe.js(single-file bundle)dist/example-mfe.js.mapdist/module.definition.json
GraphQL endpoint/token values are runtime-resolved. They are not baked into the built bundle.
Resolution order:
props.graphql.*from CMS block config- Shell runtime values (
#cms-rootdata attrs /window.__SUNCOAST_RUNTIME__.graphql) - Browser auth storage fallback for token (for preview helper flows)
Local preview:
- Copy
.env.local.exampleto.env.local - Set optional preview auth values
- Run
npm run dev
Supported env vars:
MFE_PREVIEW_AUTH_ISSUER_URL(preview login default, usuallyhttps://auth.suncoast.systems)MFE_PREVIEW_AUTH_CLIENT_ID(preview login client id)MFE_PREVIEW_AUTH_AUDIENCE(preview login audience, optional)MFE_PREVIEW_AUTH_SCOPE(preview login scope, defaultopenid profile email)MFE_PREVIEW_PORT(dev only)
The local preview page (/preview/) now includes a login helper that runs OAuth/OIDC code+PKCE in-browser:
- Fill
Auth Issuer URLandAuth Client ID(or setMFE_PREVIEW_AUTH_*env vars). - Click
Loginon the preview page. - After redirect back to
/preview/, the access token is auto-filled intoAuth Token. - Click
Apply / Remountto use that token for GraphQL HTTP/WS requests.
If your auth provider returns access_token in URL hash (implicit flow), the preview page will capture that too.
- Module key:
mfe-example-chat - Renders a simple textbox + submit button chat UI
- Submits prompts using GraphQL mutation
publish_async_request - Listens for response row updates from
graphql.client_async_messagesover GraphQL subscription - Emits module events
- Host
dist/example-mfe.jsat a URL reachable by your shell runtime. - Create/update a
cms_modulesrecord usingdirectus/cms-module.seed.json. - In a
cms_block_moduleblock, choose module keymfe-example-chat. - Use
directus/cms-block-module.props.example.jsonas yourprops_jsonbaseline. - Set:
- optional
graphql.httpUrlandgraphql.wsUrloverrides (leave unset to use shell runtime defaults) - optional
graphql.authTokenoverride (usually leave unset and let shell runtime auth provide token) graphql.submitMutationandgraphql.streamSubscription(defaults are preconfigured forpublish_async_request+graphql_client_async_messages)- path mappings:
graphql.submitRequestIdPathgraphql.streamTextPathgraphql.streamDonePathgraphql.streamErrorPath
- optional
publish.yml now publishes module artifacts directly to the module registry service POST /v1/modules/publish using multipart upload.
- Add repository variable(s) or secret(s):
MODULE_REGISTRY_SERVICE_URL_PREVIEWMODULE_REGISTRY_SERVICE_URL_PROD- optional legacy fallback:
MODULE_REGISTRY_SERVICE_URL
- Add repository secrets for module registry publish API auth:
MODULE_REGISTRY_SERVICE_GOOGLE_SERVICE_ACCOUNT_EMAILMODULE_REGISTRY_SERVICE_GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEYMODULE_REGISTRY_SERVICE_GOOGLE_TOKEN_AUDIENCE
- Optional repository variable:
MODULE_REGISTRY_SERVICE_PUBLISH_PATH(default/v1/modules/publish)
- Publish tag
v*(or run Publish workflow manually). - Workflow will:
- build artifacts
- run
npm run publish:registryto generatedist/module.publish.json - run
npm run notify:catalogto uploaddist/example-mfe.jsanddist/module.publish.jsonto the registry service - attach release artifacts in GitHub
publish:registry writes metadata in dist/module.publish.json:
module_versionpublished_atrelease.tagrelease.shabundle.sha256- full
definition+seeddocuments
Module registry service endpoint called by workflow:
POST <resolved-service-url><MODULE_REGISTRY_SERVICE_PUBLISH_PATH>- Default path:
/v1/modules/publish - Channel defaults:
- tag publish:
prod - manual publish:
preview(override via workflow inputmodule_channel)
- tag publish:
- Service URL selection:
prodchannel:MODULE_REGISTRY_SERVICE_URL_PRODthen fallbackMODULE_REGISTRY_SERVICE_URLpreviewchannel:MODULE_REGISTRY_SERVICE_URL_PREVIEWthen fallbackMODULE_REGISTRY_SERVICE_URL
This repo provides the MFE contract + bundle. Your shell runtime must include or load this module definition at runtime.
If your shell currently only mounts modules from an internal registry, wire this module using the exported host adapter:
- export:
createCmsModuleDefinition()
The bundle also self-registers at:
globalThis.SuncoastMfeRegistry["mfe-example-chat"]
npm run clean- removedistnpm run clean:dev- removedev-distnpm run typecheck- TS type checknpm run build- compile single JS + copy module definitionnpm run dev- local preview server with live rebuild + preview harnessnpm run publish:registry- generate local publish manifest from built artifactsnpm run notify:catalog- upload built bundle + publish manifest to module registry APInpm run sync:directus- direct Directus upsert (optional; only if network access exists)
Workflows included:
.github/workflows/ci.yml- runs typecheck/build on push + PR
- uploads dist artifacts
.github/workflows/publish.yml- runs on
v*tags or manual dispatch - builds bundle + publish metadata
- uploads artifacts
- creates a GitHub Release for tag pushes
- runs on
Secrets expected by publish workflow:
MODULE_REGISTRY_SERVICE_GOOGLE_SERVICE_ACCOUNT_EMAILMODULE_REGISTRY_SERVICE_GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEYMODULE_REGISTRY_SERVICE_GOOGLE_TOKEN_AUDIENCE
Repository variables used by publish workflow:
MODULE_REGISTRY_SERVICE_URL_PREVIEWMODULE_REGISTRY_SERVICE_URL_PRODMODULE_REGISTRY_SERVICE_URL(legacy fallback)MODULE_REGISTRY_SERVICE_PUBLISH_PATH(optional, default/v1/modules/publish)