moldable

SKILL.md

Moldable App Development

This skill provides comprehensive knowledge for building and modifying apps within the Moldable desktop application.

Quick Reference

Resource Path
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

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

Creating Apps

ALWAYS use the scaffoldApp tool — never create app files manually.

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

Detailed References

Read these for in-depth guidance:

Core Concepts

Implementation Patterns

Essential Patterns

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

Always use @moldable-ai/ui for all UI work. It includes shadcn/ui components, theme support, and a rich text editor.

// 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:

// āœ… 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.

2. Workspace-Aware Storage

All apps must isolate data per workspace:

// 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

Apps communicate with Moldable desktop via postMessage:

// 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

Required providers for Moldable apps:

// 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

Use sandbox: false for package manager commands:

await runCommand({
  command: 'cd ~/.moldable/shared/apps/my-app && pnpm add zod',
  sandbox: false  // Required for network access
})

App Management Tools

Tool Purpose Reversible
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

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

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

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.

Weekly Installs
6
First Seen
Jan 24, 2026
Installed on
codex6
opencode5
gemini-cli5
antigravity5
claude-code5
windsurf5