ai-skills/skills/valdi-setup/skill.md
load("//bzl/valdi:valdi_module.bzl", "valdi_module")
valdi_module(
name = "my_module", # Must match the directory name exactly
srcs = glob([
"src/**/*.ts",
"src/**/*.tsx",
]) + [
"tsconfig.json", # tsconfig must be listed in srcs
],
android_output_target = "release",
ios_module_name = "SCCMyModule", # SCC prefix + PascalCase module name
ios_output_target = "release",
visibility = ["//visibility:public"],
deps = [
"//src/valdi_modules/src/valdi/valdi_core",
"//src/valdi_modules/src/valdi/valdi_tsx",
# Add as needed — see dependency table below
],
)
Common mistakes that cause build failures:
name must equal the Bazel package directory name. The Valdi compiler derives
module identity from this — mismatches cause a build error.tsconfig.json must be in srcs. It won't be picked up automatically even if
it's in the directory.HTTPClient without valdi_http) produces a TypeScript
path resolution error, not a missing import error — can be confusing.{
"extends": "../../../../src/valdi_modules/src/valdi/_configs/base.tsconfig.json"
}
Adjust the ../../../../ prefix to match how many directories deep your module is
from the repo root. The base config sets up paths aliases so 'valdi_core/src/...'
imports resolve correctly.
| You're using | Add this dep |
|---|---|
Component, StatefulComponent, Style, providers, CancelablePromise | //src/valdi_modules/src/valdi/valdi_core |
JSX elements (<view>, <label>, etc.), NativeTemplateElements | //src/valdi_modules/src/valdi/valdi_tsx |
HTTPClient, HTTPResponse | //src/valdi_modules/src/valdi/valdi_http |
PersistentStore | //src/valdi_modules/src/valdi/persistence |
| Pre-built UI components (buttons, cards, etc.) | //src/valdi_modules/src/valdi/valdi_widgets_core |
Must start with SCC followed by the module name in PascalCase:
| Directory name | ios_module_name |
|---|---|
chat_thread | SCCChatThread |
profile_editor | SCCProfileEditor |
story_viewer | SCCStoryViewer |
This becomes the Swift module name on iOS. Conflicts with other SCCXxx modules in
the same app target will cause a linker error.
import { Component } from 'valdi_core/src/Component';
interface MyComponentViewModel {
// viewModel properties
}
export class MyComponent extends Component<MyComponentViewModel> {
onRender(): void {
<view>
<label value={this.viewModel.someText} />;
</view>;
}
}
For stateful components:
import { StatefulComponent } from 'valdi_core/src/Component';
interface MyState {
// state properties
}
export class MyComponent extends StatefulComponent<MyComponentViewModel, MyState> {
state: MyState = { /* initial values */ };
onRender(): void {
// ...
}
}
bazel build //path/to/my_module:my_module
valdi hotreload
Run from your module directory. The CLI watches for file changes, recompiles, and
pushes the updated module to a connected simulator or device over USB (or network
with --network).
valdi hotreload --network # Discover device over Wi-Fi instead of USB
If hot reload stops reflecting changes, stop with Ctrl+C and restart — the CLI
will clean stale build artifacts automatically.