ai-skills/skills/valdi-polyglot-module/skill.md
Applies to: **/BUILD.bazel and source files in modules with platform-specific implementations (android/, ios/, macos/, web/ directories).
A polyglot module contains platform-native implementations alongside Valdi TSX source:
my_module/
src/ # Valdi TSX components (compiled by Valdi compiler)
android/ # Kotlin/Java native implementation
ios/ # Objective-C native implementation
macos/ # Objective-C native implementation (macOS desktop)
web/ # TypeScript web implementation (compiled by ts_project, NOT Valdi compiler)
strings/ # Localization
module.yaml
tsconfig.json
BUILD.bazel
ts_project(
name = "my_module_web",
srcs = glob(["web/**/*.ts", "web/**/*.d.ts"]),
tsconfig = "web/tsconfig.json",
visibility = ["//visibility:public"],
)
valdi_module(
name = "my_module",
srcs = glob(["src/**/*.ts", "src/**/*.tsx"]) + ["tsconfig.json"],
android_deps = [":android_impl"],
ios_deps = [":ios_impl"],
macos_deps = [":macos_impl"],
web_deps = [":my_module_web"],
deps = [...],
)
web_deps: makes web/ outputs available to the web bundle. Any file in web_deps that exports webPolyglotViews is automatically registered with the WebViewClassRegistry at bundle time — no extra configuration needed.module.yaml deps, run: ./scripts/regenerate_valdi_modules_build_bazel_files.shWeb entry files export view factories that are auto-registered with the WebViewClassRegistry at bundle time. Export a webPolyglotViews record mapping class names to factory functions:
export const webPolyglotViews: Record<string, (container: HTMLElement) => void> = {
MyCustomViewClass: createMyViewFactory(),
};
Each key must match the webClass attribute used in <custom-view webClass="MyCustomViewClass">.
A factory receives an HTMLElement container and populates it with DOM content:
function createMyViewFactory(): (container: HTMLElement) => void {
return (container: HTMLElement) => {
const element = document.createElement('div');
container.appendChild(element);
};
}
web/ filestsc via ts_project, not the Valdi compilervaldi_core/, valdi_tsx/) — web files run in the browser, not the Valdi runtimeglobalThis.moduleLoader.resolveRequire() — build system handles registrationtsconfig.json in web/ should target DOM + ES2020 with module: "commonjs"See valdi_polyglot module for a complete working example with all four platforms:
src/composer_modules/src/composer/valdi_polyglot/ (in the Snap monorepo)web/ files in srcs — they must go through ts_project + web_deps, not the Valdi compiler_deps — each platform impl must be wired via android_deps, ios_deps, macos_depsweb/ — they don't exist in the browser bundle