refactor: replace raw HTML elements with design system components

- Replace <select>, <input>, <label>, <textarea> with UI components
- Update various dashboard and docs pages
- Simplify unsandbox package.json
- Add DESIGN_SYSTEM.md documentation
- Add Claude skills configuration
This commit is contained in:
Ajax Davis 2026-01-16 16:52:44 +10:00
parent 7d9321d9c6
commit 23d5159b28
26 changed files with 1280 additions and 335 deletions

View file

@ -0,0 +1,102 @@
---
description: Develop and validate TPMJS tools using the blocks CLI
---
Help the user develop new tools for the TPMJS registry using the blocks CLI. This workflow covers defining tools in blocks.yml, implementing them with AI SDK v6, validating with the blocks CLI, and publishing to npm.
## Development Workflow
### 1. Define Tool in blocks.yml
Add tool definition to `packages/tools/official/blocks.yml`:
```yaml
blocks:
category.toolName:
type: utility
description: "Clear description for LLMs"
path: "tool-directory-name"
domain_rules:
- id: rule_name
description: "Implementation requirement"
inputs:
- name: paramName
type: string
description: "Parameter description"
outputs:
- name: result
type: ResultType
description: "Output description"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
```
### 2. Create Package Structure
```
packages/tools/official/tool-name/
├── package.json # npm package with tpmjs field
├── tsconfig.json # Extends @tpmjs/tsconfig
├── tsup.config.ts # Build config
├── block.ts # REQUIRED by validator
├── index.ts # Re-export from src
└── src/index.ts # Main implementation
```
### 3. Implement with AI SDK v6
```typescript
import { jsonSchema, tool } from 'ai';
export const myTool = tool({
description: 'Description for LLMs',
parameters: jsonSchema<InputType>({
type: 'object',
properties: { /* ... */ },
required: ['field1'],
}),
async execute(input): Promise<OutputType> {
// REAL implementation - no stubs
return result;
},
});
export default myTool;
```
### 4. Run Validation
```bash
cd packages/tools/official
pnpm blocks run tool-name # Validate single tool
pnpm blocks run tool-name --force # Force full validation
pnpm blocks run --all # Validate all tools
```
### 5. Build and Publish
```bash
pnpm build
npm publish --access public
# Trigger sync to tpmjs.com
source apps/web/.env.local
curl -X POST https://tpmjs.com/api/sync/keyword -H "Authorization: Bearer $CRON_SECRET"
```
## Valid Categories
For `tpmjs.category` in package.json: `research`, `web`, `data`, `documentation`, `engineering`, `security`, `statistics`, `ops`, `agent`, `sandbox`, `utilities`, `html`, `compliance`
## Required Files
- **block.ts** at root: `export const block = { name: 'tool-name', tools: { myTool } };`
- **index.ts** at root: `export * from './src/index.js';`
- Both are required for the validator to find the tool
## Common Issues
- "invalid tpmjs field" during sync = Invalid category or missing tools array
- "Tool not found in exports" = Export name must match blocks.yml
- "Required file not found" = Need index.ts and block.ts at package root
When helping the user, read the full skill documentation at `.claude/skills/blocks-develop.md` for comprehensive details on entities, measures, and multi-tool packages.

View file

@ -0,0 +1,357 @@
# TPMJS Tool Development with Blocks CLI
Use this skill when developing new tools for the TPMJS registry. This covers the full workflow from defining a tool in blocks.yml through implementation, validation, and publishing.
## Quick Start
```bash
# Navigate to official tools directory
cd packages/tools/official
# Run validation on a specific tool
pnpm blocks run <block-name>
# Run validation on all tools
pnpm blocks run --all
# Force full validation (ignore cache)
pnpm blocks run <block-name> --force
```
## Development Workflow
### 1. Define the Tool Block in blocks.yml
Add your tool definition to `packages/tools/official/blocks.yml` in the `blocks:` section:
```yaml
blocks:
# Category.toolName format
sandbox.myTool:
type: utility
description: "Clear, LLM-friendly description of what the tool does"
path: "my-tool" # Directory name under packages/tools/official/
domain_rules:
- id: rule_name
description: "What this implementation must do"
inputs:
- name: inputName
type: string
description: "Description for LLMs"
- name: optionalInput
type: number
optional: true
description: "Optional parameter"
outputs:
- name: result
type: MyResultType
description: "What the tool returns"
measures: [working_implementation, valid_output_structure, proper_error_handling, ai_sdk_compliance]
```
**Key Fields:**
- `type`: Usually `utility` for single-shot tools
- `path`: Directory name (kebab-case)
- `domain_rules`: Implementation requirements the validator checks
- `inputs/outputs`: Schema for validation
- `measures`: Quality constraints from the domain section
### 2. Create the Tool Package
Create the directory structure:
```
packages/tools/official/my-tool/
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── block.ts # Required by validator
├── index.ts # Re-export from src
└── src/
└── index.ts # Main implementation
```
**package.json:**
```json
{
"name": "@tpmjs/tools-my-tool",
"version": "0.1.0",
"description": "Short description for npm",
"type": "module",
"keywords": ["tpmjs", "category-name", "ai"],
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"files": ["dist"],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"type-check": "tsc --noEmit",
"clean": "rm -rf dist .turbo"
},
"devDependencies": {
"@tpmjs/tsconfig": "workspace:*",
"tsup": "^8.5.1",
"typescript": "^5.9.3"
},
"dependencies": {
"ai": "6.0.23"
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/tpmjs/tpmjs.git",
"directory": "packages/tools/official/my-tool"
},
"homepage": "https://tpmjs.com",
"license": "MIT",
"tpmjs": {
"category": "sandbox",
"frameworks": ["vercel-ai"],
"tools": [
{
"name": "myTool",
"description": "Clear description (20+ chars) of what this tool does."
}
]
}
}
```
**Valid categories for tpmjs.category:**
- `research`, `web`, `data`, `documentation`, `engineering`
- `security`, `statistics`, `ops`, `agent`, `sandbox`, `utilities`
- `html`, `compliance`
**tsconfig.json:**
```json
{
"extends": "@tpmjs/tsconfig/react-library.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
```
**tsup.config.ts:**
```typescript
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
clean: true,
sourcemap: true,
target: 'es2022',
});
```
**block.ts (Required by validator):**
```typescript
import { myTool } from './src/index.js';
export const block = {
name: 'my-tool',
description: 'Short description',
tools: { myTool },
};
export default block;
```
**index.ts (Root re-export):**
```typescript
export * from './src/index.js';
export { default } from './src/index.js';
```
### 3. Implement the Tool
**src/index.ts:**
```typescript
import { jsonSchema, tool } from 'ai';
// Define input/output types
interface MyToolInput {
param1: string;
param2?: number;
}
interface MyToolResult {
data: string;
metadata: {
processedAt: string;
};
}
// Export the tool using AI SDK v6 pattern
export const myTool = tool({
description: 'Clear description for LLMs explaining what this tool does and when to use it.',
parameters: jsonSchema<MyToolInput>({
type: 'object',
properties: {
param1: {
type: 'string',
description: 'Description of param1',
},
param2: {
type: 'number',
description: 'Optional description of param2',
},
},
required: ['param1'],
}),
async execute(input): Promise<MyToolResult> {
// REAL implementation - no stubs, no TODOs
const result = await doSomething(input.param1);
return {
data: result,
metadata: {
processedAt: new Date().toISOString(),
},
};
},
});
// Default export for compatibility
export default myTool;
```
### 4. Run Validation
```bash
cd packages/tools/official
# Validate your tool
pnpm blocks run my-tool
# The validator runs 3 stages:
# 1. schema - Validates inputs/outputs match blocks.yml
# 2. shape - Verifies exports and structure
# 3. domain - Checks domain rules are satisfied
```
**Common validation errors:**
- `Required file "index.ts" not found` - Need index.ts at package root
- `Required file "block.ts" not found` - Need block.ts at package root
- `Tool "myTool" not found in exports` - Export name must match blocks.yml
- `invalid tpmjs field` - Category must be valid, tools array required
### 5. Build and Publish
```bash
# Build the package
pnpm build
# Publish to npm
npm publish --access public
# Trigger sync to tpmjs.com
source apps/web/.env.local
curl -X POST https://tpmjs.com/api/sync/keyword \
-H "Authorization: Bearer $CRON_SECRET"
```
## Multi-Tool Packages
For packages with multiple tools (like unsandbox):
**blocks.yml:**
```yaml
blocks:
sandbox.executeCodeAsync:
type: utility
path: "unsandbox" # Same path for all tools in package
# ...
sandbox.getJob:
type: utility
path: "unsandbox" # Same path
# ...
```
**block.ts:**
```typescript
import { executeCodeAsync, getJob, listJobs } from './src/index.js';
export const block = {
name: 'unsandbox',
tools: { executeCodeAsync, getJob, listJobs },
};
export default block;
```
**package.json tpmjs field:**
```json
{
"tpmjs": {
"category": "sandbox",
"frameworks": ["vercel-ai"],
"tools": [
{ "name": "executeCodeAsync", "description": "..." },
{ "name": "getJob", "description": "..." },
{ "name": "listJobs", "description": "..." }
]
}
}
```
## Philosophy (from blocks.yml)
- Every tool MUST be a working, production-ready implementation - no stubs, no TODOs
- Tools use AI SDK v6 `tool()` + `jsonSchema()` pattern exclusively
- Each tool does ONE thing exceptionally well (single-shot, one call in, one result out)
- Tools return structured, typed outputs that agents can reliably parse
- Error handling is explicit - throw meaningful errors, never silently fail
- Dependencies are minimal and production-stable
## Domain Entities
When defining outputs, reference existing entities from blocks.yml:
```yaml
# Example entities available:
url: [href, domain, protocol, path, query, fragment]
webpage: [url, title, html, text, metadata]
text_content: [raw, sentences, paragraphs, wordCount]
claim: [statement, confidence, needsCitation, category]
timeline: [events, dateRange, gaps, eventCount]
```
Or define new entities in the `domain.entities` section if needed.
## Quality Measures
Reference these in your tool's `measures` array:
- `working_implementation` - No stubs, TODOs, or placeholders
- `valid_output_structure` - Returns correct typed object
- `proper_error_handling` - Throws descriptive errors
- `ai_sdk_compliance` - Uses tool() and jsonSchema()
- `npm_publishable` - Valid package.json with tpmjs field
- `readme_documentation` - Has README with examples
## Debugging Tips
```bash
# Force rebuild without cache
pnpm blocks run my-tool --force --no-cache
# See JSON output for debugging
pnpm blocks run my-tool --json
# Check if validator finds your package
ls packages/tools/official/my-tool/
# Must have: index.ts, block.ts at root level
```