# Valdi

> This skill should be used when working on Valdi framework projects. Valdi is Snapchat's cross-platform UI framework that compiles TypeScript/TSX components into native views for iOS, Android, and macOS. It provides specialized knowledge for component architecture, Bazel build system, native bindings, TSX elements, and cross-platform development. Use this skill when implementing Valdi components, debugging build issues, or creating new Valdi projects.

- Skill: `jarrodmedrano/valdi` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add jarrodmedrano/valdi`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jarrodmedrano/valdi/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: jarrodmedrano (https://skillmd.com/u/jarrodmedrano)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jarrodmedrano/valdi

---


# Valdi Framework Development Skill

Specialized guidance for developing cross-platform applications with Valdi, Snapchat's native UI framework that compiles TypeScript/TSX to native iOS, Android, and macOS views.

## Overview

Valdi is NOT a WebView-based framework. It compiles TypeScript components directly into native platform code, delivering native performance without JavaScript bridges. The framework has been used in Snap's production apps for over 8 years.

## When to Use This Skill

Invoke this skill when:

- Working on any Valdi framework project
- Creating new Valdi components or modules
- Configuring Bazel build files for Valdi
- Implementing native bindings (CppModule, NativeModule)
- Debugging cross-platform rendering issues
- Setting up Valdi development environment
- Understanding Valdi's TSX element system

## Key Principles

### 1. Bazel is Mandatory

Valdi uses Bazel exclusively for builds. Never suggest alternative build systems.

**Common commands:**
```bash
# Install CLI globally
pnpm install -g @snap/valdi

# Setup development environment
valdi dev_setup

# Check environment health
valdi doctor

# Bootstrap new project
valdi bootstrap

# Install platform dependencies
valdi install ios
valdi install android

# Enable hot reload during development
valdi hotreload

# Sync project configuration
valdi projectsync
```

### 2. Component Architecture

Valdi components are class-based with lifecycle methods:

```tsx
import { Component, ComponentContext } from 'valdi_core';

interface ViewModel {
  title: string;
  count: number;
}

class MyComponent extends Component<ViewModel, ComponentContext> {
  onCreate(): void {
    // Initialize component
    console.log('Component created');
  }

  onMount(): void {
    // Component mounted to view hierarchy
  }

  onUnmount(): void {
    // Cleanup before removal
  }

  onRender() {
    return (
      <view style={styles.container}>
        <label style={styles.title}>{this.viewModel.title}</label>
      </view>
    );
  }
}
```

### 3. Native TSX Elements

Valdi provides native UI elements (NOT HTML):

| Element | Purpose |
|---------|---------|
| `<view>` | Container view (like div) |
| `<layout>` | Flexbox layout container |
| `<scroll>` | Scrollable container |
| `<label>` | Text display |
| `<image>` | Image display |
| `<video>` | Video player |
| `<slot>` | Content projection |

**Element attributes use native styling, not CSS:**
```tsx
const styles = {
  container: {
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#FFFFFF',
    padding: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#000000',
  },
};
```

### 4. Project Structure

Standard Valdi project layout:

```
my_project/
├── BUILD.bazel              # Main Bazel build file
├── package.json             # Node dependencies (use pnpm)
├── .eslintrc.js            # ESLint configuration
├── app_assets/             # Application assets
│   └── images/
├── src/
│   ├── android/            # Android-specific code
│   ├── cpp/                # C++ native modules
│   ├── ios/                # iOS-specific code
│   └── valdi/              # Valdi TypeScript/TSX
│       ├── _configs/       # Valdi configs
│       ├── tsconfig.json
│       ├── .terserrc.json
│       └── my_module/      # Your module
│           ├── BUILD.bazel
│           ├── tsconfig.json
│           ├── res/        # Module resources
│           └── src/
│               ├── index.ts
│               └── MyComponent.tsx
└── standalone_app/         # Standalone app config
```

### 5. Bazel Build Configuration

**Application BUILD.bazel:**
```python
load("//bzl:valdi.bzl", "valdi_application", "valdi_exported_library")

valdi_application(
    name = "my_app",
    title = "My Valdi App",
    version = "1.0.0",
    ios_bundle_id = "com.example.myapp",
    ios_device_families = ["iphone"],
    android_theme = "Theme.MyApp.Launch",
    android_app_icon = "app_icon",
    root_component = "App@my_module/src/MyApp",
    assets = glob(["app_assets/**/*"]),
    deps = ["//path/to/src/valdi/my_module"],
)

valdi_exported_library(
    name = "my_app_export",
    ios_bundle_id = "com.example.myapp.lib",
    bundle_name = "MyApp",
    deps = ["//path/to/src/valdi/my_module"],
)
```

**Module BUILD.bazel:**
```python
load("//bzl:valdi.bzl", "valdi_module")

valdi_module(
    name = "my_module",
    srcs = glob(["src/**/*.ts", "src/**/*.tsx"]) + ["tsconfig.json"],
    assets = glob(["res/**/*.{jpeg,jpg,png,svg,webp}"]),
    android = struct(
        class_path = "com.example.valdi.modules.my_module",
        native_deps = ["//path/to/android:native_module"],
        release = True,
    ),
    ios = struct(
        module_name = "SCCMyModule",
        native_deps = ["//path/to/ios:native_module"],
        release = True,
    ),
    native = struct(
        deps = ["//path/to/cpp:native_module_cpp"],
    ),
    deps = [
        "//src/valdi_modules/valdi_core",
        "//src/valdi_modules/valdi_tsx",
    ],
    visibility = ["//visibility:public"],
)
```

### 6. Native Bindings

Valdi supports type-safe bindings to native code:

**CppModule.d.ts:**
```typescript
declare module 'CppModule' {
  export function performCalculation(value: number): number;
  export function getNativeString(): string;
}
```

**NativeModule.d.ts:**
```typescript
declare module 'NativeModule' {
  export function showNativeAlert(message: string): void;
  export function getPlatformInfo(): { os: string; version: string };
}
```

**Usage in component:**
```tsx
import * as CppModule from 'CppModule';
import * as NativeModule from 'NativeModule';

class MyComponent extends Component<ViewModel, ComponentContext> {
  onMount() {
    const result = CppModule.performCalculation(42);
    const platform = NativeModule.getPlatformInfo();
  }
}
```

### 7. Cross-Platform Best Practices

**All changes must work across iOS, Android, and macOS:**

- Test on multiple platforms before committing
- Platform-specific code goes in dedicated directories (src/ios/, src/android/)
- Use Valdi's abstraction layer for platform differences
- Check AGENTS.md in repository for platform-specific guidance

**Performance is critical:**
- Valdi emphasizes rendering efficiency
- Use view recycling through Valdi's pooling systems
- Components render independently (no parent re-renders)
- Viewport-aware rendering for efficient scrolling

### 8. Development Workflow

**Initial setup:**
```bash
# Install Valdi CLI
pnpm install -g @snap/valdi

# Setup development environment (takes 10-20 minutes first time)
valdi dev_setup

# Verify installation
valdi doctor
```

**Creating a new project:**
```bash
mkdir my_project && cd my_project
valdi bootstrap
valdi install ios  # or android
```

**Development cycle:**
```bash
# Start hot reload for live updates
valdi hotreload

# After changing dependencies or resources
valdi projectsync
```

**Editor setup (VSCode/Cursor):**
1. Install shell commands from editor
2. Install extensions from Valdi release:
   - `valdi-vivaldi.vsix` (device logs, language support)
   - `valdi-debug.vsix` (JavaScript debugger)
3. Configure TypeScript workspace version

## Common Pitfalls

### 1. Using Web/React Patterns

**Problem:** Treating Valdi like React or web development.

```tsx
// WRONG - HTML elements don't exist
<div className="container">
  <span>Hello</span>
</div>

// CORRECT - Use Valdi native elements
<view style={styles.container}>
  <label>Hello</label>
</view>
```

### 2. CSS-Style Styling

**Problem:** Using CSS syntax for styles.

```tsx
// WRONG - CSS syntax
const styles = {
  container: {
    'background-color': '#fff',
    'font-size': '16px',
  }
};

// CORRECT - Camel case, numeric values
const styles = {
  container: {
    backgroundColor: '#FFFFFF',
    fontSize: 16,
  }
};
```

### 3. Modifying Auto-Generated Code

**Problem:** Editing Djinni-generated native bindings directly.

**Solution:** Always modify source files, never generated code. Regenerate bindings after source changes.

### 4. Wrong Build System

**Problem:** Using npm/yarn scripts, webpack, or other bundlers.

**Solution:** Valdi uses Bazel exclusively. Use `valdi` CLI commands.

### 5. Missing Platform Testing

**Problem:** Only testing on one platform.

**Solution:** Always verify changes work on iOS, Android, and macOS where applicable.

## ESLint Configuration

Standard Valdi ESLint setup:

```javascript
// .eslintrc.js
module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
    ecmaVersion: 2020,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  plugins: [
    '@typescript-eslint',
    'eslint-plugin-valdi',
    'rxjs',
    'import',
    'unused-imports',
  ],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  rules: {
    // Valdi-specific rules
  },
};
```

## TypeScript Configuration

Standard tsconfig.json for Valdi modules:

```json
{
  "extends": "../../_configs/tsconfig.json",
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "Valdi.createElement",
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}
```

## Available Libraries

Valdi provides these core modules:

| Module | Purpose |
|--------|---------|
| `valdi_core` | Core component system, lifecycle |
| `valdi_tsx` | TSX/JSX support |
| `valdi_protobuf` | Protobuf serialization |
| `valdi_http` | HTTP client |
| `valdi_storage` | Persistent encrypted storage |
| `valdi_navigation` | Navigation system |
| `valdi_rxjs` | RxJS integration |

## Debugging

**Using Hermes Debugger:**
- Available for JavaScript debugging
- Set breakpoints in VSCode with valdi-debug extension

**Using Valdi Inspector:**
- Inspect UI hierarchy
- View component state
- Performance profiling

## Quick Reference

### CLI Commands
| Command | Purpose |
|---------|---------|
| `valdi dev_setup` | Setup development environment |
| `valdi doctor` | Check environment health |
| `valdi bootstrap` | Create new project |
| `valdi install [platform]` | Install platform dependencies |
| `valdi hotreload` | Enable live updates |
| `valdi projectsync` | Sync project configuration |

### Lifecycle Methods
| Method | When Called |
|--------|-------------|
| `onCreate()` | Component initialization |
| `onMount()` | Added to view hierarchy |
| `onUnmount()` | Before removal from hierarchy |
| `onRender()` | Render component UI |

### Native Elements
| Element | HTML Equivalent |
|---------|-----------------|
| `<view>` | `<div>` |
| `<layout>` | Flexbox container |
| `<scroll>` | Scrollable div |
| `<label>` | `<span>` / `<p>` |
| `<image>` | `<img>` |
| `<video>` | `<video>` |

## References

For more details:
- `references/component-patterns.md` - Advanced component patterns
- `references/bazel-configuration.md` - Detailed Bazel setup
- `references/native-bindings.md` - Native code integration

## Additional Resources

- Valdi GitHub: https://github.com/Snapchat/Valdi
- AGENTS.md in repository for AI coding guidelines
- Discord community for support
- Codelabs in docs/ for guided tutorials

---

**Remember:** Valdi compiles to native code - think native, not web. Use Bazel for builds, pnpm for Node dependencies, and test on all target platforms.

