Skip to content

views: find_by_tag endpoint + facade CDN 1.0.30 + host_config_layout + wc-content-kit#56

Open
AndrewKirkovski wants to merge 9 commits into
masterfrom
feat/views-find-by-tag
Open

views: find_by_tag endpoint + facade CDN 1.0.30 + host_config_layout + wc-content-kit#56
AndrewKirkovski wants to merge 9 commits into
masterfrom
feat/views-find-by-tag

Conversation

@AndrewKirkovski
Copy link
Copy Markdown
Contributor

@AndrewKirkovski AndrewKirkovski commented May 14, 2026

Summary

One big update consolidating four threads that ship together as the framework-side counterpart to gen-2-chat 1.0.30:

  1. views: find_by_tag API — tag-name-keyed lookup for registered view.component entries (companion to gen-2-chat's $W.loadByTagName(tag)).
  2. Facade CDN bump → 1.0.30 — across _index.yaml, README.md, Makefile, and the test fixture.
  3. facade.host_config_layout ns.requirement — JSON-string config bag for managed-layout shells.
  4. wc-content-kit module (NEW) — vendored mermaid / markdown / chartjs web components shipped from the framework so apps don't have to bundle them.

1. views: find_by_tag — tag-name → view.component lookup

Closes a gap in the FE isolation paradigm: there was no way to load a peer WC by its custom-element tag — loadWebComponent(componentId) only works on artifact UUIDs, and the only sanctioned path for static dependencies was auto_register: true + announced: true + customElements.whenDefined(). This adds the missing primitive.

Endpoint shape:

GET /components/by-tag/wc-thread-picker
→ 200 OK
{
  "success": true,
  "component": {
    "id": "...",
    "name": "...",
    "title": "...",
    "tag_name": "wc-thread-picker",
    "base_url": "http://localhost:8088/components/thread-picker/",
    "entry_point": "dist/index.js",
    "auto_register": true,
    "props": {...},
    "events": {...}
  }
}

GET /components/by-tag/no-such-tag
→ 404
{ "success": false, "error": "No view.component registered for tag: no-such-tag" }

Files (Lua):

  • src/views/component_registry.lua — new find_by_tag_name(tag) library function. Returns the first matching view.component info or nil + error. Filters via registry.find({ "meta.type": "view.component", "meta.tag_name": tag }).
  • src/views/api/find_by_tag.lua — new HTTP handler. 400 on missing tag, 404 on no match or unannounced, 403 on access denied. Respects the same announced + can_access checks as /components/list.
  • src/views/api/_index.yaml — registers the function.lua + http.endpoint entries.
  • src/views/_index.yaml — adds find_by_tag + find_by_tag.endpoint to the api_router targets.
  • src/views/component_registry_test.lua — adds tag_name="test-widget" to the widget fixture + 3 new test cases (known tag, unknown tag, empty/nil tag).

Companion FE work (gen-2-chat 1.0.30, already published): $W.loadByTagName(tag, options?) proxy SDK function calls this endpoint then dynamic-imports + registers via the existing importESMComponentByPackageJSON pipeline. Per-tag in-flight dedup across all three FE load paths (loadByTagName, parseDomForLoaders, loadGlobalAutoloadWidgets), 30s whenDefined timeout, tag normalization at the boundary.

2. Facade CDN → 1.0.30

_index.yaml         fe_facade_url default   →  webcomponents-1.0.30
README.md           3 doc references         →  webcomponents-1.0.30
Makefile            WEB_HOST_CDN             →  webcomponents-1.0.30
config_handler_test  origin-extraction fixture →  webcomponents-1.0.30

The pre-existing branch state had _index.yaml and README.md stuck at 1.0.27 because the earlier merge that built this branch dropped the 1.0.28/1.0.29 bumps during conflict resolution. The final bump commit (bb97229) unifies all five locations on 1.0.30.

gen-2-chat 1.0.30 is published to npm (@wippy-fe/* 0.0.30, all 13 packages); CDN deploy to web-host.wippy.ai/webcomponents-1.0.30/ still pending.

3. host_config_layout ns.requirement

Added in feat(facade): add host_config_layout ns.requirement for managed-layout (commit on the feat/host-config-layout-requirement branch, merged in). Lets a managed-layout consumer ship its panel/floating/modal declaration as a JSON-string requirement value instead of hard-coding it in the consumer JS. Defaults to {}.

4. wc-content-kit module (NEW)

New top-level src/wc-content-kit/ shipping three production web components built from frontend/{mermaid,markdown,chartjs}/ Vite projects, served as static assets via http.static + http.endpoint. Apps consume via the same view.component registry as any other peer WC. Pre-built public/ artifacts checked in to keep the deploy story simple (no FE build step required in the framework's CI).

Lint

wippy lint --level error clean for both:

  • src/facade (8 entries) — one lint error fixed in this PR (json.decode(entry.data.default) cast to string)
  • src/views (pre-existing, clean)

Commits

Hash Subject
feat(wc-content-kit) new module shipping mermaid / markdown / chartjs
feat(facade) host_config_layout ns.requirement for managed-layout
1fa60c3 Bump facade CDN to 1.0.28
55e55b5 Bump facade CDN to 1.0.29
310ea47 facade: drop live-yaml-test marker
merge origin/feat/host-config-layout-requirement into chore/bump-facade-cdn-1.0.28
merge fix restore extra_scripts content lost during conflict resolution
views add find_by_tag_name lookup + GET /components/by-tag/{tag}
bb97229 Bump facade CDN to 1.0.30 + fix lint error

Cross-repo coordination

…s web components

Adds `wippy/wc-content-kit` — a self-contained framework module that
auto-registers three Wippy web components for content rendering in
chat / artifacts / pages:

  • <wippy-mermaid>  — any Mermaid v11 diagram via `definition` attr
  • <wippy-markdown> — GFM rendered through markdown-it + sanitize-html
  • <wippy-chartjs>  — universal Chart.js v4 wrapper supporting all 8
                       chart types from a single tag

Integrators add the dependency once (`kind: ns.dependency`,
`component: wippy/wc-content-kit`) and the tags become available
everywhere chat content is rendered — no copy-paste, no per-app wiring.

Mermaid + markdown source carried over byte-identical from the
battle-tested `app-template/frontend/web-components/{mermaid,markdown}/`
templates. Chartjs extended from `chart-circle/` (single-purpose
doughnut) into a universal Chart.js wrapper that registers all
controllers, scales, and elements at module load and falls back to
the host CSS palette when datasets omit colors.

Module contents:
  wippy.yaml         — org/module/embed declaration
  _index.yaml        — ns.requirement (server) + http.static
                       (/wippy/wc-content-kit/) + 3× registry.entry
                       with full props schemas + AI-ready descriptions
  Makefile           — build / clean / per-component targets
  README.md          — 7-section reference: integration snippet,
                       per-tag attribute tables and 8-9 examples each,
                       AI prompting notes, build instructions
  frontend/{name}/   — Vue 3 + Vite source for each component
  public/{name}/     — pre-built bundles (committed; ship-ready)

Live integration test verified in real Wippy host:
  - GET /api/public/components/list exposes all three tags with
    auto_register=true and correct base_urls under /wippy/wc-content-kit
  - All bundles serve HTTP 200 from http.static
  - Custom elements registered, mounted in Shadow DOM, render expected
    content (SVGs / canvases / sanitized HTML)
  - Theme palette inheritance works for chartjs (--p-primary-500 etc.)
  - Error path produces inline error banner instead of crashing
Adds a server-side configuration path for managed-layout's
HostLayoutDeclaration. Before this, the only paths to set
hostConfig.layout were the dev-shortcut `?layout=<base64>` URL param
and the parent SetConfig postMessage handshake — there was no way
to declare layout in the consumer's `app/deps/_index.yaml` like
every other facade option.

config_handler.lua reads the new requirement, JSON-decodes, and
attaches as hostConfig.layout in the response body when
fe_mode == "managed". Empty/missing decode skips the field so the
host falls back to its other configuration paths. fe_mode == "compat"
ignores the field entirely (preserves existing behavior).

Bumps default fe_facade_url to webcomponents-1.0.27 to pick up
declarative drawer-mode support shipped in gen-2-chat 1.0.27.
Web Host 1.0.29 release brings:
- proxy api default 401 → host.handleError('auth-expired') interceptor
  with skipDefaultAuth per-request opt-out + cross-origin auto-skip
- fix for cold-cache "Proxy globals not found" race in host shells
  (~1/3 fail rate on cold loads, host context only — iframe unaffected)

Refs updated in src/facade/{_index.yaml, README.md, Makefile,
config_handler_test.lua}.
Was used to confirm wippy.lock `replacements:` overrides hub-fetched
vendor with the local checkout — the test query string appeared at
runtime, proving the replace wires correctly. Removing it now that
the smoke test is complete.
…de-cdn-1.0.28

Combines facade CDN bump (chore) with host-config-layout-requirement (feat).
Facade conflicts resolved by taking feat-branch versions of README.md,
_index.yaml, and config_handler_test.lua.
The previous merge commit resolved 3 facade conflicts by taking feat-branch
versions outright, which dropped chore's extra_scripts content:
- src/facade/_index.yaml: extra_scripts ns.requirement entry
- src/facade/config_handler_test.lua: extra_scripts in REQ_NAMES + defaults
  + the test.describe("extra scripts", ...) block (4 tests)
- src/facade/README.md: extra_scripts requirement table row, ### Extra scripts
  section, extraScripts: null in config-response example

This commit re-adds those parts on top of feat's host_config_layout
additions, so both extra_scripts (chore) and host_config_layout (feat)
coexist correctly.
Adds a tag-name-keyed lookup for registered view.component entries so a
consumer WC can resolve a peer module's URL without hardcoding it. Closes
the "FE isolation paradigm" gap where consumers had to know the peer's
physical URL because no by-tag-name lookup existed.

Changes:
- component_registry.lua: `find_by_tag_name(tag)` returns the first
  matching view.component or nil + error. Uses registry.find with the
  meta.type + meta.tag_name filter.
- api/find_by_tag.lua: HTTP handler at GET /components/by-tag/{tag} that
  returns a single-component response shape mirroring /components/list,
  respecting announced + can_access checks. 400 on missing tag, 404 on
  no match.
- api/_index.yaml: registers the function.lua + http.endpoint entries.
- _index.yaml: adds find_by_tag + find_by_tag.endpoint to the api_router
  targets list.
- component_registry_test.lua: adds tag_name=test-widget to the widget
  fixture + 3 new test cases (known tag, unknown tag, empty/nil tag).

Live-tested via lattice (with wippy.lock replacements:
  - from: wippy/views
    to: ../wippy-framework/src/views
):
  GET /api/public/components/by-tag/wc-thread-picker -> 200 + JSON
  GET /api/public/components/by-tag/no-such-tag-zzz -> 404 + error
CDN refs unified across:
- _index.yaml fe_facade_url default (was 1.0.27 — merge conflict
  resolution earlier in this branch dropped the bump to 1.0.28/29)
- README.md fe_facade_url table row + two JSON examples (was 1.0.27)
- Makefile WEB_HOST_CDN (was 1.0.29)
- config_handler_test.lua "extracts iframe origin from facade URL"
  fixture (was 1.0.26 — refresh keeps test data in sync with the
  current host version even though the test only exercises the
  origin-extraction regex)

Lint fix: cast `entry.data.default` (typed `any`) to `string` before
passing to `json.decode` in the host_config_layout test. The Luau
linter rejected the previous `json.decode(entry.data.default)` with
E0000 "expected string, got any". Cast via `:: string` is the
canonical Luau workaround per the project's pyright/luau gotcha
playbook.

wippy lint --level error: 8 entries, no issues.
@AndrewKirkovski AndrewKirkovski changed the title views: add find_by_tag_name lookup + GET /components/by-tag/{tag} views: find_by_tag endpoint + facade CDN 1.0.30 + host_config_layout + wc-content-kit May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants