diff --git a/apps/tutorial/src/app/agent-example/page.tsx b/apps/tutorial/src/app/agent-example/page.tsx
new file mode 100644
index 0000000..112f1ff
--- /dev/null
+++ b/apps/tutorial/src/app/agent-example/page.tsx
@@ -0,0 +1,16 @@
+import { AgentExampleSlideshow } from '@/components/AgentExampleSlideshow';
+import type { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Real-World Agent Example | TPMJS Tutorials',
+ description:
+ 'Build a complete AI agent that discovers and uses tools dynamically from the TPMJS registry. Working code examples included.',
+};
+
+export default function AgentExamplePage(): React.ReactElement {
+ return (
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/app/first-tool/page.tsx b/apps/tutorial/src/app/first-tool/page.tsx
new file mode 100644
index 0000000..5f6a007
--- /dev/null
+++ b/apps/tutorial/src/app/first-tool/page.tsx
@@ -0,0 +1,16 @@
+import { FirstToolSlideshow } from '@/components/FirstToolSlideshow';
+import type { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Build Your First Tool | TPMJS Tutorials',
+ description:
+ 'Step-by-step guide to creating your first AI SDK tool for the TPMJS registry. From npm init to published tool in 10 minutes.',
+};
+
+export default function FirstToolPage(): React.ReactElement {
+ return (
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/app/page.tsx b/apps/tutorial/src/app/page.tsx
index 7342375..b376992 100644
--- a/apps/tutorial/src/app/page.tsx
+++ b/apps/tutorial/src/app/page.tsx
@@ -80,6 +80,81 @@ const tutorials = [
),
features: ['tpmjs keyword', 'Schema extraction', 'Quality scoring'],
},
+ {
+ id: 'first-tool',
+ title: 'Build Your First Tool',
+ subtitle: 'Step-by-Step',
+ description: 'Create an AI SDK tool from scratch and publish it to the registry in 10 minutes.',
+ href: '/first-tool',
+ gradient: 'from-orange-500 to-amber-600',
+ icon: (
+
+
+
+ ),
+ features: ['npm init', 'Zod schema', 'npm publish'],
+ },
+ {
+ id: 'agent-example',
+ title: 'Real-World Agent',
+ subtitle: 'Working Example',
+ description: 'Build a complete agent that discovers and uses tools dynamically.',
+ href: '/agent-example',
+ gradient: 'from-rose-500 to-pink-600',
+ icon: (
+
+
+
+ ),
+ features: ['generateText', 'maxSteps', 'Meta-tools'],
+ },
+ {
+ id: 'playground',
+ title: 'Interactive Playground',
+ subtitle: 'Try Before Install',
+ description: 'Test any tool directly in your browser without installation.',
+ href: '/playground',
+ gradient: 'from-sky-500 to-blue-600',
+ icon: (
+
+
+
+ ),
+ features: ['Live execution', 'Schema forms', 'JSON output'],
+ },
];
export default function TutorialHome(): React.ReactElement {
@@ -99,7 +174,7 @@ export default function TutorialHome(): React.ReactElement {
/>
{/* Content */}
-
+
{/* Header */}
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/AgentExampleSlideshow.tsx b/apps/tutorial/src/components/AgentExampleSlideshow.tsx
new file mode 100644
index 0000000..9a38f3c
--- /dev/null
+++ b/apps/tutorial/src/components/AgentExampleSlideshow.tsx
@@ -0,0 +1,77 @@
+'use client';
+
+import { useSlideshow } from '@/hooks/useSlideshow';
+import { AnimatePresence } from 'framer-motion';
+import Link from 'next/link';
+import { Slide } from './Slide';
+import { SlideNavigation } from './SlideNavigation';
+import { SlideProgress } from './SlideProgress';
+import { AgentCodeSlide } from './agent-example-slides/AgentCodeSlide';
+import { AgentExampleNextStepsSlide } from './agent-example-slides/AgentExampleNextStepsSlide';
+import { AgentExampleWelcomeSlide } from './agent-example-slides/AgentExampleWelcomeSlide';
+import { ExecutionFlowSlide } from './agent-example-slides/ExecutionFlowSlide';
+import { SetupCodeSlide } from './agent-example-slides/SetupCodeSlide';
+import { TheGoalSlide } from './agent-example-slides/TheGoalSlide';
+
+const SLIDES = [
+ { id: 'welcome', Component: AgentExampleWelcomeSlide },
+ { id: 'the-goal', Component: TheGoalSlide },
+ { id: 'setup', Component: SetupCodeSlide },
+ { id: 'agent-code', Component: AgentCodeSlide },
+ { id: 'execution-flow', Component: ExecutionFlowSlide },
+ { id: 'next-steps', Component: AgentExampleNextStepsSlide },
+];
+
+export function AgentExampleSlideshow(): React.ReactElement {
+ const { currentSlide, totalSlides, next, prev, goTo, direction, isFirst, isLast } = useSlideshow({
+ totalSlides: SLIDES.length,
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+ Tutorials
+
+
+
+ {SLIDES.map((slide, index) => (
+
+
+
+ ))}
+
+
+
+
+
+
+ Use arrow keys or click to navigate
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/FirstToolSlideshow.tsx b/apps/tutorial/src/components/FirstToolSlideshow.tsx
new file mode 100644
index 0000000..7be911a
--- /dev/null
+++ b/apps/tutorial/src/components/FirstToolSlideshow.tsx
@@ -0,0 +1,77 @@
+'use client';
+
+import { useSlideshow } from '@/hooks/useSlideshow';
+import { AnimatePresence } from 'framer-motion';
+import Link from 'next/link';
+import { Slide } from './Slide';
+import { SlideNavigation } from './SlideNavigation';
+import { SlideProgress } from './SlideProgress';
+import { FirstToolNextStepsSlide } from './first-tool-slides/FirstToolNextStepsSlide';
+import { FirstToolWelcomeSlide } from './first-tool-slides/FirstToolWelcomeSlide';
+import { PackageJsonSlide } from './first-tool-slides/PackageJsonSlide';
+import { ProjectSetupSlide } from './first-tool-slides/ProjectSetupSlide';
+import { PublishSlide } from './first-tool-slides/PublishSlide';
+import { WriteToolSlide } from './first-tool-slides/WriteToolSlide';
+
+const SLIDES = [
+ { id: 'welcome', Component: FirstToolWelcomeSlide },
+ { id: 'project-setup', Component: ProjectSetupSlide },
+ { id: 'write-tool', Component: WriteToolSlide },
+ { id: 'package-json', Component: PackageJsonSlide },
+ { id: 'publish', Component: PublishSlide },
+ { id: 'next-steps', Component: FirstToolNextStepsSlide },
+];
+
+export function FirstToolSlideshow(): React.ReactElement {
+ const { currentSlide, totalSlides, next, prev, goTo, direction, isFirst, isLast } = useSlideshow({
+ totalSlides: SLIDES.length,
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+ Tutorials
+
+
+
+ {SLIDES.map((slide, index) => (
+
+
+
+ ))}
+
+
+
+
+
+
+ Use arrow keys or click to navigate
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/PlaygroundSlideshow.tsx b/apps/tutorial/src/components/PlaygroundSlideshow.tsx
new file mode 100644
index 0000000..3489e6f
--- /dev/null
+++ b/apps/tutorial/src/components/PlaygroundSlideshow.tsx
@@ -0,0 +1,77 @@
+'use client';
+
+import { useSlideshow } from '@/hooks/useSlideshow';
+import { AnimatePresence } from 'framer-motion';
+import Link from 'next/link';
+import { Slide } from './Slide';
+import { SlideNavigation } from './SlideNavigation';
+import { SlideProgress } from './SlideProgress';
+import { FillParametersSlide } from './playground-slides/FillParametersSlide';
+import { FindToolSlide } from './playground-slides/FindToolSlide';
+import { OpenPlaygroundSlide } from './playground-slides/OpenPlaygroundSlide';
+import { PlaygroundNextStepsSlide } from './playground-slides/PlaygroundNextStepsSlide';
+import { PlaygroundWelcomeSlide } from './playground-slides/PlaygroundWelcomeSlide';
+import { SeeResultsSlide } from './playground-slides/SeeResultsSlide';
+
+const SLIDES = [
+ { id: 'welcome', Component: PlaygroundWelcomeSlide },
+ { id: 'find-tool', Component: FindToolSlide },
+ { id: 'open-playground', Component: OpenPlaygroundSlide },
+ { id: 'fill-parameters', Component: FillParametersSlide },
+ { id: 'see-results', Component: SeeResultsSlide },
+ { id: 'next-steps', Component: PlaygroundNextStepsSlide },
+];
+
+export function PlaygroundSlideshow(): React.ReactElement {
+ const { currentSlide, totalSlides, next, prev, goTo, direction, isFirst, isLast } = useSlideshow({
+ totalSlides: SLIDES.length,
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+ Tutorials
+
+
+
+ {SLIDES.map((slide, index) => (
+
+
+
+ ))}
+
+
+
+
+
+
+ Use arrow keys or click to navigate
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/agent-example-slides/AgentCodeSlide.tsx b/apps/tutorial/src/components/agent-example-slides/AgentCodeSlide.tsx
new file mode 100644
index 0000000..7870769
--- /dev/null
+++ b/apps/tutorial/src/components/agent-example-slides/AgentCodeSlide.tsx
@@ -0,0 +1,104 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function AgentCodeSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 2
+ The Agent Loop
+ Pass meta-tools to generateText with maxSteps
+
+
+ agent.ts
+
+
+ const
+ result =
+ await
+ generateText
+ {'({'}
+ {'\n'}
+ {' '}
+ model
+ :
+ openai
+ (
+ 'gpt-4o'
+ ),
+ {'\n'}
+ {' '}
+ tools
+ {': {'}
+ {'\n'}
+ {' '}
+ search
+ :
+ searchTpmjsToolsTool
+ ,
+ {'\n'}
+ {' '}
+ execute
+ :
+ registryExecuteTool
+ ,
+ {'\n'}
+ {' },'}
+ {'\n'}
+ {' '}
+ maxSteps
+ :
+ 10
+ ,
+ {' // Allow multiple tool calls'}
+ {'\n'}
+ {' '}
+ system
+ :
+ `You are an assistant that can find and use
+ {'\n'}
+
+ {' '}
+ tools from the TPMJS registry. First search for
+
+ {'\n'}
+ relevant tools, then execute them.`
+ ,
+ {'\n'}
+ {' '}
+ prompt
+ : userRequest,
+ {'\n'}
+ {'});'}
+
+
+
+
+
+
+ Key: maxSteps allows the agent to search, then
+ execute, then reason about results
+
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/agent-example-slides/AgentExampleNextStepsSlide.tsx b/apps/tutorial/src/components/agent-example-slides/AgentExampleNextStepsSlide.tsx
new file mode 100644
index 0000000..82f10e9
--- /dev/null
+++ b/apps/tutorial/src/components/agent-example-slides/AgentExampleNextStepsSlide.tsx
@@ -0,0 +1,80 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function AgentExampleNextStepsSlide(): React.ReactElement {
+ return (
+
+ );
+}
diff --git a/apps/tutorial/src/components/agent-example-slides/AgentExampleWelcomeSlide.tsx b/apps/tutorial/src/components/agent-example-slides/AgentExampleWelcomeSlide.tsx
new file mode 100644
index 0000000..7f1b525
--- /dev/null
+++ b/apps/tutorial/src/components/agent-example-slides/AgentExampleWelcomeSlide.tsx
@@ -0,0 +1,87 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function AgentExampleWelcomeSlide(): React.ReactElement {
+ return (
+
+
+
+
+
+
+ Practical Example
+
+
+
+
+
+ Real-World Agent
+
+
+
+
+ Build an agent that discovers and uses tools dynamically
+
+
+
+ A complete working example with search, execute, and reasoning
+
+
+
+
+
+
+
+
+
+ Press any key
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/agent-example-slides/ExecutionFlowSlide.tsx b/apps/tutorial/src/components/agent-example-slides/ExecutionFlowSlide.tsx
new file mode 100644
index 0000000..04f57d1
--- /dev/null
+++ b/apps/tutorial/src/components/agent-example-slides/ExecutionFlowSlide.tsx
@@ -0,0 +1,95 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+const steps = [
+ {
+ step: '1',
+ action: 'Agent receives request',
+ detail: '"Format this markdown..."',
+ color: 'rose',
+ },
+ {
+ step: '2',
+ action: 'Calls searchTpmjsToolsTool',
+ detail: 'query: "markdown formatter"',
+ color: 'pink',
+ },
+ {
+ step: '3',
+ action: 'Receives tool list',
+ detail: '[markdownFormat, mdToHtml, ...]',
+ color: 'purple',
+ },
+ {
+ step: '4',
+ action: 'Calls registryExecuteTool',
+ detail: 'toolId: "markdownFormat", args: {...}',
+ color: 'violet',
+ },
+ {
+ step: '5',
+ action: 'Returns result to user',
+ detail: 'Formatted blog post',
+ color: 'indigo',
+ },
+];
+
+export function ExecutionFlowSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Execution Flow
+ What happens when the agent runs
+
+
+ {steps.map((step, index) => (
+
+
+ {step.step}
+
+
+
{step.action}
+
{step.detail}
+
+
+ ))}
+
+
+
+ All tool execution happens in a secure sandbox
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/agent-example-slides/SetupCodeSlide.tsx b/apps/tutorial/src/components/agent-example-slides/SetupCodeSlide.tsx
new file mode 100644
index 0000000..7a8362e
--- /dev/null
+++ b/apps/tutorial/src/components/agent-example-slides/SetupCodeSlide.tsx
@@ -0,0 +1,81 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function SetupCodeSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 1
+ Install & Setup
+ Add the TPMJS meta-tools to your project
+
+
+ Terminal
+
+
+ npm
+
+ {' '}
+ install @tpmjs/search-registry @tpmjs/registry-execute
+
+
+
+
+
+
+ agent.ts
+
+
+ import
+ {' { searchTpmjsToolsTool } '}
+ from
+ {'\n'}
+ '@tpmjs/search-registry'
+ ;
+ {'\n'}
+ import
+ {' { registryExecuteTool } '}
+ from
+ {'\n'}
+ '@tpmjs/registry-execute'
+ ;
+ {'\n'}
+ import
+ {' { generateText } '}
+ from
+ 'ai'
+ ;
+
+
+
+
+
+ Two tools that give your agent access to the entire registry
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/agent-example-slides/TheGoalSlide.tsx b/apps/tutorial/src/components/agent-example-slides/TheGoalSlide.tsx
new file mode 100644
index 0000000..1f7bd23
--- /dev/null
+++ b/apps/tutorial/src/components/agent-example-slides/TheGoalSlide.tsx
@@ -0,0 +1,77 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function TheGoalSlide(): React.ReactElement {
+ return (
+
+
+
+
+ The Goal
+
+ An agent that can handle any request by finding the right tools
+
+
+
+ User Request
+
+ "Convert this markdown to a formatted blog post and generate a summary"
+
+
+
+
+
+
+
+
+
+
+
+
1. Search
+
Find markdown tools
+
+
+
2. Execute
+
Format the content
+
+
+
3. Return
+
Give result to user
+
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/first-tool-slides/FirstToolNextStepsSlide.tsx b/apps/tutorial/src/components/first-tool-slides/FirstToolNextStepsSlide.tsx
new file mode 100644
index 0000000..ee779f1
--- /dev/null
+++ b/apps/tutorial/src/components/first-tool-slides/FirstToolNextStepsSlide.tsx
@@ -0,0 +1,71 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+const nextSteps = [
+ {
+ title: 'Add Rich Metadata',
+ description: 'Include tpmjs field in package.json for better quality scores',
+ href: '/authors',
+ icon: '๐',
+ },
+ {
+ title: 'Test in Playground',
+ description: 'Try your tool at tpmjs.com/tool/your-package/yourTool',
+ href: '/playground',
+ icon: '๐ฎ',
+ },
+ {
+ title: 'View on Registry',
+ description: 'See how agents discover your tool',
+ href: 'https://tpmjs.com',
+ icon: '๐',
+ },
+];
+
+export function FirstToolNextStepsSlide(): React.ReactElement {
+ return (
+
+
+
+
+ You're Published!
+ Your tool is now discoverable by AI agents
+
+
+ {nextSteps.map((step, index) => (
+
+
+ {step.icon}
+
+ {step.title}
+ {step.description}
+
+ ))}
+
+
+
+ Complete code example:
+ github.com/tpmjs/example-tool
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/first-tool-slides/FirstToolWelcomeSlide.tsx b/apps/tutorial/src/components/first-tool-slides/FirstToolWelcomeSlide.tsx
new file mode 100644
index 0000000..73b4f4d
--- /dev/null
+++ b/apps/tutorial/src/components/first-tool-slides/FirstToolWelcomeSlide.tsx
@@ -0,0 +1,87 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function FirstToolWelcomeSlide(): React.ReactElement {
+ return (
+
+
+
+
+
+
+ Step-by-Step Guide
+
+
+
+
+
+ Build Your First Tool
+
+
+
+
+ From npm init to published tool in 10 minutes
+
+
+
+ Create an AI SDK tool that agents can discover and execute
+
+
+
+
+
+
+
+
+
+ Press any key
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/first-tool-slides/PackageJsonSlide.tsx b/apps/tutorial/src/components/first-tool-slides/PackageJsonSlide.tsx
new file mode 100644
index 0000000..38af26b
--- /dev/null
+++ b/apps/tutorial/src/components/first-tool-slides/PackageJsonSlide.tsx
@@ -0,0 +1,96 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function PackageJsonSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 3
+ Configure package.json
+ Add the tpmjs-tool keyword for discovery
+
+
+ package.json
+
+
+ {'{'}
+ {'\n'}
+ {' '}
+ "name"
+ :
+ "my-ai-tool"
+ ,
+ {'\n'}
+ {' '}
+ "version"
+ :
+ "1.0.0"
+ ,
+ {'\n'}
+ {' '}
+ "keywords"
+ : [
+ {'\n'}
+ {' '}
+ "tpmjs-tool"
+ {' โ Required for discovery'}
+ {'\n'}
+ {' ],'}]
+ {'\n'}
+ {' '}
+ "main"
+ :
+ "dist/index.js"
+ ,
+ {'\n'}
+ {' '}
+ "types"
+ :
+ "dist/index.d.ts"
+ ,
+ {'\n'}
+ {' '}
+ "exports"
+ {': {'}
+ {'\n'}
+ {' '}
+ "."
+ :
+ "./dist/index.js"
+ {'\n'}
+ {' }'}
+ {'\n'}
+ {'}'}
+
+
+
+
+
+
+ Key: The{' '}
+ tpmjs-tool keyword triggers
+ automatic indexing
+
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/first-tool-slides/ProjectSetupSlide.tsx b/apps/tutorial/src/components/first-tool-slides/ProjectSetupSlide.tsx
new file mode 100644
index 0000000..e836ec5
--- /dev/null
+++ b/apps/tutorial/src/components/first-tool-slides/ProjectSetupSlide.tsx
@@ -0,0 +1,68 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function ProjectSetupSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 1
+ Project Setup
+ Create a new npm package
+
+
+ Terminal
+
+
+ # Create directory
+ {'\n'}
+ mkdir
+ my-ai-tool
+ {'\n'}
+ cd
+ my-ai-tool
+ {'\n\n'}
+ # Initialize package
+ {'\n'}
+ npm
+ init -y
+ {'\n\n'}
+ # Install dependencies
+ {'\n'}
+ npm
+ install ai zod
+
+
+
+
+
+
+ ai
+
+ +
+
+ zod
+
+ = AI SDK tools
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/first-tool-slides/PublishSlide.tsx b/apps/tutorial/src/components/first-tool-slides/PublishSlide.tsx
new file mode 100644
index 0000000..f4c7d46
--- /dev/null
+++ b/apps/tutorial/src/components/first-tool-slides/PublishSlide.tsx
@@ -0,0 +1,73 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function PublishSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 4
+ Publish to npm
+ Build and publish your tool
+
+
+ Terminal
+
+
+ # Build TypeScript
+ {'\n'}
+ npm
+ run build
+ {'\n\n'}
+ # Publish to npm
+ {'\n'}
+ npm
+ publish
+
+
+
+
+
+
+
๐ฆ
+
Published to npm
+
+
+
๐
+
Synced in ~2 min
+
+
+
โจ
+
Live on tpmjs.com
+
+
+
+
+ TPMJS syncs from npm's changes feed every 2 minutes
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/first-tool-slides/WriteToolSlide.tsx b/apps/tutorial/src/components/first-tool-slides/WriteToolSlide.tsx
new file mode 100644
index 0000000..0b5be13
--- /dev/null
+++ b/apps/tutorial/src/components/first-tool-slides/WriteToolSlide.tsx
@@ -0,0 +1,107 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function WriteToolSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 2
+ Write Your Tool
+
+ Define schema, description, and execute function
+
+
+
+ src/index.ts
+
+
+ import
+ {' { tool } '}
+ from
+ {" 'ai'"}
+ ;
+ {'\n'}
+ import
+ {' { z } '}
+ from
+ {" 'zod'"}
+ ;
+ {'\n\n'}
+ export const
+ greetingTool
+ =
+ tool
+ {'({'}
+ {'\n'}
+ {' '}
+ description
+ :
+ 'Generate a greeting'
+ ,
+ {'\n'}
+ {' '}
+ parameters
+ : z.
+ object
+ {'({'}
+ {'\n'}
+ {' '}
+ name
+ : z.
+ string
+ ().
+ describe
+ (
+ 'Name'
+ ),
+ {'\n'}
+ {' }'}),
+ {'\n'}
+ {' '}
+ execute
+ :
+ async
+ {' ({ name }) => {'}
+ {'\n'}
+ {' '}
+ return
+
+ `Hello,
+ {'${'}
+ name
+ {'}'}
+ !`
+ ;
+ {'\n'}
+ {' },'}
+ {'\n'}
+ {'});'}
+
+
+
+
+
+ The AI SDK tool() wrapper makes it compatible with generateText()
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/playground-slides/FillParametersSlide.tsx b/apps/tutorial/src/components/playground-slides/FillParametersSlide.tsx
new file mode 100644
index 0000000..59aeef2
--- /dev/null
+++ b/apps/tutorial/src/components/playground-slides/FillParametersSlide.tsx
@@ -0,0 +1,80 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function FillParametersSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 3
+ Fill Parameters
+
+ The form is auto-generated from the tool's schema
+
+
+
+ textToEmoji Parameters
+
+
+
+
+
+
style
+
+ default
+ minimal
+ expressive
+
+
+
+
+
+ Execute Tool
+
+
+
+
+ Required fields are marked with * โ optional fields have defaults
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/playground-slides/FindToolSlide.tsx b/apps/tutorial/src/components/playground-slides/FindToolSlide.tsx
new file mode 100644
index 0000000..7dc79de
--- /dev/null
+++ b/apps/tutorial/src/components/playground-slides/FindToolSlide.tsx
@@ -0,0 +1,70 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function FindToolSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 1
+ Find a Tool
+ Browse or search the registry
+
+
+
+
+ ๐
+ Search tools...
+
+
+
+
+ {[
+ { name: 'textToEmoji', pkg: '@tpmjs/emoji-magic', desc: 'Convert text to emojis' },
+ { name: 'markdownFormat', pkg: '@tpmjs/markdown-formatter', desc: 'Format markdown' },
+ { name: 'helloWorld', pkg: '@tpmjs/hello', desc: 'Simple greeting tool' },
+ ].map((tool, i) => (
+
+
+ fn
+
+
+
{tool.name}
+
{tool.pkg}
+
+ {tool.desc}
+
+ ))}
+
+
+
+
+ tpmjs.com โ Browse 200+ tools by category
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/playground-slides/OpenPlaygroundSlide.tsx b/apps/tutorial/src/components/playground-slides/OpenPlaygroundSlide.tsx
new file mode 100644
index 0000000..6d23037
--- /dev/null
+++ b/apps/tutorial/src/components/playground-slides/OpenPlaygroundSlide.tsx
@@ -0,0 +1,84 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function OpenPlaygroundSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 2
+ Open the Playground
+ Click "Try it" on any tool page
+
+
+ {/* Mock browser header */}
+
+
+
+
+ tpmjs.com/tool/@tpmjs/emoji-magic/textToEmoji
+
+
+
+
+ {/* Mock tool page */}
+
+
+
+
@tpmjs/emoji-magic
+
textToEmoji
+
Convert text to emojis
+
+
+ Try it โ
+
+
+
+
+
+
Parameters
+
text, style?
+
+
+
+
+
+
+
+
+ Every tool page has a "Try it" button that opens the playground
+
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/playground-slides/PlaygroundNextStepsSlide.tsx b/apps/tutorial/src/components/playground-slides/PlaygroundNextStepsSlide.tsx
new file mode 100644
index 0000000..5915282
--- /dev/null
+++ b/apps/tutorial/src/components/playground-slides/PlaygroundNextStepsSlide.tsx
@@ -0,0 +1,99 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+const features = [
+ {
+ title: 'Test Parameters',
+ description: 'Understand what each tool expects before integrating',
+ icon: '๐งช',
+ },
+ {
+ title: 'Debug Issues',
+ description: 'See exact inputs and outputs to troubleshoot',
+ icon: '๐ง',
+ },
+ {
+ title: 'Evaluate Quality',
+ description: 'Check if a tool does what you need before using it',
+ icon: 'โ
',
+ },
+ {
+ title: 'Share Examples',
+ description: 'Copy the URL to share working examples',
+ icon: '๐',
+ },
+];
+
+export function PlaygroundNextStepsSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Use Cases
+ Why the playground is useful
+
+
+ {features.map((feature, index) => (
+
+ {feature.icon}
+ {feature.title}
+ {feature.description}
+
+ ))}
+
+
+
+
+ Try the Playground
+
+
+
+
+
+
+
+ Every tool on tpmjs.com has a playground โ try any of them
+
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/playground-slides/PlaygroundWelcomeSlide.tsx b/apps/tutorial/src/components/playground-slides/PlaygroundWelcomeSlide.tsx
new file mode 100644
index 0000000..bef8b60
--- /dev/null
+++ b/apps/tutorial/src/components/playground-slides/PlaygroundWelcomeSlide.tsx
@@ -0,0 +1,87 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function PlaygroundWelcomeSlide(): React.ReactElement {
+ return (
+
+
+
+
+
+
+ Try Before You Install
+
+
+
+
+
+ Interactive Playground
+
+
+
+
+ Test any tool directly in your browser
+
+
+
+ No installation required โ execute tools live and see results instantly
+
+
+
+
+
+
+
+
+
+ Press any key
+
+
+ );
+}
diff --git a/apps/tutorial/src/components/playground-slides/SeeResultsSlide.tsx b/apps/tutorial/src/components/playground-slides/SeeResultsSlide.tsx
new file mode 100644
index 0000000..c924573
--- /dev/null
+++ b/apps/tutorial/src/components/playground-slides/SeeResultsSlide.tsx
@@ -0,0 +1,85 @@
+'use client';
+
+import { motion } from 'framer-motion';
+
+export function SeeResultsSlide(): React.ReactElement {
+ return (
+
+
+
+
+ Step 4
+ See Results
+ Tool executes in a secure sandbox
+
+
+
+ Input
+
+ {JSON.stringify(
+ {
+ text: 'Hello world, I love coding!',
+ style: 'expressive',
+ },
+ null,
+ 2
+ )}
+
+
+
+
+
+
+ {JSON.stringify(
+ {
+ result: '๐๐, ๐๐ป!',
+ emoji_count: 4,
+ },
+ null,
+ 2
+ )}
+
+
+
+
+
+
+
127ms
+
Execution time
+
+
+
+
+
+
+ );
+}