moldable

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Moldable App Development

Moldable应用开发

This skill provides comprehensive knowledge for building and modifying apps within the Moldable desktop application.
本技能为在Moldable桌面应用内构建和修改应用提供全面知识。

Quick Reference

快速参考

ResourcePath
App source code
~/.moldable/shared/apps/{app-id}/
App runtime data
~/.moldable/workspaces/{workspace-id}/apps/{app-id}/data/
Workspace config
~/.moldable/workspaces/{workspace-id}/config.json
MCP config
~/.moldable/shared/config/mcp.json
Skills
~/.moldable/shared/skills/{repo}/{skill}/
Environment
~/.moldable/shared/.env
资源路径
应用源代码
~/.moldable/shared/apps/{app-id}/
应用运行时数据
~/.moldable/workspaces/{workspace-id}/apps/{app-id}/data/
工作区配置
~/.moldable/workspaces/{workspace-id}/config.json
MCP配置
~/.moldable/shared/config/mcp.json
Skills
~/.moldable/shared/skills/{repo}/{skill}/
环境变量
~/.moldable/shared/.env

Default Tech Stack

默认技术栈

  • Framework: Next.js 16 + React 19 + TypeScript
  • Styling: Tailwind CSS 4 + shadcn/ui (semantic colors only)
  • State: TanStack Query v5
  • Storage: Filesystem via
    @moldable-ai/storage
  • Package Manager: pnpm
  • 框架: Next.js 16 + React 19 + TypeScript
  • 样式: Tailwind CSS 4 + shadcn/ui(仅使用语义化颜色)
  • 状态管理: TanStack Query v5
  • 存储: 基于
    @moldable-ai/storage
    的文件系统
  • 包管理器: pnpm

Creating Apps

创建应用

ALWAYS use the
scaffoldApp
tool
— never create app files manually.
typescript
scaffoldApp({
  appId: "expense-tracker",   // lowercase, hyphens only
  name: "Expense Tracker",    // Display name
  icon: "💰",                 // Emoji icon
  description: "Track expenses and generate reports",
  widgetSize: "medium",       // small, medium, or large
  extraDependencies: {        // Optional npm packages
    "zod": "^3.0.0"
  }
})
After scaffolding, customize:
  • src/app/page.tsx
    — Main app view
  • src/app/widget/page.tsx
    — Widget view
  • src/app/api/
    — API routes
  • src/components/
    — React components
必须使用
scaffoldApp
工具
— 切勿手动创建应用文件。
typescript
scaffoldApp({
  appId: "expense-tracker",   // lowercase, hyphens only
  name: "Expense Tracker",    // Display name
  icon: "💰",                 // Emoji icon
  description: "Track expenses and generate reports",
  widgetSize: "medium",       // small, medium, or large
  extraDependencies: {        // Optional npm packages
    "zod": "^3.0.0"
  }
})
脚手架搭建完成后,可自定义以下内容:
  • src/app/page.tsx
    — 应用主视图
  • src/app/widget/page.tsx
    — 小组件视图
  • src/app/api/
    — API路由
  • src/components/
    — React组件

Detailed References

详细参考

Read these for in-depth guidance:
如需深入指导,请阅读以下文档:

Core Concepts

核心概念

  • references/app-lifecycle.md — Creating, starting, managing, and deleting apps
  • references/app-scaffold.mdRequired files, lint rules, templates for new apps
  • references/workspaces.md — Workspace system, data isolation, environment layering
  • references/configuration.md — moldable.json, config.json, environment variables
  • references/app-lifecycle.md — 应用的创建、启动、管理与删除
  • references/app-scaffold.md — 新应用的必填文件、代码规范、模板
  • references/workspaces.md — 工作区系统、数据隔离、环境分层
  • references/configuration.md — moldable.json、config.json、环境变量

Implementation Patterns

实现模式

  • references/ui.md@moldable-ai/ui components, shadcn/ui, themes, rich text editor
  • references/storage-patterns.md — Filesystem storage, React Query, workspace-aware APIs
  • references/desktop-apis.md — postMessage APIs (open-url, show-in-folder, set-chat-input, save-file)
  • references/skills-mcps.md — Skills library, MCP configuration, custom MCP servers
  • references/ui.md@moldable-ai/ui组件、shadcn/ui、主题、富文本编辑器
  • references/storage-patterns.md — 文件系统存储、React Query、工作区感知API
  • references/desktop-apis.md — postMessage API(open-url、show-in-folder、set-chat-input、save-file)
  • references/skills-mcps.md — Skills库、MCP配置、自定义MCP服务器

Essential Patterns

必备实现模式

1. UI Components (@moldable-ai/ui)

1. UI组件 (@moldable-ai/ui)

Always use
@moldable-ai/ui
for all UI work. It includes shadcn/ui components, theme support, and a rich text editor.
tsx
// Import components from @moldable-ai/ui (NOT from shadcn directly)
import { 
  Button, Card, Input, Dialog, Select, Tabs,
  ThemeProvider, WorkspaceProvider, useTheme,
  Markdown, CodeBlock, WidgetLayout,
  downloadFile, sendToMoldable
} from '@moldable-ai/ui'

// For rich text editing
import { MarkdownEditor } from '@moldable-ai/editor'
Use semantic colors only:
tsx
// ✅ Correct
<div className="bg-background text-foreground border-border" />
<Button className="bg-primary text-primary-foreground" />

// ❌ Wrong - raw colors don't adapt to theme
<div className="bg-white text-gray-900" />
See references/ui.md for complete component list and usage.
所有UI工作必须使用
@moldable-ai/ui
,它包含shadcn/ui组件、主题支持和富文本编辑器。
tsx
// Import components from @moldable-ai/ui (NOT from shadcn directly)
import { 
  Button, Card, Input, Dialog, Select, Tabs,
  ThemeProvider, WorkspaceProvider, useTheme,
  Markdown, CodeBlock, WidgetLayout,
  downloadFile, sendToMoldable
} from '@moldable-ai/ui'

// For rich text editing
import { MarkdownEditor } from '@moldable-ai/editor'
仅使用语义化颜色:
tsx
// ✅ Correct
<div className="bg-background text-foreground border-border" />
<Button className="bg-primary text-primary-foreground" />

// ❌ Wrong - raw colors don't adapt to theme
<div className="bg-white text-gray-900" />
完整组件列表及用法请查看references/ui.md

2. Workspace-Aware Storage

2. 工作区感知存储

All apps must isolate data per workspace:
tsx
// Client - use workspaceId in query keys
const { workspaceId, fetchWithWorkspace } = useWorkspace()
const { data } = useQuery({
  queryKey: ['items', workspaceId],  // ← Include workspace!
  queryFn: () => fetchWithWorkspace('/api/items').then(r => r.json())
})

// Server - extract workspace from request
import { getWorkspaceFromRequest, getAppDataDir } from '@moldable-ai/storage'

export async function GET(request: Request) {
  const workspaceId = getWorkspaceFromRequest(request)
  const dataDir = getAppDataDir(workspaceId)
  // Read/write files in dataDir
}
所有应用必须按工作区隔离数据:
tsx
// Client - use workspaceId in query keys
const { workspaceId, fetchWithWorkspace } = useWorkspace()
const { data } = useQuery({
  queryKey: ['items', workspaceId],  // ← Include workspace!
  queryFn: () => fetchWithWorkspace('/api/items').then(r => r.json())
})

// Server - extract workspace from request
import { getWorkspaceFromRequest, getAppDataDir } from '@moldable-ai/storage'

export async function GET(request: Request) {
  const workspaceId = getWorkspaceFromRequest(request)
  const dataDir = getAppDataDir(workspaceId)
  // Read/write files in dataDir
}

3. Desktop Integration

3. 桌面端集成

Apps communicate with Moldable desktop via postMessage:
typescript
// Open external URL
window.parent.postMessage({ type: 'moldable:open-url', url: 'https://...' }, '*')

// Show file in Finder
window.parent.postMessage({ type: 'moldable:show-in-folder', path: '/path/to/file' }, '*')

// Pre-populate chat input
window.parent.postMessage({ type: 'moldable:set-chat-input', text: 'Help me...' }, '*')

// Provide context to AI
window.parent.postMessage({ 
  type: 'moldable:set-chat-instructions', 
  text: 'User is viewing meeting #123...' 
}, '*')
应用通过postMessage与Moldable桌面端通信:
typescript
// Open external URL
window.parent.postMessage({ type: 'moldable:open-url', url: 'https://...' }, '*')

// Show file in Finder
window.parent.postMessage({ type: 'moldable:show-in-folder', path: '/path/to/file' }, '*')

// Pre-populate chat input
window.parent.postMessage({ type: 'moldable:set-chat-input', text: 'Help me...' }, '*')

// Provide context to AI
window.parent.postMessage({ 
  type: 'moldable:set-chat-instructions', 
  text: 'User is viewing meeting #123...' 
}, '*')

4. Layout Setup

4. 布局设置

Required providers for Moldable apps:
tsx
// src/app/layout.tsx
import { ThemeProvider, WorkspaceProvider } from '@moldable-ai/ui'
import { QueryProvider } from '@/lib/query-provider'

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider>
          <WorkspaceProvider>
            <QueryProvider>{children}</QueryProvider>
          </WorkspaceProvider>
        </ThemeProvider>
      </body>
    </html>
  )
}
Moldable应用所需的必备提供者:
tsx
// src/app/layout.tsx
import { ThemeProvider, WorkspaceProvider } from '@moldable-ai/ui'
import { QueryProvider } from '@/lib/query-provider'

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider>
          <WorkspaceProvider>
            <QueryProvider>{children}</QueryProvider>
          </WorkspaceProvider>
        </ThemeProvider>
      </body>
    </html>
  )
}

5. Adding Dependencies

5. 添加依赖

Use
sandbox: false
for package manager commands:
typescript
await runCommand({
  command: 'cd ~/.moldable/shared/apps/my-app && pnpm add zod',
  sandbox: false  // Required for network access
})
执行包管理器命令时需设置
sandbox: false
typescript
await runCommand({
  command: 'cd ~/.moldable/shared/apps/my-app && pnpm add zod',
  sandbox: false  // Required for network access
})

App Management Tools

应用管理工具

ToolPurposeReversible
scaffoldApp
Create new app
getAppInfo
Check which workspaces use an app
unregisterApp
Remove from current workspace only✅ Re-add later
deleteAppData
Delete app's data (keep installed)❌ Data lost
deleteApp
Permanently delete from ALL workspaces❌ Everything lost
工具用途可撤销性
scaffoldApp
创建新应用
getAppInfo
查看哪些工作区使用了该应用
unregisterApp
仅从当前工作区移除✅ 可重新添加
deleteAppData
删除应用数据(保留应用安装状态)❌ 数据丢失不可恢复
deleteApp
永久从所有工作区删除❌ 所有数据及应用文件丢失

File Structure

文件结构

~/.moldable/
├── shared/
│   ├── apps/{app-id}/              # App source code
│   │   ├── moldable.json           # App manifest
│   │   ├── package.json
│   │   └── src/
│   ├── skills/{repo}/{skill}/      # Skills library
│   ├── mcps/{mcp-name}/            # Custom MCP servers
│   └── config/mcp.json             # Shared MCP config
└── workspaces/{workspace-id}/
    ├── config.json                 # Registered apps
    ├── .env                        # Workspace env overrides
    ├── apps/{app-id}/data/         # App runtime data
    └── conversations/              # Chat history
~/.moldable/
├── shared/
│   ├── apps/{app-id}/              # App source code
│   │   ├── moldable.json           # App manifest
│   │   ├── package.json
│   │   └── src/
│   ├── skills/{repo}/{skill}/      # Skills library
│   ├── mcps/{mcp-name}/            # Custom MCP servers
│   └── config/mcp.json             # Shared MCP config
└── workspaces/{workspace-id}/
    ├── config.json                 # Registered apps
    ├── .env                        # Workspace env overrides
    ├── apps/{app-id}/data/         # App runtime data
    └── conversations/              # Chat history

Common Mistakes to Avoid

需避免的常见错误

  1. ❌ Creating apps manually — Always use
    scaffoldApp
  2. ❌ Using localStorage — Use filesystem storage
  3. ❌ Forgetting workspaceId — Include in query keys and API calls
  4. ❌ Hardcoding paths — Use
    getAppDataDir()
    for portability
  5. ❌ Using raw colors — Use shadcn semantic colors (
    bg-background
    , not
    bg-gray-100
    )
  6. ❌ Running pnpm with sandbox — Set
    sandbox: false
    for network access
  1. ❌ 手动创建应用 — 必须使用
    scaffoldApp
  2. ❌ 使用localStorage — 应使用文件系统存储
  3. ❌ 遗漏workspaceId — 需包含在查询键和API调用中
  4. ❌ 硬编码路径 — 使用
    getAppDataDir()
    保证可移植性
  5. ❌ 使用原始颜色 — 使用shadcn语义化颜色(如
    bg-background
    ,而非
    bg-gray-100
  6. ❌ 在沙箱中运行pnpm — 需设置
    sandbox: false
    以获取网络权限

Study Existing Apps

参考现有应用

For complex features, reference apps in
~/.moldable/shared/apps/
:
  • scribo — Translation journal with language selection
  • meetings — Audio recording with real-time transcription
  • calendar — Google Calendar integration with OAuth
These demonstrate data fetching, storage patterns, API routes, and UI components.
如需实现复杂功能,可参考
~/.moldable/shared/apps/
中的应用:
  • scribo — 带语言选择的翻译日志应用
  • meetings — 带实时转写的音频录制应用
  • calendar — 集成OAuth的Google日历应用
这些示例展示了数据获取、存储模式、API路由和UI组件的实现方式。