# App Creator

> Develop and maintain frontend apps in `<AgentWorkspaceRoot>/app` such as tools, mini-games, landing pages, and interactive experiences. Use when the user asks to create, iterate on, or fix an app or page.

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

---


# App Creator

Use this skill to develop and maintain frontend apps in **`<AgentWorkspaceRoot>/app`**, including utilities, mini-games, campaign pages, and other interactive experiences.

## When to Use

- The user wants a tool, small app, or webpage built.
- The user wants existing app code updated, improved, or fixed.
- The user says things like "build an XXX app", "make an XXX tool", or "develop XXX".

## Core Conventions

- Store all app code under the `app` directory. This directory is only for frontend projects, and dependencies should be managed with **pnpm**.
- App metadata is stored in `app/app.json`:
  - `name`: the app name shown in the app module title.
  - `buildTime`: the last build time, updated automatically by the system after builds and usually not edited manually.
- When the app name needs to change, update the `name` field in `app/app.json` instead of hardcoding the title in UI code.
- Apps should default to **Vite + TypeScript + React** and enable `vite-plugin-singlefile` so the app can be bundled into a single file.
- If the task is a mini-game, use **Phaser**.

## Built-in SDK (Native Capabilities)

In the app preview environment, a built-in SDK is injected automatically and can be used directly:

- Global object: `window.KianNativeSDK` (alias: `window.kian`)
- Capabilities in the current version:
  - Camera: `openCamera()` / `getUserMedia({ video: true })`
  - Microphone: `openMicrophone()` / `getUserMedia({ audio: true })`
  - Screen capture: `getDisplayMedia()`
  - Device enumeration: `enumerateDevices()`
  - Permission status: `getPermissions()`
  - Stream cleanup: `stopStream(stream)`
  - Save files to the asset library: `saveFileToAssets(fileName, data)`

### Media Example

```ts
const sdk = window.KianNativeSDK;

const mediaStream = await sdk.media.getUserMedia({ audio: true, video: true });
const devices = await sdk.media.enumerateDevices();
const permissions = await sdk.media.getPermissions();

// Release hardware resources when finished.
sdk.media.stopStream(mediaStream);
```

### Save Files to the Asset Library

`sdk.saveFileToAssets(fileName, data)` saves files generated by the app, such as images, audio, or text, into the project's asset library.

- `fileName`: file name including extension, such as `"photo.png"` or `"recording.wav"`
- `data`: file contents, supporting `Blob`, `ArrayBuffer`, `TypedArray` (for example `Uint8Array`), or `string` for text files
- Return value: `Promise<Asset>`, containing metadata for the saved asset such as `id`, `name`, and `url`

```ts
const sdk = window.KianNativeSDK;

// Save a canvas snapshot.
const canvas = document.querySelector("canvas");
const blob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
const asset = await sdk.saveFileToAssets("screenshot.png", blob);
console.log("Saved:", asset.name, asset.url);

// Save a text file.
await sdk.saveFileToAssets("data.json", JSON.stringify({ key: "value" }));

// Save an audio blob.
const audioBlob = /* obtained from MediaRecorder */;
await sdk.saveFileToAssets("recording.wav", audioBlob);
```

Constraints and notes:

- Prefer `window.KianNativeSDK`; do not wrap it with another redundant bridge API.
- Before opening the camera or microphone, check `sdk.media.isSupported()` and handle failures such as denied permissions or unavailable devices.
- Always call `stopStream` after using media streams so the camera or microphone is not left open.
- `saveFileToAssets` is available only in the preview environment and saves into the current project's asset library.
- The SDK primarily targets the app-module preview WebView. If the user needs the app to run outside that environment, add an explicit fallback strategy.

## Build and Preview

After every code update, you must build first, for example with `pnpm build`, then preview the result and use the app refresh tool. Otherwise the latest changes will not be visible.

## Prerequisite Check

Before starting development, run `node --version` and `pnpm --version` to confirm Node.js and pnpm are installed correctly. If either is missing, tell the user, provide installation guidance, and help install them after confirmation. Reference example:

```bash
# Download and install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash

# in lieu of restarting the shell
\. "$HOME/.nvm/nvm.sh"

# Download and install Node.js:
nvm install 24

# Verify the Node.js version:
node -v # Should print "v24.14.0".

# Download and install pnpm:
corepack enable pnpm

# Verify pnpm version:
pnpm -v
```

## Recommended Workflow

1. **Understand the request**: clarify what kind of app the user wants.
2. **Run the prerequisite check**: confirm Node.js and pnpm are installed.
3. **Inspect the existing project**: check whether `app` already contains a project and decide whether to create or modify.
4. **Write code**: create or update files under `app`.
5. **Build**: run `pnpm build`.
6. **Refresh the preview**: use the app refresh tool so the user can see the latest result.

