Self-hosted Web Host
wippy/cdn-web-host embeds a Web Host build in a Wippy module and serves its
files from the application. It removes the Web Host asset graph's dependency
on the public Wippy CDN. The module does not download assets during startup or
asset requests, and it does not need CDN Core, a database, or a writable asset
directory.
Bind the module
Host 1.0.N pairs with wippy/cdn-web-host version 0.0.N. The module
requires wippy/facade >=0.6.46 <0.7.0. Facade does not depend on this module;
the module depends on the Facade contributor contract.
Add the dependency where the application declares its modules:
- name: cdn_web_host
kind: ns.dependency
component: wippy/cdn-web-host
version: "0.0.66"
parameters:
- name: server
value: app:gateway
- name: public_url
value: https://app.example
Use the application's HTTP service entry for server. Set public_url to
the origin through which browsers reach that application. An optional external
path prefix is allowed, for example https://app.example/tenant.
The URL must use HTTP or HTTPS with a DNS hostname or valid IPv4 address. Credentials, query strings, fragments, IPv6 literals, and traversal segments are rejected. The value is configuration, not a download source.
Run
wippy update wippy/facade wippy/cdn-web-host to resolve the declared versions
and retain the resulting wippy.lock. Use the application's existing startup
workflow and persistent data. This integration does not require a new database.
How Facade selects the local Host
The module registers a wippy.facade.config_contributor function. Facade calls
it through its existing generic contributor pipeline while building config.
The Web Host does not discover CDN modules.
With the example above, the contributor supplies:
fe_facade_url = https://app.example/cdn/web-host/webcomponents-1.0.66
host_policy_mode = shared
Facade uses that URL for the Host entrypoint and its import map. It still owns AppConfig, authentication, and the application bootstrap. No separate Facade Host URL setting or application resolver shim is needed.
An explicit application resolver value for fe_facade_url takes precedence
and suppresses both contributed values. An explicit resolver
host_policy_mode is retained when the module supplies the Host URL. Empty or
invalid public_url makes no contribution, so the existing Facade Host
selection, including its online default, remains in effect. Local assets that
need URL substitution return 503 until public_url is valid.
The packaged build contains an asset-root placeholder. The module replaces it
with the configured public URL only in manifest-listed text files. Other
assets are served unchanged. GET and HEAD are supported. Unknown paths return
404, and invalid paths return 400. Unchanged assets use immutable caching
and ETags. Responses with URL substitution use Cache-Control: no-store.
Markdown and Tailwind
Markdown rendered by w-page and w-artifact can create HTML iframes whose
content is only known at runtime. The existing renderer loads Tailwind's
browser compiler to generate CSS for utility classes in that content.
The offline build loads the pinned Tailwind Play 3.4.16 file from
<fe_facade_url>/@core/tailwind-play.3.4.16.offline.js. The normal online build
keeps its existing https://cdn.tailwindcss.com script. This is separate from
the Host's CSS compiled during its build.
The Host repository keeps the downloaded script, its source and checksum
record, and third-party notices in external-lib-precompiled/. The offline
build verifies the script's size and SHA-256 before including it. The module
also serves the notices at <fe_facade_url>/@core/TAILWIND-PLAY-NOTICES.txt.
Verify the application
- Open
/api/public/facade/configand check that itsfacade_urlfield points to the application's versioned/cdn/web-host/route. This is the resolved value of thefe_facade_urlrequirement. The endpoint uses the default public-router prefix; use the application's configured router prefix if it differs. - Reload the application. Check the browser Network panel for Host modules, the import map, shared vendor files, iframe proxy, and workers below that URL. A document already loaded with another Host needs a reload.
- Open a Markdown preview and confirm that its Tailwind script uses the same local release root. Test this with external requests blocked, including in a fresh browser context so cached CDN responses cannot hide dependencies.
- Exercise the application's pages and components. Check their own network requests separately. Local Host delivery does not make application bundles, images, icons, fonts, or external APIs offline-ready.
For icons and fonts, use Local CDN Assets. Font use remains a manual CSS change using the Fonts panel's copyable stylesheet import and family declaration. This module does not rewrite font CSS or repair the separate Views fragment import-map and scopes limitation.
An external prefix changes the Host asset URLs only. For example,
public_url=https://app.example/tenant selects
https://app.example/tenant/cdn/web-host/webcomponents-1.0.66. Configure the
reverse proxy to forward that asset path to the application's versioned
router. This does not relocate Facade's own root-relative bootstrap, config,
or CSS routes below /tenant.
Build a specific Host tag
The Host repository owns the module source, exporter, and manual release
workflow. The Makefile and Windows wrappers live in wippy/cdn-web-host/.
Generated module output needs no Host submodule. Host CI does not build or
publish Wippy modules.
Use a Host release tag that includes wippy/cdn-web-host/Makefile, Node.js 22
or later, and pnpm 10.24.0. This example builds Host 1.0.66 and module
0.0.66:
git clone --branch webcomponents-1.0.66 --single-branch git@git.spiralscout.com:estimation-engine/wippy-web-host.git web-host-1.0.66
cd web-host-1.0.66
corepack enable
corepack prepare pnpm@10.24.0 --activate
pnpm install --frozen-lockfile
make -C wippy/cdn-web-host build
On Windows, replace the last command with
.\wippy\cdn-web-host\make.bat build. Run it from the Host repository root.
The build verifies the tag, clean source, matching version pair, asset hashes,
and provenance. It writes artifacts/wippy-cdn-web-host/ without publishing.
Set WIPPY_CLI to an absolute native Wippy CLI path, then use these targets:
| Target | Result |
|---|---|
make -C wippy/cdn-web-host check |
Validates the prepared module and runs native publish --dry-run. |
make -C wippy/cdn-web-host publish-prepared |
Validates and publishes the prepared module. |
make -C wippy/cdn-web-host release |
Builds, validates, and publishes the selected tag in one command. |
Windows uses the same targets through wippy/cdn-web-host/make.bat.
Publication uses the native CLI's existing Hub credentials and packs the
validated source directory. It does not retain a WAPP for a later archive
upload. Keep credentials outside the Host repository and CI. Before tagging,
build-draft and check-draft support local work; publication rejects draft
provenance.