# Send FOSMVVM React View Generator to your agent
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
## Fast path
- Download the package from Yavira.
- Extract it into a folder your agent can access.
- Paste one of the prompts below and point your agent at the extracted folder.
## Suggested prompts
### New install

```text
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
```
### Upgrade existing

```text
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
```
## Machine-readable fields
```json
{
  "schemaVersion": "1.0",
  "item": {
    "slug": "fosmvvm-react-view-generator",
    "name": "FOSMVVM React View Generator",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/foscomputerservices/fosmvvm-react-view-generator",
    "canonicalUrl": "https://clawhub.ai/foscomputerservices/fosmvvm-react-view-generator",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadUrl": "/downloads/fosmvvm-react-view-generator",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=fosmvvm-react-view-generator",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "packageFormat": "ZIP package",
    "primaryDoc": "SKILL.md",
    "includedAssets": [
      "SKILL.md",
      "reference.md"
    ],
    "downloadMode": "redirect",
    "sourceHealth": {
      "source": "tencent",
      "slug": "fosmvvm-react-view-generator",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-03T03:10:08.004Z",
      "expiresAt": "2026-05-10T03:10:08.004Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=fosmvvm-react-view-generator",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=fosmvvm-react-view-generator",
        "contentDisposition": "attachment; filename=\"fosmvvm-react-view-generator-2.0.6.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "fosmvvm-react-view-generator"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/fosmvvm-react-view-generator"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    }
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/fosmvvm-react-view-generator",
    "downloadUrl": "https://openagent3.xyz/downloads/fosmvvm-react-view-generator",
    "agentUrl": "https://openagent3.xyz/skills/fosmvvm-react-view-generator/agent",
    "manifestUrl": "https://openagent3.xyz/skills/fosmvvm-react-view-generator/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/fosmvvm-react-view-generator/agent.md"
  }
}
```
## Documentation

### FOSMVVM React View Generator

Generate React components that render FOSMVVM ViewModels.

### Conceptual Foundation

For full architecture context, see FOSMVVMArchitecture.md | OpenClaw reference

In FOSMVVM, React components are thin rendering layers that display ViewModels:

┌─────────────────────────────────────────────────────────────┐
│                    ViewModelView Pattern                     │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ViewModel (Data)          React Component                  │
│  ┌──────────────────┐     ┌──────────────────┐             │
│  │ title: String    │────►│ <h1>{vm.title}   │             │
│  │ items: [Item]    │────►│ {vm.items.map()} │             │
│  │ isEnabled: Bool  │────►│ disabled={!...}  │             │
│  └──────────────────┘     └──────────────────┘             │
│                                                              │
│  ServerRequest (Actions)                                     │
│  ┌──────────────────┐     ┌──────────────────┐             │
│  │ processRequest() │◄────│ <Component.bind  │             │
│  │                  │     │   requestType={} │             │
│  └──────────────────┘     └──────────────────┘             │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Key principle: Components don't transform or compute data. They render what the ViewModel provides.

### View-ViewModel Alignment

The component filename should match the ViewModel it renders.

src/
  viewmodels/
    {Feature}ViewModel.js           ←──┐
    {Entity}CardViewModel.js        ←──┼── Same names
                                        │
  components/                           │
    {Feature}/                          │
      {Feature}View.jsx             ────┤  (renders {Feature}ViewModel)
      {Entity}CardView.jsx          ────┘  (renders {Entity}CardViewModel)

This alignment provides:

Discoverability - Find the component for any ViewModel instantly
Consistency - Same naming discipline as SwiftUI and Leaf
Maintainability - Changes to ViewModel are reflected in component location

### TDD Workflow

This skill generates tests FIRST, implementation SECOND in a single invocation:

1. Reference ViewModel and ServerRequest details from conversation context
2. Generate .test.js file → Tests FAIL (no implementation yet)
3. Generate .jsx file → Tests PASS
4. Verify completeness (both files exist)
5. User runs \`npm test\` → All tests pass ✓

Context-aware: Skill references conversation understanding of requirements. No file parsing or Q&A needed.

### 1. viewModelComponent() Wrapper

Every component is wrapped with viewModelComponent():

const MyView = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return <div>{viewModel.title}</div>;
});

export default MyView;

Required:

Use FOSMVVM.viewModelComponent() from global namespace (loaded via script tag)
Component function receives { viewModel } prop
No imports needed - FOSMVVM utilities loaded via <script> tags

### 2. The .bind() Pattern

Parent components use .bind() to invoke ServerRequests:

// Parent component
function Dashboard() {
  return (
    <div>
      <TaskList.bind({
        requestType: 'GetTasksRequest',
        params: { status: 'active' }
      }) />
    </div>
  );
}

The .bind() pattern:

Child components receive data via ServerRequest
Parent specifies requestType and params
WASM bridge handles request → ViewModel → component rendering
No fetch() calls, no hardcoded URLs

### 3. Error ViewModel Handling

Error ViewModels are rendered like any other ViewModel:

const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  // Handle error ViewModels
  if (viewModel.errorType === 'NotFoundError') {
    return (
      <div className="error">
        <p>{viewModel.message}</p>
        <p>{viewModel.suggestedAction}</p>
      </div>
    );
  }

  if (viewModel.errorType === 'ValidationError') {
    return (
      <div className="validation-error">
        <h3>{viewModel.title}</h3>
        <ul>
          {viewModel.errors.map(err => (
            <li key={err.field}>{err.message}</li>
          ))}
        </ul>
      </div>
    );
  }

  // Render success ViewModel
  return (
    <div className="task-card">
      <h3>{viewModel.title}</h3>
      <p>{viewModel.description}</p>
    </div>
  );
});

Key principles:

No generic error handling
Each error type has its own ViewModel
Component conditionally renders based on errorType property
Error rendering is just data rendering

### 4. Navigation Intents (Not URLs)

Use navigation intents, not hardcoded paths:

// FOSMVVM utilities loaded via <script> tag, available on global namespace

// ❌ NEVER
<a href="/tasks/123">View Task</a>

// ✅ ALWAYS
<FOSMVVM.Link to={{ intent: 'viewTask', id: viewModel.id }}>
  {viewModel.linkText}
</FOSMVVM.Link>

Navigation patterns:

Use FOSMVVM.Link from global namespace (loaded via script tag)
Use intent property, not hardcoded paths
Router maps intents to routes
Platform-independent navigation

### Display-Only Components

Components that just render data (no user interactions):

const InfoCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return (
    <div className="info-card">
      <h2>{viewModel.title}</h2>
      <p>{viewModel.description}</p>

      {viewModel.isActive && (
        <span className="badge">{viewModel.activeLabel}</span>
      )}
    </div>
  );
});

export default InfoCard;

Characteristics:

Just renders ViewModel properties
No event handlers (onClick, onSubmit, etc.)
May have conditional rendering based on ViewModel state
No .bind() calls to child components

### Interactive Components

Components with user actions that trigger ServerRequests:

const ActionCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return (
    <div className="action-card">
      <h2>{viewModel.title}</h2>
      <p>{viewModel.description}</p>

      <div className="actions">
        <button
          onClick={() => viewModel.operations.performAction()}
          disabled={!viewModel.canPerformAction}
        >
          {viewModel.actionLabel}
        </button>

        <button onClick={() => viewModel.operations.cancel()}>
          {viewModel.cancelLabel}
        </button>
      </div>
    </div>
  );
});

export default ActionCard;

### List Components

Components that render collections:

const TaskList = FOSMVVM.viewModelComponent(({ viewModel }) => {
  if (viewModel.isEmpty) {
    return <div className="empty">{viewModel.emptyMessage}</div>;
  }

  return (
    <div className="task-list">
      <h2>{viewModel.title}</h2>
      <p>{viewModel.totalCount}</p>

      {viewModel.tasks.map(task => (
        <TaskCard.bind({
          requestType: 'GetTaskRequest',
          params: { id: task.id }
        }) />
      ))}
    </div>
  );
});

export default TaskList;

### Form Components

Components with validated input fields:

const SignInForm = FOSMVVM.viewModelComponent(({ viewModel }) => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [errors, setErrors] = useState({});

  const handleSubmit = async (e) => {
    e.preventDefault();

    const result = await viewModel.operations.submit({
      email,
      password
    });

    if (result.validationErrors) {
      setErrors(result.validationErrors);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>{viewModel.emailLabel}</label>
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder={viewModel.emailPlaceholder}
        />
        {errors.email && <span className="error">{errors.email}</span>}
      </div>

      <div>
        <label>{viewModel.passwordLabel}</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder={viewModel.passwordPlaceholder}
        />
        {errors.password && <span className="error">{errors.password}</span>}
      </div>

      <button type="submit" disabled={viewModel.submitDisabled}>
        {viewModel.submitLabel}
      </button>
    </form>
  );
});

export default SignInForm;

### When to Use This Skill

Creating a new React component for a FOSMVVM app
Building UI to render a ViewModel
Migrating Leaf templates to React
Following an implementation plan that requires new views
Creating forms with validation
Building list views that compose child components

### What This Skill Generates

Two files per invocation:

FileLocationPurpose{ViewName}View.test.jssrc/components/{Feature}/Jest + React Testing Library tests{ViewName}View.jsxsrc/components/{Feature}/React component

Test file generated FIRST (tests fail initially)
Implementation file generated SECOND (tests pass)

Note: The corresponding ViewModel and ServerRequest should already exist (use other FOSMVVM generator skills).

### Project Structure Configuration

PlaceholderDescriptionExample{ViewName}View name (without "View" suffix)TaskList, SignIn{Feature}Feature/module groupingTasks, Auth

### Pattern Implementation

This skill references conversation context to determine component structure:

### Component Type Detection

From conversation context, the skill identifies:

ViewModel structure (from prior discussion or specifications read by Claude)
ServerRequest details (from requirements already in context)
Component category: Display-only, interactive, form, or list
Error ViewModels to handle

### Test Generation (FIRST)

Based on component type, generates .test.js with:

All components: Success ViewModel rendering, error ViewModel rendering
Interactive: Button clicks, operation verification
Form: Input changes, validation errors, submission
List: Empty state, multiple items, child binding

### Component Generation (SECOND)

Generates .jsx following patterns:

Import viewModelComponent wrapper
Handle error ViewModels with conditional rendering
Render success ViewModel
Add interactions (if interactive)
Add form state (if form)
Add child .bind() calls (if container)
Export wrapped component

### Context Sources

Skill references information from:

Prior conversation: Requirements discussed with user
Specification files: If Claude has read specifications into context
ViewModel definitions: From codebase or discussion

### Step 5: Verify Completeness

Check:

.test.js file exists
 .jsx file exists
 Component uses FOSMVVM.viewModelComponent() wrapper
 Component accesses FOSMVVM functions from global namespace
 Tests cover success and error ViewModels
 Tests cover user interactions (if applicable)

### Pattern: No Business Logic in Components

// ❌ BAD - Component is transforming data
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  const daysLeft = Math.ceil((viewModel.dueDate - Date.now()) / 86400000);
  return <span>{daysLeft} days remaining</span>;
});

// ✅ GOOD - ViewModel provides shaped result
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return <span>{viewModel.daysRemainingText}</span>;
});

### Pattern: No fetch() Calls

// ❌ BAD - Component making HTTP requests
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(\`/api/tasks/${viewModel.id}\`)
      .then(r => r.json())
      .then(setData);
  }, [viewModel.id]);

  return <div>{data?.title}</div>;
});

// ✅ GOOD - Parent uses .bind() to invoke ServerRequest
<TaskCard.bind({
  requestType: 'GetTaskRequest',
  params: { id: taskId }
}) />

### Pattern: Error ViewModels Are Data

// ❌ BAD - Generic error handling
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  if (viewModel.error) {
    return <div>Error: {viewModel.error.message}</div>;
  }
  return <div>{viewModel.title}</div>;
});

// ✅ GOOD - Specific error ViewModels
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  if (viewModel.errorType === 'NotFoundError') {
    return (
      <div className="not-found">
        <h3>{viewModel.errorTitle}</h3>
        <p>{viewModel.errorMessage}</p>
        <p>{viewModel.suggestedAction}</p>
      </div>
    );
  }

  if (viewModel.errorType === 'ValidationError') {
    return (
      <div className="validation-error">
        <h3>{viewModel.errorTitle}</h3>
        <ul>
          {viewModel.validationErrors.map(err => (
            <li key={err.field}>{err.message}</li>
          ))}
        </ul>
      </div>
    );
  }

  return <div>{viewModel.title}</div>;
});

### Pattern: Navigation Intents

// ❌ BAD - Hardcoded URLs
const TaskRow = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return (
    <div>
      <a href={\`/tasks/${viewModel.id}\`}>{viewModel.title}</a>
    </div>
  );
});

// ✅ GOOD - Navigation intents
// FOSMVVM utilities loaded via <script> tag, available on global namespace

const TaskRow = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return (
    <div>
      <FOSMVVM.Link to={{ intent: 'viewTask', id: viewModel.id }}>
        {viewModel.title}
      </FOSMVVM.Link>
    </div>
  );
});

### File Organization

src/components/
├── {Feature}/
│   ├── {Feature}View.jsx             # Full page → {Feature}ViewModel
│   ├── {Feature}View.test.js         # Tests for {Feature}View
│   ├── {Entity}CardView.jsx          # Child component → {Entity}CardViewModel
│   ├── {Entity}CardView.test.js      # Tests for {Entity}CardView
│   └── {Entity}RowView.jsx           # Child component → {Entity}RowViewModel
├── Shared/
│   ├── HeaderView.jsx                # Shared components
│   └── FooterView.jsx

### Computing Data in Components

// ❌ BAD - Component is transforming data
const UserCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return <div>{viewModel.firstName} {viewModel.lastName}</div>;
});

// ✅ GOOD - ViewModel provides shaped result
const UserCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return <div>{viewModel.fullName}</div>;
});

### Making HTTP Requests Directly

// ❌ BAD - fetch() call in component
const TaskList = FOSMVVM.viewModelComponent(({ viewModel }) => {
  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    fetch('/api/tasks').then(r => r.json()).then(setTasks);
  }, []);

  return <div>{tasks.map(t => <div key={t.id}>{t.title}</div>)}</div>;
});

// ✅ GOOD - Parent uses .bind() with ServerRequest
<TaskList.bind({
  requestType: 'GetTasksRequest',
  params: {}
}) />

### Hardcoding Text

// ❌ BAD - Not localizable
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return (
    <button onClick={viewModel.operations.submit}>
      Submit
    </button>
  );
});

// ✅ GOOD - ViewModel provides localized text
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return (
    <button onClick={viewModel.operations.submit}>
      {viewModel.submitLabel}
    </button>
  );
});

### Using Hardcoded URLs

// ❌ BAD - Hardcoded path
const TaskRow = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return <a href={\`/tasks/${viewModel.id}\`}>{viewModel.title}</a>;
});

// ✅ GOOD - Navigation intent
// FOSMVVM utilities loaded via <script> tag, available on global namespace

const TaskRow = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return (
    <FOSMVVM.Link to={{ intent: 'viewTask', id: viewModel.id }}>
      {viewModel.title}
    </FOSMVVM.Link>
  );
});

### Not Wrapping with viewModelComponent()

// ❌ BAD - Missing viewModelComponent() wrapper
const TaskCard = ({ viewModel }) => {
  return <div>{viewModel.title}</div>;
};
export default TaskCard;

// ✅ GOOD - Wrapped with viewModelComponent()
const TaskCard = FOSMVVM.viewModelComponent(({ viewModel }) => {
  return <div>{viewModel.title}</div>;
});
export default TaskCard;

### Mismatched Filenames

// ❌ BAD - Filename doesn't match ViewModel
ViewModel: TaskListViewModel
Component: Tasks.jsx

// ✅ GOOD - Aligned names
ViewModel: TaskListViewModel
Component: TaskListView.jsx

### File Templates

See reference.md for complete file templates.

### Naming Conventions

ConceptConventionExampleComponent file{Name}View.jsxTaskListView.jsx, SignInView.jsxTest file{Name}View.test.jsTaskListView.test.jsComponent function{Name}ViewTaskListView, SignInViewViewModel propviewModelAlways viewModel

### Test: Rendering with Success ViewModel

it('renders task card with ViewModel', () => {
  const viewModel = {
    title: 'Test Task',
    description: 'Test Description',
    dueDate: 'Jan 30, 2026'
  };

  render(<TaskCard viewModel={viewModel} />);

  expect(screen.getByText('Test Task')).toBeInTheDocument();
  expect(screen.getByText('Test Description')).toBeInTheDocument();
});

### Test: Rendering with Error ViewModel

it('renders NotFoundViewModel', () => {
  const viewModel = {
    errorType: 'NotFoundError',
    errorTitle: 'Task Not Found',
    errorMessage: 'The task you requested does not exist',
    suggestedAction: 'Try searching for a different task'
  };

  render(<TaskCard viewModel={viewModel} />);

  expect(screen.getByText('Task Not Found')).toBeInTheDocument();
  expect(screen.getByText(/does not exist/)).toBeInTheDocument();
});

### Test: User Interaction

it('calls operation when button clicked', () => {
  const mockOperation = jest.fn();
  const viewModel = {
    title: 'Test Task',
    submitLabel: 'Complete Task',
    operations: {
      complete: mockOperation
    }
  };

  render(<TaskCard viewModel={viewModel} />);

  fireEvent.click(screen.getByText('Complete Task'));

  expect(mockOperation).toHaveBeenCalled();
});

### How to Use This Skill

Invocation:

/fosmvvm-react-view-generator

Prerequisites:

ViewModel and ServerRequest details are understood from conversation
Optionally, specification files have been read into context
Component requirements (display-only, interactive, form, list) are clear from discussion

Output:

{ComponentName}.test.js - Generated FIRST (tests fail)
{ComponentName}.jsx - Generated SECOND (tests pass)

Workflow integration:
This skill is typically used after discussing requirements or reading specification files. The skill references that context automatically—no file paths or Q&A needed.

### See Also

Architecture Patterns - Mental models and patterns
FOSMVVMArchitecture.md - Full FOSMVVM architecture
fosmvvm-swiftui-view-generator - SwiftUI equivalent
fosmvvm-leaf-view-generator - Leaf equivalent
reference.md - Complete file templates

### Version History

VersionDateChanges1.02026-01-23Initial skill for React view generation based on Kairos requirements
## Trust
- Source: tencent
- Verification: Indexed source record
- Publisher: foscomputerservices
- Version: 2.0.6
## Source health
- Status: healthy
- Item download looks usable.
- Yavira can redirect you to the upstream package for this item.
- Health scope: item
- Reason: direct_download_ok
- Checked at: 2026-05-03T03:10:08.004Z
- Expires at: 2026-05-10T03:10:08.004Z
- Recommended action: Download for OpenClaw
## Links
- [Detail page](https://openagent3.xyz/skills/fosmvvm-react-view-generator)
- [Send to Agent page](https://openagent3.xyz/skills/fosmvvm-react-view-generator/agent)
- [JSON manifest](https://openagent3.xyz/skills/fosmvvm-react-view-generator/agent.json)
- [Markdown brief](https://openagent3.xyz/skills/fosmvvm-react-view-generator/agent.md)
- [Download page](https://openagent3.xyz/downloads/fosmvvm-react-view-generator)