@reventlessdev/reventless-host-shell
v3.0.0-alpha.91
Published
Reventless host shell SPA — loads plugin UI fragments at runtime via Module Federation
Readme
@reventlessdev/reventless-host-shell
The web front end of a Reventless platform, shipped as a prebuilt bundle.
This is how a Reventless application gets a user interface. You do not write one: your plugins already describe their read models and commands, and those descriptions become lists, detail pages, filters, forms and routes. There is nothing here to compile and no component code to author — you add the shell to your platform stack and your domain shows up in a browser.
Adding a UI to your platform
1. Serve the shell from your platform stack
Pass ~hostUiBundle to deployPlatform. The deploy resolves this package's
built bundle, hosts it as your platform's static site, and writes a
config.json beside index.html naming the endpoints, auth mode and services
it just provisioned:
let default = Platform.deployPlatform(
~version=Reventless.PackageVersion.fromCaller(),
~hostUiBundle={},
)That generated config is what lets one prebuilt bundle serve every environment — you never rebuild the shell per stage.
2. Let each plugin contribute its screens
A plugin declares which of its components should appear, and where, by passing
a UI fragment manifest. makeAutoUIManifest derives that manifest from the
plugin structure you already have, so a read model becomes a list page and an
aggregate becomes a detail panel without naming them twice:
Platform.Plugin.make(
~name="Catalog",
~pluginStructure,
~uiFragments=Platform.Plugin.makeAutoUIManifest(
~remoteEntryUrl=uiBundleUrl,
~name="Catalog",
~pluginStructure,
~readModelPositions=["platform-summary"],
~aggregatePositions=["resource-detail"],
),
// …aggregates, slices, extension points
)Components marked internal are left out of the manifest, so hiding a read model from the UI does not mean unwiring it.
3. Run it against a local platform
npx reventless-host-shellThis serves the built bundle and proxies /graphql to localhost:4000 and
/platform-graphql to localhost:4001, where an in-memory Reventless platform
serves its domain and admin APIs. Use it while developing; production is served
by the platform stack from step 1.
4. Correct what was inferred
AutoUI guesses labels, column order, which view a list opens in, and which
fields belong on a form. Where a guess is wrong, a ui-hints.json overrides it
without touching code — point hostUiBundle.uiHintsFile at the file and the
deploy publishes it beside config.json. Absent, the shell treats the 404 as
"no hints" and uses its own defaults.
5. Turn on the capabilities that need infrastructure
Some features need something provisioned before they appear. Uploads are the
example: hostUiBundle.uploadBucket provisions a presigned-upload service
against an object store and threads its URL into the config, which is what makes
file and image fields accept a real upload.
Leave it unset and the service is not provisioned, the endpoint is omitted from the config, and the shell notices — the upload input is never registered, so a file field renders plainly rather than failing.
What you get
- Screens without UI code. The generated pages are the product, not a scaffold to replace later.
- New plugins without redeploying the shell. Plugins that bring their own screens are loaded at runtime as Module Federation remotes: the shell has no remotes compiled into it and discovers them from the platform as it boots.
- Alternative views where the data supports them. A read model is a table by default, and is offered other views when its schema fits them — a status enum earns a board, a latitude/longitude pair earns a map. An offered view is a toggle the user can take or leave, never a forced default.
- Live updates, presence and uploads when the platform advertises the matching endpoints, and nothing when it does not.
What is in config.json
The deploy writes this for you; write it by hand only when self-hosting the bundle. The keys the shell reads include:
| Key | Purpose |
|---|---|
| apiEndpoint | the domain GraphQL API |
| platformApiEndpoint | the platform (admin) GraphQL API |
| authMode | local or cognito, with the matching cognito* keys |
| domainApiEventsEndpoint | live updates transport; absent ⇒ no live updates |
| clientEventsNamespace | channel namespace browsers may publish to; absent ⇒ presence and chat surfaces stay dark |
| viewModes | which optional view modes to register |
Uploads need no key. A file or image input mints its upload target through the
domain API's Upload_Presign mutation, naming the object store its own field
declares, and PUTs the bytes straight there — so apiEndpoint is all it needs.
See docs/guides/upload-contract.md in reventless-core for the contract.
To host the bundle yourself, serve this package's dist/ as static files with a
config.json next to index.html.
License
Proprietary — see LICENSE. This package is published so that it can be
obtained and run to operate a Reventless application; it grants no
redistribution or modification rights.
