From 013b98a53e387b09cc7b3c4d4fb094157c0f8945 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Mon, 1 Dec 2025 05:37:28 +1000 Subject: [PATCH] refactor: rename envVars to env and remove example field from TPMJS spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename TpmjsEnvVarSchema to TpmjsEnvSchema - Rename envVars field to env throughout codebase - Remove example field from TpmjsMinimalSchema (no longer required) - Update all documentation (spec page, publish page, HOW_TO_PUBLISH_A_TOOL.md) - Update example tool package.json - Simplify minimal tier requirements to only category and description 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- HOW_TO_PUBLISH_A_TOOL.md | 16 ++-- apps/web/src/app/publish/page.tsx | 8 +- apps/web/src/app/spec/page.tsx | 97 +++++++++------------- packages/tools/createBlogPost/package.json | 1 - packages/types/src/tpmjs.ts | 9 +- 5 files changed, 48 insertions(+), 83 deletions(-) diff --git a/HOW_TO_PUBLISH_A_TOOL.md b/HOW_TO_PUBLISH_A_TOOL.md index d7ae0bb..9a7b913 100644 --- a/HOW_TO_PUBLISH_A_TOOL.md +++ b/HOW_TO_PUBLISH_A_TOOL.md @@ -49,8 +49,7 @@ The bare minimum to get listed: { "tpmjs": { "category": "text-analysis", - "description": "A concise description of what your tool does", - "example": "const result = await myTool({ input: 'hello' });" + "description": "A concise description of what your tool does" } } ``` @@ -58,7 +57,6 @@ The bare minimum to get listed: **Required fields:** - `category` - One of: `text-analysis`, `code-generation`, `data-processing`, `image-generation`, `audio-processing`, `search`, `integration`, `other` - `description` - Clear description of what the tool does (1-3 sentences) -- `example` - Simple code example showing how to use the tool #### Tier 2: Basic (Recommended) @@ -69,7 +67,6 @@ Add parameter and return type information: "tpmjs": { "category": "text-analysis", "description": "Analyzes sentiment in text and returns a score", - "example": "const result = await analyzeSentiment({ text: 'I love this!' });", "parameters": [ { "name": "text", @@ -102,7 +99,6 @@ Complete metadata for maximum visibility: "tpmjs": { "category": "text-analysis", "description": "Advanced sentiment analysis with emotion detection", - "example": "const result = await analyzeSentiment({ text: 'I love this!', includeEmotions: true });", "parameters": [ { "name": "text", @@ -129,7 +125,7 @@ Complete metadata for maximum visibility: "type": "SentimentResult", "description": "Object with score, label, and optional emotions array" }, - "envVars": [ + "env": [ { "name": "SENTIMENT_API_KEY", "description": "API key for sentiment analysis service", @@ -266,7 +262,6 @@ Here's the complete `package.json` from the published example: "tpmjs": { "category": "text-analysis", "description": "Creates structured blog posts with customizable frontmatter, content sections, and SEO metadata. Supports multiple output formats including Markdown and MDX.", - "example": "const post = await createBlogPost({ title: 'My First Post', author: 'John Doe', content: 'Hello World!', tags: ['intro', 'blog'] });", "parameters": [ { "name": "title", @@ -340,7 +335,6 @@ Here's the complete `package.json` from the published example: |-------|------|-------------| | `category` | string | Tool category (see categories below) | | `description` | string | Clear description (1-3 sentences) | -| `example` | string | Code example showing usage | ### Optional Fields (Tier 2 - Basic) @@ -353,7 +347,7 @@ Here's the complete `package.json` from the published example: | Field | Type | Description | |-------|------|-------------| -| `envVars` | array | Required environment variables | +| `env` | array | Required environment variables | | `frameworks` | array | Compatible frameworks | | `links` | object | Related URLs | | `tags` | array | Additional tags | @@ -378,7 +372,7 @@ Choose one of these for the `category` field: If your tool requires environment variables: ```json -"envVars": [ +"env": [ { "name": "OPENAI_API_KEY", "description": "API key for OpenAI services", @@ -426,7 +420,7 @@ Or manually check the structure matches the examples above. **Tool not appearing after 15 minutes?** - Check that you added `"tpmjs-tool"` to keywords -- Verify your `tpmjs` field has required fields (category, description, example) +- Verify your `tpmjs` field has required fields (category, description) - Check the NPM package is public: `npm view yourpackage` **Tool showing as "minimal" tier?** diff --git a/apps/web/src/app/publish/page.tsx b/apps/web/src/app/publish/page.tsx index 9cc7e85..882b98c 100644 --- a/apps/web/src/app/publish/page.tsx +++ b/apps/web/src/app/publish/page.tsx @@ -96,8 +96,7 @@ export default function PublishPage(): React.ReactElement { code={`{ "tpmjs": { "category": "text-analysis", - "description": "A concise description of what your tool does", - "example": "const result = await myTool({ input: 'hello' });" + "description": "A concise description of what your tool does" } }`} /> @@ -120,7 +119,6 @@ export default function PublishPage(): React.ReactElement { "tpmjs": { "category": "text-analysis", "description": "Analyzes sentiment in text", - "example": "const result = await analyzeSentiment({ text: 'I love this!' });", "parameters": [ { "name": "text", @@ -162,10 +160,9 @@ export default function PublishPage(): React.ReactElement { "tpmjs": { "category": "text-analysis", "description": "Advanced sentiment analysis with emotion detection", - "example": "const result = await analyzeSentiment({ text: 'I love this!', includeEmotions: true });", "parameters": [...], "returns": {...}, - "envVars": [ + "env": [ { "name": "SENTIMENT_API_KEY", "description": "API key for sentiment analysis service", @@ -290,7 +287,6 @@ npm publish --access public "tpmjs": { "category": "text-analysis", "description": "Creates structured blog posts with frontmatter and SEO metadata", - "example": "const post = await createBlogPost({ title: 'My Post', author: 'John', content: 'Hello' });", "parameters": [ { "name": "title", diff --git a/apps/web/src/app/spec/page.tsx b/apps/web/src/app/spec/page.tsx index 988adc5..8d4d0ef 100644 --- a/apps/web/src/app/spec/page.tsx +++ b/apps/web/src/app/spec/page.tsx @@ -1,9 +1,9 @@ +import { TPMJS_CATEGORIES } from '@tpmjs/types/tpmjs'; import { Badge } from '@tpmjs/ui/Badge/Badge'; import { Button } from '@tpmjs/ui/Button/Button'; import { Card, CardContent, CardHeader, CardTitle } from '@tpmjs/ui/Card/Card'; import { CodeBlock } from '@tpmjs/ui/CodeBlock/CodeBlock'; import { Container } from '@tpmjs/ui/Container/Container'; -import { TPMJS_CATEGORIES } from '@tpmjs/types/tpmjs'; import Link from 'next/link'; import { AppHeader } from '~/components/AppHeader'; @@ -49,8 +49,8 @@ export default function SpecPage(): React.ReactElement { specification for describing tool capabilities
  • - Quality Scoring - Algorithmic - ranking based on documentation completeness and community adoption + Quality Scoring - Algorithmic ranking + based on documentation completeness and community adoption
  • AI Agent Integration - Structured @@ -71,9 +71,11 @@ export default function SpecPage(): React.ReactElement {

    - Add the tpmjs-tool keyword - and a tpmjs metadata field - to your package.json + Add the{' '} + tpmjs-tool{' '} + keyword and a{' '} + tpmjs metadata + field to your package.json

    @@ -110,9 +112,10 @@ export default function SpecPage(): React.ReactElement {

    The Specification

    - The TPMJS specification defines a tpmjs field - in package.json with three tiers of metadata. Higher tiers receive better visibility - and quality scores. + The TPMJS specification defines a{' '} + tpmjs field in + package.json with three tiers of metadata. Higher tiers receive better visibility and + quality scores.

    {/* Tier 1: Minimal */} @@ -151,16 +154,6 @@ export default function SpecPage(): React.ReactElement { appears in search results and tool listings.

    - -
    -

    - example * -

    -

    - Code example showing basic usage. Minimum 10 characters. Helps developers - understand how to use your tool. -

    -
    @@ -170,8 +163,7 @@ export default function SpecPage(): React.ReactElement { code={`{ "tpmjs": { "category": "text-analysis", - "description": "Analyzes sentiment in text and returns positive/negative/neutral classification", - "example": "const result = await analyzeSentiment({ text: 'I love this!' });" + "description": "Analyzes sentiment in text and returns positive/negative/neutral classification" } }`} /> @@ -246,7 +238,6 @@ export default function SpecPage(): React.ReactElement { "tpmjs": { "category": "text-analysis", "description": "Analyzes sentiment in text", - "example": "const result = await analyzeSentiment({ text: 'I love this!' });", "parameters": [ { "name": "text", @@ -289,7 +280,7 @@ export default function SpecPage(): React.ReactElement {

    - envVars + env

    Array of environment variables required by the tool. Each variable has: @@ -297,11 +288,11 @@ export default function SpecPage(): React.ReactElement {

    • name - Environment variable name - (e.g., "OPENAI_API_KEY") + (e.g., "OPENAI_API_KEY")
    • - description - What the variable is - used for + description - What the variable + is used for
    • required - Boolean (defaults to @@ -322,13 +313,17 @@ export default function SpecPage(): React.ReactElement { Array of compatible AI frameworks. Supported values:

      - {['vercel-ai', 'langchain', 'llamaindex', 'haystack', 'semantic-kernel'].map( - (fw) => ( - - {fw} - - ) - )} + {[ + 'vercel-ai', + 'langchain', + 'llamaindex', + 'haystack', + 'semantic-kernel', + ].map((fw) => ( + + {fw} + + ))}
    @@ -417,10 +412,9 @@ export default function SpecPage(): React.ReactElement { "tpmjs": { "category": "text-analysis", "description": "Advanced sentiment analysis with emotion detection", - "example": "const result = await analyzeSentiment({ text: 'I love this!', includeEmotions: true });", "parameters": [...], "returns": {...}, - "envVars": [ + "env": [ { "name": "SENTIMENT_API_KEY", "description": "API key for sentiment analysis service", @@ -499,21 +493,6 @@ export default function SpecPage(): React.ReactElement { Tool description (20-500 chars) - - - example - - string - - - Minimal - - - - Yes - - Usage example code (min 10 chars) - parameters @@ -542,7 +521,7 @@ export default function SpecPage(): React.ReactElement { - envVars + env array @@ -708,7 +687,7 @@ export default function SpecPage(): React.ReactElement {

    - Monitors NPM's real-time changes feed every 2 minutes + Monitors NPM's real-time changes feed every 2 minutes

    Real-time @@ -722,8 +701,9 @@ export default function SpecPage(): React.ReactElement {

    - Searches for tpmjs-tool keyword - every 15 minutes + Searches for{' '} + tpmjs-tool{' '} + keyword every 15 minutes

    Every 15 min @@ -778,11 +758,7 @@ export default function SpecPage(): React.ReactElement { Description must be 20-500 characters
  • - Example too short: Example must be - at least 10 characters -
  • -
  • - Invalid envVar: Each environment + Invalid env: Each environment variable must have a name and description
  • @@ -809,7 +785,8 @@ export default function SpecPage(): React.ReactElement {
    1️⃣

    - Add tpmjs-tool keyword + Add tpmjs-tool{' '} + keyword

    diff --git a/packages/tools/createBlogPost/package.json b/packages/tools/createBlogPost/package.json index b347894..0714f28 100644 --- a/packages/tools/createBlogPost/package.json +++ b/packages/tools/createBlogPost/package.json @@ -35,7 +35,6 @@ "tpmjs": { "category": "text-analysis", "description": "Creates structured blog posts with customizable frontmatter, content sections, and SEO metadata. Supports multiple output formats including Markdown and MDX.", - "example": "const post = await createBlogPost({ title: 'My First Post', author: 'John Doe', content: 'Hello World!', tags: ['intro', 'blog'] });", "parameters": [ { "name": "title", diff --git a/packages/types/src/tpmjs.ts b/packages/types/src/tpmjs.ts index 57d25b0..7c5d182 100644 --- a/packages/types/src/tpmjs.ts +++ b/packages/types/src/tpmjs.ts @@ -46,14 +46,14 @@ export type TpmjsReturns = z.infer; /** * Environment variable schema */ -export const TpmjsEnvVarSchema = z.object({ +export const TpmjsEnvSchema = z.object({ name: z.string().min(1), description: z.string().min(1), required: z.boolean().default(true), default: z.string().optional(), }); -export type TpmjsEnvVar = z.infer; +export type TpmjsEnv = z.infer; /** * External links schema @@ -87,7 +87,6 @@ export const TpmjsMinimalSchema = z.object({ message: `Category must be one of: ${TPMJS_CATEGORIES.join(', ')}`, }), description: z.string().min(20, 'Description must be at least 20 characters').max(500), - example: z.string().min(10, 'Example must be at least 10 characters'), }); export type TpmjsMinimal = z.infer; @@ -99,7 +98,7 @@ export type TpmjsMinimal = z.infer; export const TpmjsRichSchema = TpmjsMinimalSchema.extend({ parameters: z.array(TpmjsParameterSchema).optional(), returns: TpmjsReturnsSchema.optional(), - envVars: z.array(TpmjsEnvVarSchema).optional(), + env: z.array(TpmjsEnvSchema).optional(), frameworks: z .array(z.enum(['vercel-ai', 'langchain', 'llamaindex', 'haystack', 'semantic-kernel'])) .optional(), @@ -138,7 +137,7 @@ export function validateTpmjsField(tpmjs: unknown): ValidationResult { const hasRichFields = data.parameters || data.returns || - data.envVars || + data.env || data.frameworks || data.links || data.tags ||