refactor: rewrite tutorial slides with coherent AI SDK narrative

Complete rewrite of all 9 slides to create a coherent story for engineers:

1. Welcome - TPMJS: A Tool Registry for the AI SDK
2. Problem - AI SDK Tools Are Static (compiled in, bundle grows)
3. Solution - Two imports enable dynamic tools at runtime
4. HowItWorks - The two meta-tools (search + execute)
5. Discovery - searchTpmjsToolsTool schema and response
6. Integration - registryExecuteTool execution flow
7. Quality - What gets indexed (schemas, scores, health)
8. ToolDetail - Full agent conversation flow example
9. GetStarted - How to publish tools to the registry

Also adds eslint.config.mjs to ignore .next build directory.
This commit is contained in:
Ajax Davis 2025-12-29 12:03:56 +10:00
parent 70d0c5ba94
commit e298109e94
10 changed files with 640 additions and 717 deletions

View file

@ -0,0 +1,16 @@
import reactConfig from '@tpmjs/eslint-config/react.js';
export default [
{
ignores: [
'.next/**',
'.turbo/**',
'node_modules/**',
'*.config.js',
'*.config.ts',
'next-env.d.ts',
'eslint.config.mjs',
],
},
...reactConfig,
];

View file

@ -2,76 +2,91 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
const searchSchema = [
' query: z.string(),',
' category?: z.enum([...]),',
' limit?: z.number().max(20),',
];
const responseExample = [
{ id: 'open', line: '{' },
{ id: 'tools', line: ' "tools": [{' },
{ id: 'toolId', line: ' "toolId": "@tpmjs/markdown::formatTable",' },
{ id: 'desc', line: ' "description": "Format markdown tables",' },
{ id: 'schema', line: ' "inputSchema": { ... },' },
{ id: 'score', line: ' "qualityScore": 0.92' },
{ id: 'closeArr', line: ' }]' },
{ id: 'close', line: '}' },
];
export function DiscoverySlide(): React.ReactElement { export function DiscoverySlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Background pulse */} <div className="absolute inset-0 bg-gradient-to-br from-cyan-900/10 via-transparent to-blue-900/10 pointer-events-none" />
<motion.div
className="absolute inset-0 bg-gradient-to-br from-cyan-900/20 via-transparent to-blue-900/20 pointer-events-none"
animate={{ opacity: [0.3, 0.5, 0.3] }}
transition={{ duration: 3, repeat: Number.POSITIVE_INFINITY, ease: 'easeInOut' }}
/>
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }} initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-4xl" className="relative z-10 max-w-5xl w-full"
> >
<motion.div <h2 className="text-4xl md:text-5xl font-bold text-white mb-4">searchTpmjsToolsTool</h2>
initial={{ scale: 0 }} <p className="text-xl text-white/50 mb-10">
animate={{ scale: 1 }} Agent describes what it needs. Registry returns matches.
transition={{ type: 'spring', stiffness: 200, delay: 0.2 }}
className="text-6xl mb-8"
>
⚙️
</motion.div>
<h2 className="text-5xl md:text-6xl font-bold text-white mb-4">Schema Extraction</h2>
<p className="text-xl text-white/40 mb-12">
The hard part.{' '}
<span className="text-cyan-400 font-semibold">We run your code in a sandbox.</span>
</p> </p>
{/* Code block showing extraction */} <div className="grid md:grid-cols-2 gap-6 max-w-4xl mx-auto text-left">
<motion.div {/* Input */}
initial={{ opacity: 0, y: 20 }} <motion.div
animate={{ opacity: 1, y: 0 }} initial={{ opacity: 0, x: -20 }}
transition={{ delay: 0.5 }} animate={{ opacity: 1, x: 0 }}
className="max-w-2xl mx-auto p-6 rounded-xl bg-[#1e1e2e] text-left font-mono text-sm" transition={{ delay: 0.3 }}
> >
<div className="text-white/40 mb-3"> <div className="text-xs text-cyan-400/60 font-mono mb-2">inputSchema</div>
{/* comment */} <div className="bg-[#1e1e2e] p-4 rounded-xl font-mono text-sm">
{'// We extract this from your actual code:'} <div className="text-white/40">{'z.object({'}</div>
</div> {searchSchema.map((line) => (
<div className="text-purple-400">inputSchema: {'{'}</div> <div key={line} className="text-cyan-400 pl-2">
<div className="text-white/80 pl-4"> {line}
type: <span className="text-emerald-400">&quot;object&quot;</span>, </div>
</div> ))}
<div className="text-white/80 pl-4">properties: {'{'}</div> <div className="text-white/40">{'})'}</div>
<div className="text-white/80 pl-8"> </div>
url: {'{'} type: <span className="text-emerald-400">&quot;string&quot;</span>, format:{' '} </motion.div>
<span className="text-emerald-400">&quot;uri&quot;</span> {'}'}
</div> {/* Output */}
<div className="text-white/80 pl-8"> <motion.div
timeout: {'{'} type: <span className="text-emerald-400">&quot;number&quot;</span>, initial={{ opacity: 0, x: 20 }}
default: <span className="text-cyan-400">30000</span> {'}'} animate={{ opacity: 1, x: 0 }}
</div> transition={{ delay: 0.5 }}
<div className="text-white/80 pl-4">{'}'}</div> >
<div className="text-purple-400">{'}'}</div> <div className="text-xs text-emerald-400/60 font-mono mb-2">returns</div>
</motion.div> <div className="bg-[#1e1e2e] p-4 rounded-xl font-mono text-sm">
{responseExample.map((item) => (
<div
key={item.id}
className={
item.line.includes('toolId')
? 'text-emerald-400'
: item.line.includes('qualityScore')
? 'text-yellow-400'
: 'text-white/60'
}
>
{item.line}
</div>
))}
</div>
</motion.div>
</div>
{/* Key insight */}
<motion.div <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ delay: 1.2 }} transition={{ delay: 0.8 }}
className="mt-8 text-white/40 text-lg" className="mt-8 text-white/40 text-sm"
> >
Not documentation.{' '} BM25 search over 200+ tools. Ranked by relevance and quality score.
<span className="text-emerald-400 font-semibold">
Ground truth from TypeScript types.
</span>
</motion.div> </motion.div>
</motion.div> </motion.div>
</div> </div>

View file

@ -2,46 +2,31 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
const links = [ const packageJsonLines = [
{ { id: 'open', line: '{' },
label: 'Browse Tools', { id: 'name', line: ' "name": "@your-org/your-tools",' },
href: 'https://tpmjs.com/tool-search', { id: 'keywords', line: ' "keywords": ["tpmjs-tool"],' },
description: 'Search by name, category, quality', { id: 'tpmjs', line: ' "tpmjs": {' },
icon: '🔍', { id: 'tools', line: ' "tools": [{' },
gradient: 'from-cyan-500 to-blue-500', { id: 'toolName', line: ' "name": "yourTool",' },
}, { id: 'desc', line: ' "description": "Does something useful"' },
{ { id: 'closeArr', line: ' }]' },
label: 'Publish a Tool', { id: 'closeTpmjs', line: ' }' },
href: 'https://tpmjs.com/docs/publishing', { id: 'close', line: '}' },
description: 'Add tpmjs-tool keyword to npm', ];
icon: '📦',
gradient: 'from-purple-500 to-pink-500', const steps = [
}, { step: '1', text: 'Add tpmjs-tool keyword', color: 'cyan' },
{ { step: '2', text: 'Define tpmjs field with tool metadata', color: 'purple' },
label: 'The Playground', { step: '3', text: 'npm publish', color: 'emerald' },
href: 'https://tpmjs.com/playground',
description: 'Run tools in browser sandbox',
icon: '🎮',
gradient: 'from-emerald-500 to-teal-500',
},
]; ];
export function GetStartedSlide(): React.ReactElement { export function GetStartedSlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Celebratory background */}
<div className="absolute inset-0 overflow-hidden pointer-events-none"> <div className="absolute inset-0 overflow-hidden pointer-events-none">
<motion.div <div
className="absolute w-[800px] h-[800px] rounded-full bg-gradient-to-r from-cyan-500/10 to-purple-500/10 blur-[150px]" className="absolute w-[600px] h-[600px] rounded-full bg-gradient-to-r from-cyan-500/5 to-purple-500/5 blur-[100px]"
animate={{
scale: [1, 1.2, 1],
rotate: [0, 180, 360],
}}
transition={{
duration: 20,
repeat: Number.POSITIVE_INFINITY,
ease: 'linear',
}}
style={{ top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }} style={{ top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }}
/> />
</div> </div>
@ -52,83 +37,107 @@ export function GetStartedSlide(): React.ReactElement {
transition={{ duration: 0.8 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-4xl w-full" className="relative z-10 max-w-4xl w-full"
> >
<motion.div <h2 className="text-4xl md:text-5xl font-bold text-white mb-4">Publish Your Tool</h2>
initial={{ scale: 0 }} <p className="text-xl text-white/50 mb-10">
animate={{ scale: 1 }} Add keyword. Define metadata. Publish. Indexed in 2 minutes.
transition={{ type: 'spring', stiffness: 200, delay: 0.2 }}
className="text-7xl mb-8"
>
🚀
</motion.div>
<h2 className="text-5xl md:text-7xl font-bold text-white mb-4">Get Started</h2>
<p className="text-xl md:text-2xl text-white/40 mb-16">
Indexed automatically. Updated every 2 minutes.
</p> </p>
{/* CTA buttons */} <div className="grid md:grid-cols-2 gap-6 max-w-4xl mx-auto">
<div className="flex flex-col md:flex-row items-center justify-center gap-6"> {/* package.json */}
{links.map((link, index) => ( <motion.div
<motion.a initial={{ opacity: 0, x: -20 }}
key={link.label} animate={{ opacity: 1, x: 0 }}
href={link.href} transition={{ delay: 0.3 }}
target="_blank" className="text-left"
rel="noopener noreferrer" >
initial={{ opacity: 0, y: 30 }} <div className="text-xs text-cyan-400/60 font-mono mb-2">package.json</div>
animate={{ opacity: 1, y: 0 }} <div className="bg-[#1e1e2e] p-4 rounded-xl font-mono text-sm">
transition={{ delay: 0.4 + index * 0.15 }} {packageJsonLines.map((item) => (
whileHover={{ scale: 1.05, y: -5 }} <div
whileTap={{ scale: 0.98 }} key={item.id}
className={` className={
group relative w-full md:w-auto item.line.includes('tpmjs-tool')
px-8 py-6 rounded-2xl ? 'text-cyan-400'
bg-gradient-to-br ${link.gradient} : item.line.includes('tpmjs')
text-white font-semibold text-lg ? 'text-purple-400'
shadow-lg shadow-black/20 : item.line.includes('name') || item.line.includes('description')
transition-shadow hover:shadow-xl hover:shadow-black/30 ? 'text-emerald-400'
`} : 'text-white/60'
> }
<div className="flex items-center gap-4">
<span className="text-3xl">{link.icon}</span>
<div className="text-left">
<div className="font-bold">{link.label}</div>
<div className="text-sm text-white/70">{link.description}</div>
</div>
</div>
{/* Hover arrow */}
<motion.div
className="absolute right-6 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity"
initial={{ x: -10 }}
whileHover={{ x: 0 }}
>
<svg
aria-hidden="true"
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
> >
<path {item.line}
strokeLinecap="round" </div>
strokeLinejoin="round" ))}
strokeWidth={2} </div>
d="M9 5l7 7-7 7" </motion.div>
/>
</svg> {/* Steps */}
</motion.div> <motion.div
</motion.a> initial={{ opacity: 0, x: 20 }}
))} animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.5 }}
className="text-left"
>
<div className="text-xs text-white/40 font-mono mb-2">three steps</div>
<div className="space-y-3">
{steps.map((item, i) => (
<motion.div
key={item.step}
initial={{ opacity: 0, x: 10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.7 + i * 0.1 }}
className="flex items-center gap-3"
>
<span
className={`w-8 h-8 rounded-full flex items-center justify-center text-sm font-mono ${
item.color === 'cyan'
? 'bg-cyan-500/20 text-cyan-400'
: item.color === 'purple'
? 'bg-purple-500/20 text-purple-400'
: 'bg-emerald-500/20 text-emerald-400'
}`}
>
{item.step}
</span>
<span className="text-sm text-white/70">{item.text}</span>
</motion.div>
))}
</div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1.2 }}
className="mt-6 p-4 rounded-lg bg-emerald-500/10 border border-emerald-500/20"
>
<code className="text-emerald-400 text-sm">npm publish</code>
<div className="text-xs text-white/40 mt-1">That&apos;s it. We find you.</div>
</motion.div>
</motion.div>
</div> </div>
{/* Footer */}
<motion.div <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ delay: 1.2 }} transition={{ delay: 1.5 }}
className="mt-16 text-white/30 text-sm" className="mt-10 flex flex-wrap justify-center gap-4"
> >
The missing layer between npm and AI agents. <a
href="https://tpmjs.com/tool-search"
target="_blank"
rel="noopener noreferrer"
className="px-6 py-3 rounded-lg bg-cyan-500/20 text-cyan-400 text-sm font-medium hover:bg-cyan-500/30 transition-colors"
>
Browse Registry
</a>
<a
href="https://tpmjs.com/playground"
target="_blank"
rel="noopener noreferrer"
className="px-6 py-3 rounded-lg bg-purple-500/20 text-purple-400 text-sm font-medium hover:bg-purple-500/30 transition-colors"
>
Try Playground
</a>
</motion.div> </motion.div>
</motion.div> </motion.div>
</div> </div>

View file

@ -2,89 +2,73 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
const steps = [ const tools = [
{ icon: '📦', label: 'npm publish', description: 'Add tpmjs-tool keyword' }, {
{ icon: '🔄', label: 'Auto-sync', description: 'Indexed in ~2 minutes' }, name: 'searchTpmjsToolsTool',
{ icon: '⚙️', label: 'Schema extracted', description: 'From actual code' }, package: '@tpmjs/search-registry',
{ icon: '✅', label: 'Health checked', description: 'Import + execution' }, description: 'Agent searches the registry by query, category, or context',
color: 'cyan',
},
{
name: 'registryExecuteTool',
package: '@tpmjs/registry-execute',
description: 'Agent executes a discovered tool by ID in a sandbox',
color: 'purple',
},
]; ];
export function HowItWorksSlide(): React.ReactElement { export function HowItWorksSlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Background gradient */} <div className="absolute inset-0 bg-gradient-to-br from-cyan-900/10 via-transparent to-purple-900/10 pointer-events-none" />
<div className="absolute inset-0 bg-gradient-to-br from-blue-900/10 via-transparent to-purple-900/10 pointer-events-none" />
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }} initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-5xl w-full" className="relative z-10 max-w-4xl w-full"
> >
<h2 className="text-5xl md:text-6xl font-bold text-white mb-4">How It Works</h2> <h2 className="text-4xl md:text-5xl font-bold text-white mb-4">Two Meta-Tools</h2>
<p className="text-xl text-white/40 mb-16">Automated pipeline. No manual curation.</p> <p className="text-xl text-white/50 mb-12">Tools that discover and execute other tools</p>
{/* Flow diagram */} <div className="grid md:grid-cols-2 gap-6 max-w-3xl mx-auto">
<div className="flex flex-col md:flex-row items-center justify-center gap-4 md:gap-0"> {tools.map((tool, index) => (
{steps.map((step, index) => ( <motion.div
<div key={step.label} className="flex items-center"> key={tool.name}
{/* Step card */} initial={{ opacity: 0, y: 20 }}
<motion.div animate={{ opacity: 1, y: 0 }}
initial={{ opacity: 0, y: 30 }} transition={{ delay: 0.3 + index * 0.2 }}
animate={{ opacity: 1, y: 0 }} className={`p-6 rounded-xl bg-white/5 border text-left ${
transition={{ delay: 0.3 + index * 0.2 }} tool.color === 'cyan' ? 'border-cyan-500/30' : 'border-purple-500/30'
className="flex flex-col items-center" }`}
>
<div
className={`text-xs font-mono mb-2 ${
tool.color === 'cyan' ? 'text-cyan-400/60' : 'text-purple-400/60'
}`}
> >
<motion.div {tool.package}
initial={{ scale: 0 }} </div>
animate={{ scale: 1 }} <div
transition={{ className={`text-lg font-semibold mb-3 ${
delay: 0.5 + index * 0.2, tool.color === 'cyan' ? 'text-cyan-400' : 'text-purple-400'
type: 'spring', }`}
stiffness: 300, >
}} {tool.name}
className="w-20 h-20 md:w-24 md:h-24 rounded-2xl bg-gradient-to-br from-white/10 to-white/5 border border-white/10 flex items-center justify-center text-4xl md:text-5xl mb-4 hover:from-white/15 hover:to-white/10 transition-colors" </div>
> <div className="text-sm text-white/50">{tool.description}</div>
{step.icon} </motion.div>
</motion.div>
<span className="text-white font-semibold text-lg">{step.label}</span>
<span className="text-white/40 text-sm mt-1">{step.description}</span>
</motion.div>
{/* Arrow */}
{index < steps.length - 1 && (
<motion.div
initial={{ opacity: 0, scaleX: 0 }}
animate={{ opacity: 1, scaleX: 1 }}
transition={{ delay: 0.8 + index * 0.2 }}
className="hidden md:flex items-center mx-6"
>
<div className="w-12 h-px bg-gradient-to-r from-cyan-500/50 to-purple-500/50" />
<svg
aria-hidden="true"
className="w-4 h-4 text-purple-500/50 -ml-1"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</motion.div>
)}
</div>
))} ))}
</div> </div>
{/* Animated highlight line */}
<motion.div <motion.div
initial={{ scaleX: 0, opacity: 0 }} initial={{ opacity: 0 }}
animate={{ scaleX: 1, opacity: 1 }} animate={{ opacity: 1 }}
transition={{ delay: 1.8, duration: 1 }} transition={{ delay: 1 }}
className="mt-16 h-1 bg-gradient-to-r from-transparent via-cyan-500/30 to-transparent rounded-full max-w-md mx-auto" className="mt-10 text-white/40 text-sm font-mono"
/> >
Both are standard AI SDK tools. Pass them to generateText like any other.
</motion.div>
</motion.div> </motion.div>
</div> </div>
); );

View file

@ -1,123 +1,100 @@
'use client'; 'use client';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useEffect, useState } from 'react';
const codeLines = [ const executeSchema = [
{ text: '// Quality score: 0.00 - 1.00', delay: 0.5 }, ' toolId: z.string(),',
{ text: "const tier = tier === 'rich' ? 0.6 : 0.4;", delay: 0.8 }, ' params: z.record(z.unknown()),',
{ text: 'const downloads = Math.min(0.2, log10(d));', delay: 1.1 }, ' env?: z.record(z.string()),',
{ text: 'const stars = Math.min(0.1, log10(s));', delay: 1.4 },
{ text: '', delay: 1.7 },
{ text: '// Rich = has params, returns, env', delay: 2.0 },
{ text: 'const score = tier + downloads + stars;', delay: 2.3 },
]; ];
function TypewriterLine({ text, delay }: { text: string; delay: number }) { const flowSteps = [
const [displayText, setDisplayText] = useState(''); { step: '1', text: 'Fetch tool metadata from registry', color: 'cyan' },
{ step: '2', text: 'Import package from esm.sh', color: 'purple' },
useEffect(() => { { step: '3', text: 'Execute in isolated sandbox', color: 'emerald' },
if (!text) { { step: '4', text: 'Return result to agent', color: 'yellow' },
setDisplayText(''); ];
return;
}
const timeout = setTimeout(() => {
let i = 0;
const interval = setInterval(() => {
if (i <= text.length) {
setDisplayText(text.slice(0, i));
i++;
} else {
clearInterval(interval);
}
}, 30);
return () => clearInterval(interval);
}, delay * 1000);
return () => clearTimeout(timeout);
}, [text, delay]);
// Simple text display without syntax highlighting to avoid dangerouslySetInnerHTML
const isComment = displayText.startsWith('//');
return (
<div
className={`font-mono text-sm md:text-base leading-relaxed ${isComment ? 'text-white/30' : 'text-white/80'}`}
>
{displayText || '\u00A0'}
</div>
);
}
export function IntegrationSlide(): React.ReactElement { export function IntegrationSlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Background */} <div className="absolute inset-0 bg-gradient-to-br from-purple-900/10 via-transparent to-emerald-900/10 pointer-events-none" />
<div className="absolute inset-0 bg-gradient-to-br from-purple-900/10 via-transparent to-pink-900/10 pointer-events-none" />
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }} initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-4xl w-full" className="relative z-10 max-w-5xl w-full"
> >
<motion.div <h2 className="text-4xl md:text-5xl font-bold text-white mb-4">registryExecuteTool</h2>
initial={{ scale: 0 }} <p className="text-xl text-white/50 mb-10">
animate={{ scale: 1 }} Run any tool from the registry. No install. No bundle.
transition={{ type: 'spring', stiffness: 200, delay: 0.2 }} </p>
className="text-6xl mb-8"
>
📊
</motion.div>
<h2 className="text-5xl md:text-6xl font-bold text-white mb-4">Quality Scoring</h2> <div className="grid md:grid-cols-2 gap-6 max-w-4xl mx-auto">
<p className="text-xl text-white/40 mb-12">Deliberately simple. Not trying to be clever.</p> {/* Input */}
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.3 }}
className="text-left"
>
<div className="text-xs text-purple-400/60 font-mono mb-2">inputSchema</div>
<div className="bg-[#1e1e2e] p-4 rounded-xl font-mono text-sm">
<div className="text-white/40">{'z.object({'}</div>
{executeSchema.map((line) => (
<div key={line} className="text-purple-400 pl-2">
{line}
</div>
))}
<div className="text-white/40">{'})'}</div>
</div>
</motion.div>
{/* Code block */} {/* Flow */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.3 }} transition={{ delay: 0.5 }}
className="relative max-w-2xl mx-auto" className="text-left"
> >
{/* Window chrome */} <div className="text-xs text-white/40 font-mono mb-2">execution flow</div>
<div className="flex items-center gap-2 px-4 py-3 bg-[#1e1e2e] rounded-t-xl border-b border-white/5"> <div className="space-y-2">
<div className="w-3 h-3 rounded-full bg-red-500/80" /> {flowSteps.map((item, i) => (
<div className="w-3 h-3 rounded-full bg-yellow-500/80" /> <motion.div
<div className="w-3 h-3 rounded-full bg-green-500/80" /> key={item.step}
<span className="ml-4 text-xs text-white/30 font-mono">agent.ts</span> initial={{ opacity: 0, x: 10 }}
</div> animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.7 + i * 0.1 }}
className="flex items-center gap-3"
>
<span
className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-mono ${
item.color === 'cyan'
? 'bg-cyan-500/20 text-cyan-400'
: item.color === 'purple'
? 'bg-purple-500/20 text-purple-400'
: item.color === 'emerald'
? 'bg-emerald-500/20 text-emerald-400'
: 'bg-yellow-500/20 text-yellow-400'
}`}
>
{item.step}
</span>
<span className="text-sm text-white/60">{item.text}</span>
</motion.div>
))}
</div>
</motion.div>
</div>
{/* Code content */}
<div className="bg-[#1e1e2e] p-6 rounded-b-xl text-left overflow-x-auto">
{codeLines.map((line) => (
<TypewriterLine key={line.text || line.delay} text={line.text} delay={line.delay} />
))}
<motion.span
animate={{ opacity: [1, 0, 1] }}
transition={{ duration: 1, repeat: Number.POSITIVE_INFINITY }}
className="inline-block w-2 h-5 bg-cyan-400 ml-0.5"
/>
</div>
</motion.div>
{/* Score factors */}
<motion.div <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ delay: 3 }} transition={{ delay: 1.2 }}
className="mt-8 flex flex-wrap justify-center gap-3" className="mt-8 text-white/40 text-sm"
> >
{['Tier: 40-60%', 'Downloads: 0-20%', 'Stars: 0-10%', 'Richness: 0-10%'].map((factor) => ( Sandbox runs on Railway. 5s timeout. Isolated per execution.
<span
key={factor}
className="px-3 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-cyan-400/70 text-sm font-mono"
>
{factor}
</span>
))}
</motion.div> </motion.div>
</motion.div> </motion.div>
</div> </div>

View file

@ -2,103 +2,85 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
const floatingIcons = [ const codeLines = [
{ icon: '🔧', x: '15%', y: '20%', delay: 0 }, "import { weatherTool } from './tools/weather';",
{ icon: '⚙️', x: '75%', y: '15%', delay: 0.2 }, "import { searchTool } from './tools/search';",
{ icon: '🔌', x: '85%', y: '60%', delay: 0.4 }, "import { calendarTool } from './tools/calendar';",
{ icon: '📦', x: '10%', y: '70%', delay: 0.6 }, "import { emailTool } from './tools/email';",
{ icon: '🛠️', x: '60%', y: '80%', delay: 0.8 }, '// ... 47 more imports',
{ icon: '🔗', x: '25%', y: '45%', delay: 1 }, '',
{ icon: '📡', x: '80%', y: '35%', delay: 1.2 }, 'const result = await generateText({',
{ icon: '💾', x: '40%', y: '25%', delay: 1.4 }, " model: openai('gpt-4-turbo'),",
' tools: { weather, search, calendar, email, ... },',
'});',
]; ];
export function ProblemSlide(): React.ReactElement { export function ProblemSlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Floating chaotic icons */} <div className="absolute inset-0 bg-gradient-to-br from-orange-900/10 via-transparent to-red-900/10 pointer-events-none" />
{floatingIcons.map((item) => (
<motion.div
key={item.icon}
className="absolute text-4xl md:text-5xl opacity-20"
initial={{ opacity: 0, scale: 0 }}
animate={{
opacity: 0.2,
scale: 1,
x: [0, Math.random() * 40 - 20, 0],
y: [0, Math.random() * 40 - 20, 0],
rotate: [0, Math.random() * 30 - 15, 0],
}}
transition={{
opacity: { duration: 0.5, delay: item.delay },
scale: { duration: 0.5, delay: item.delay },
x: {
duration: 4 + Math.random() * 2,
repeat: Number.POSITIVE_INFINITY,
ease: 'easeInOut',
},
y: {
duration: 3 + Math.random() * 2,
repeat: Number.POSITIVE_INFINITY,
ease: 'easeInOut',
},
rotate: {
duration: 5 + Math.random() * 2,
repeat: Number.POSITIVE_INFINITY,
ease: 'easeInOut',
},
}}
style={{ left: item.x, top: item.y }}
>
{item.icon}
</motion.div>
))}
{/* Red warning gradient */}
<div className="absolute inset-0 bg-gradient-to-br from-red-900/10 via-transparent to-orange-900/10 pointer-events-none" />
{/* Content */}
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }} initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.3 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-4xl" className="relative z-10 max-w-4xl w-full"
> >
<motion.div <h2 className="text-4xl md:text-5xl font-bold text-white mb-4">AI SDK Tools Are Static</h2>
initial={{ scale: 0 }} <p className="text-xl text-white/50 mb-12">
animate={{ scale: 1 }} You import them. You bundle them. They&apos;re compiled in.
transition={{ type: 'spring', stiffness: 200, delay: 0.2 }}
className="text-6xl mb-8"
>
😵
</motion.div>
<h2 className="text-5xl md:text-6xl font-bold text-white mb-6">The Problem</h2>
<p className="text-xl md:text-2xl text-white/60 leading-relaxed max-w-2xl">
npm has <span className="text-red-400 font-semibold">2 million packages</span>.
<br />
Which ones are AI-callable tools? Which ones{' '}
<span className="text-orange-400 font-semibold">actually work</span>?
</p> </p>
{/* Code block */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="max-w-2xl mx-auto text-left"
>
<div className="flex items-center gap-2 px-4 py-3 bg-[#1e1e2e] rounded-t-xl border-b border-white/5">
<div className="w-3 h-3 rounded-full bg-red-500/80" />
<div className="w-3 h-3 rounded-full bg-yellow-500/80" />
<div className="w-3 h-3 rounded-full bg-green-500/80" />
<span className="ml-4 text-xs text-white/30 font-mono">agent.ts</span>
</div>
<div className="bg-[#1e1e2e] p-6 rounded-b-xl overflow-x-auto">
{codeLines.map((line, i) => (
<motion.div
key={line || `empty-${i}`}
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.5 + i * 0.1 }}
className={`font-mono text-sm leading-relaxed ${
line.startsWith('import')
? 'text-purple-400'
: line.startsWith('//')
? 'text-white/30'
: line.includes('generateText')
? 'text-cyan-400'
: 'text-white/70'
}`}
>
{line || '\u00A0'}
</motion.div>
))}
</div>
</motion.div>
<motion.div <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ delay: 1 }} transition={{ delay: 1.5 }}
className="mt-12 flex flex-wrap justify-center gap-4" className="mt-8 flex flex-wrap justify-center gap-3"
> >
{["Can't find them", "Can't trust them", "Can't compare them", 'No schemas'].map( {['Every tool compiled in', 'Bundle grows forever', 'No runtime discovery'].map(
(word, i) => ( (text) => (
<motion.span <span
key={word} key={text}
initial={{ opacity: 0, y: 20 }} className="px-3 py-1.5 rounded-full border border-orange-500/30 text-orange-400/70 text-sm font-mono"
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 1.2 + i * 0.1 }}
className="px-4 py-2 rounded-full border border-red-500/30 text-red-400/60 text-sm font-mono"
> >
{word} {text}
</motion.span> </span>
) )
)} )}
</motion.div> </motion.div>

View file

@ -1,137 +1,106 @@
'use client'; 'use client';
import { animate, motion, useMotionValue } from 'framer-motion'; import { motion } from 'framer-motion';
import { useEffect, useState } from 'react';
function AnimatedGauge({ value, delay = 0 }: { value: number; delay?: number }) { const registryData = [
const progress = useMotionValue(0); { field: 'toolId', value: '"@tpmjs/markdown::formatTable"', color: 'cyan' },
const [displayValue, setDisplayValue] = useState(0); { field: 'description', value: '"Format markdown tables"', color: 'white' },
{ field: 'inputSchema', value: '{ type: "object", ... }', color: 'purple' },
useEffect(() => { { field: 'returnSchema', value: '{ type: "string" }', color: 'purple' },
const timeout = setTimeout(() => { { field: 'envKeys', value: '[]', color: 'yellow' },
animate(progress, value, { { field: 'qualityScore', value: '0.92', color: 'emerald' },
duration: 1.5, ];
ease: 'easeOut',
});
}, delay * 1000);
return () => clearTimeout(timeout);
}, [progress, value, delay]);
useEffect(() => {
const unsubscribe = progress.on('change', (v) => setDisplayValue(Math.round(v)));
return unsubscribe;
}, [progress]);
const circumference = 2 * Math.PI * 45;
const strokeDashoffset = circumference - (displayValue / 100) * circumference;
return (
<div className="relative w-32 h-32">
<svg aria-hidden="true" className="w-full h-full transform -rotate-90">
{/* Background circle */}
<circle cx="64" cy="64" r="45" fill="none" stroke="rgba(255,255,255,0.1)" strokeWidth="8" />
{/* Progress circle */}
<circle
cx="64"
cy="64"
r="45"
fill="none"
stroke="url(#gradient)"
strokeWidth="8"
strokeLinecap="round"
strokeDasharray={circumference}
strokeDashoffset={strokeDashoffset}
/>
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stopColor="#22d3ee" />
<stop offset="100%" stopColor="#a855f7" />
</linearGradient>
</defs>
</svg>
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-2xl font-bold text-white">{displayValue}%</span>
</div>
</div>
);
}
const qualityFactors = [ const qualityFactors = [
{ name: 'Import Health', icon: '📦', score: 95, color: 'cyan', desc: 'Can we require() it?' }, { name: 'Schema Completeness', desc: 'Input/output types defined' },
{ name: 'Execution Health', icon: '▶️', score: 88, color: 'emerald', desc: 'Does it run at all?' }, { name: 'npm Downloads', desc: 'Community adoption signal' },
{ name: 'HEALTHY', icon: '✅', score: 100, color: 'emerald', desc: 'Passed both checks' }, { name: 'Health Status', desc: 'Can it import and execute?' },
{ name: 'BROKEN', icon: '❌', score: 0, color: 'yellow', desc: 'Labeled, not hidden' },
]; ];
export function QualitySlide(): React.ReactElement { export function QualitySlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Background */}
<div className="absolute inset-0 bg-gradient-to-br from-yellow-900/10 via-transparent to-emerald-900/10 pointer-events-none" /> <div className="absolute inset-0 bg-gradient-to-br from-yellow-900/10 via-transparent to-emerald-900/10 pointer-events-none" />
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }} initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-4xl w-full" className="relative z-10 max-w-5xl w-full"
> >
<motion.div <h2 className="text-4xl md:text-5xl font-bold text-white mb-4">What Gets Indexed</h2>
initial={{ scale: 0 }} <p className="text-xl text-white/50 mb-10">
animate={{ scale: 1 }} Schemas extracted. Quality scored. Health checked.
transition={{ type: 'spring', stiffness: 200, delay: 0.2 }}
className="text-6xl mb-8"
>
⭐
</motion.div>
<h2 className="text-5xl md:text-6xl font-bold text-white mb-4">Health Checks</h2>
<p className="text-xl text-white/40 mb-12">
We don&apos;t hide broken tools. We <span className="text-yellow-400">label them</span>.
</p> </p>
{/* Main gauge */} <div className="grid md:grid-cols-2 gap-6 max-w-4xl mx-auto">
<motion.div {/* Registry entry */}
initial={{ opacity: 0, scale: 0.8 }} <motion.div
animate={{ opacity: 1, scale: 1 }} initial={{ opacity: 0, x: -20 }}
transition={{ delay: 0.4 }} animate={{ opacity: 1, x: 0 }}
className="flex justify-center mb-12" transition={{ delay: 0.3 }}
> className="text-left"
<AnimatedGauge value={92} delay={0.6} /> >
</motion.div> <div className="text-xs text-emerald-400/60 font-mono mb-2">registry entry</div>
<div className="bg-[#1e1e2e] p-4 rounded-xl font-mono text-sm">
<div className="text-white/40">{'{'}</div>
{registryData.map((item) => (
<div key={item.field} className="pl-2">
<span className="text-white/60">{item.field}: </span>
<span
className={
item.color === 'cyan'
? 'text-cyan-400'
: item.color === 'purple'
? 'text-purple-400'
: item.color === 'emerald'
? 'text-emerald-400'
: item.color === 'yellow'
? 'text-yellow-400'
: 'text-white/60'
}
>
{item.value}
</span>
</div>
))}
<div className="text-white/40">{'}'}</div>
</div>
</motion.div>
{/* Quality factors */} {/* Quality factors */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-6"> <motion.div
{qualityFactors.map((factor, index) => ( initial={{ opacity: 0, x: 20 }}
<motion.div animate={{ opacity: 1, x: 0 }}
key={factor.name} transition={{ delay: 0.5 }}
initial={{ opacity: 0, y: 20 }} className="text-left"
animate={{ opacity: 1, y: 0 }} >
transition={{ delay: 1 + index * 0.15 }} <div className="text-xs text-yellow-400/60 font-mono mb-2">qualityScore factors</div>
className="p-4 rounded-xl bg-white/5 border border-white/10" <div className="space-y-3">
> {qualityFactors.map((factor, i) => (
<div className="text-3xl mb-2">{factor.icon}</div>
<div className="text-base font-semibold text-white mb-1">{factor.name}</div>
<div className="text-xs text-white/40 mb-3">{factor.desc}</div>
<div className="w-full h-2 bg-white/10 rounded-full overflow-hidden">
<motion.div <motion.div
initial={{ width: 0 }} key={factor.name}
animate={{ width: `${factor.score}%` }} initial={{ opacity: 0, x: 10 }}
transition={{ delay: 1.5 + index * 0.15, duration: 1 }} animate={{ opacity: 1, x: 0 }}
className={`h-full rounded-full ${ transition={{ delay: 0.7 + i * 0.1 }}
factor.color === 'cyan' className="p-3 rounded-lg bg-white/5 border border-white/10"
? 'bg-cyan-400' >
: factor.color === 'purple' <div className="text-sm font-medium text-white">{factor.name}</div>
? 'bg-purple-400' <div className="text-xs text-white/40">{factor.desc}</div>
: factor.color === 'emerald' </motion.div>
? 'bg-emerald-400' ))}
: 'bg-yellow-400' </div>
}`} </motion.div>
/>
</div>
</motion.div>
))}
</div> </div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1.2 }}
className="mt-8 text-white/40 text-sm"
>
Synced from npm every 2 minutes. 200+ tools indexed.
</motion.div>
</motion.div> </motion.div>
</div> </div>
); );

View file

@ -2,84 +2,82 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
const gridItems = Array.from({ length: 12 }, (_, i) => ({ const codeLines = [
icon: ['🔧', '⚙️', '📦', '🔌', '🛠️', '📡', '💾', '🔗', '🎯', '⚡', '🌐', '🔐'][i], "import { searchTpmjsToolsTool } from '@tpmjs/search-registry';",
delay: i * 0.05, "import { registryExecuteTool } from '@tpmjs/registry-execute';",
})); '',
'const result = await generateText({',
" model: openai('gpt-4-turbo'),",
' tools: { search: searchTpmjsToolsTool, execute: registryExecuteTool },',
" prompt: 'Format this markdown table for me...',",
'});',
];
export function SolutionSlide(): React.ReactElement { export function SolutionSlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Green success gradient */}
<div className="absolute inset-0 bg-gradient-to-br from-emerald-900/10 via-transparent to-cyan-900/10 pointer-events-none" /> <div className="absolute inset-0 bg-gradient-to-br from-emerald-900/10 via-transparent to-cyan-900/10 pointer-events-none" />
{/* Content */}
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }} initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-4xl" className="relative z-10 max-w-4xl w-full"
> >
<h2 className="text-4xl md:text-5xl font-bold text-white mb-4">
What If Tools Were Dynamic?
</h2>
<p className="text-xl text-white/50 mb-12">Two imports. Infinite tools at runtime.</p>
{/* Code block */}
<motion.div <motion.div
initial={{ scale: 0 }} initial={{ opacity: 0, y: 20 }}
animate={{ scale: 1 }} animate={{ opacity: 1, y: 0 }}
transition={{ type: 'spring', stiffness: 200, delay: 0.2 }} transition={{ delay: 0.3 }}
className="text-6xl mb-8" className="max-w-2xl mx-auto text-left"
> >
✨ <div className="flex items-center gap-2 px-4 py-3 bg-[#1e1e2e] rounded-t-xl border-b border-white/5">
</motion.div> <div className="w-3 h-3 rounded-full bg-red-500/80" />
<div className="w-3 h-3 rounded-full bg-yellow-500/80" />
<h2 className="text-5xl md:text-6xl font-bold text-white mb-6">What TPMJS Is</h2> <div className="w-3 h-3 rounded-full bg-green-500/80" />
<span className="ml-4 text-xs text-white/30 font-mono">agent.ts</span>
<p className="text-xl md:text-2xl text-white/60 leading-relaxed mb-12 max-w-2xl"> </div>
A <span className="text-cyan-400 font-semibold">registry</span> that indexes npm packages <div className="bg-[#1e1e2e] p-6 rounded-b-xl overflow-x-auto">
for AI tool use. {codeLines.map((line, i) => (
<br /> <motion.div
<span className="text-emerald-400 font-semibold">Extracts schemas from code</span>. Scores key={line || `empty-${i}`}
quality. Checks health. initial={{ opacity: 0, x: -10 }}
</p> animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.5 + i * 0.1 }}
{/* Organized grid of icons */} className={`font-mono text-sm leading-relaxed ${
<motion.div line.startsWith('import')
initial={{ opacity: 0 }} ? 'text-emerald-400'
animate={{ opacity: 1 }} : line.includes('searchTpmjsToolsTool') || line.includes('registryExecuteTool')
transition={{ delay: 0.5 }} ? 'text-cyan-400'
className="grid grid-cols-4 md:grid-cols-6 gap-4 max-w-lg mx-auto" : line.includes('generateText')
> ? 'text-purple-400'
{gridItems.map((item) => ( : 'text-white/70'
<motion.div }`}
key={item.icon} >
initial={{ opacity: 0, scale: 0, y: 20 }} {line || '\u00A0'}
animate={{ opacity: 1, scale: 1, y: 0 }} </motion.div>
transition={{ ))}
delay: 0.8 + item.delay, </div>
type: 'spring',
stiffness: 300,
damping: 20,
}}
className="w-12 h-12 md:w-14 md:h-14 rounded-xl bg-white/5 border border-white/10 flex items-center justify-center text-2xl hover:bg-white/10 hover:border-white/20 transition-colors cursor-default"
>
{item.icon}
</motion.div>
))}
</motion.div> </motion.div>
<motion.div <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ delay: 1.5 }} transition={{ delay: 1.5 }}
className="mt-12 flex flex-wrap justify-center gap-4" className="mt-8 flex flex-wrap justify-center gap-3"
> >
{['Registry', 'Schema extraction', 'Quality scoring', 'Health checks'].map((word, i) => ( {['Discover at runtime', 'Execute in sandbox', 'No bundling'].map((text) => (
<motion.span <span
key={word} key={text}
initial={{ opacity: 0, y: 20 }} className="px-3 py-1.5 rounded-full border border-emerald-500/30 text-emerald-400/70 text-sm font-mono"
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 1.7 + i * 0.1 }}
className="px-4 py-2 rounded-full border border-emerald-500/30 text-emerald-400/60 text-sm font-mono"
> >
{word} {text}
</motion.span> </span>
))} ))}
</motion.div> </motion.div>
</motion.div> </motion.div>

View file

@ -2,111 +2,107 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
const roleStyles: Record<string, string> = {
user: 'bg-white/10 text-white/60',
agent: 'bg-cyan-500/20 text-cyan-400',
registry: 'bg-emerald-500/20 text-emerald-400',
sandbox: 'bg-yellow-500/20 text-yellow-400',
};
const colorStyles: Record<string, string> = {
white: 'text-white/70',
cyan: 'text-cyan-400',
purple: 'text-purple-400',
emerald: 'text-emerald-400',
yellow: 'text-yellow-400',
};
const conversation = [
{
id: 'user-ask',
role: 'user',
content: '"Format this CSV as a markdown table"',
color: 'white',
},
{
id: 'agent-search',
role: 'agent',
content: 'searchTpmjsToolsTool({ query: "markdown table" })',
color: 'cyan',
},
{
id: 'registry-found',
role: 'registry',
content: '→ Found: @tpmjs/markdown::formatTable',
color: 'emerald',
},
{
id: 'agent-execute',
role: 'agent',
content: 'registryExecuteTool({ toolId: "...", params: {...} })',
color: 'purple',
},
{
id: 'sandbox-result',
role: 'sandbox',
content: '→ Executed in 120ms',
color: 'yellow',
},
{
id: 'agent-respond',
role: 'agent',
content: '"Here\'s your formatted table: ..."',
color: 'white',
},
];
export function ToolDetailSlide(): React.ReactElement { export function ToolDetailSlide(): React.ReactElement {
return ( return (
<div className="relative flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center">
{/* Background */}
<div className="absolute inset-0 bg-gradient-to-br from-indigo-900/10 via-transparent to-cyan-900/10 pointer-events-none" /> <div className="absolute inset-0 bg-gradient-to-br from-indigo-900/10 via-transparent to-cyan-900/10 pointer-events-none" />
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }} initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }} transition={{ duration: 0.8 }}
className="relative z-10 max-w-4xl w-full" className="relative z-10 max-w-3xl w-full"
> >
<h2 className="text-5xl md:text-6xl font-bold text-white mb-4">What We Store</h2> <h2 className="text-4xl md:text-5xl font-bold text-white mb-4">Full Agent Flow</h2>
<p className="text-xl text-white/40 mb-12"> <p className="text-xl text-white/50 mb-10">
Everything an agent needs to <span className="text-cyan-400">call a tool correctly</span> User asks. Agent searches. Tool executes. Done.
</p> </p>
{/* Mock tool card */} <div className="space-y-3 text-left">
<motion.div {conversation.map((msg, i) => (
initial={{ opacity: 0, y: 20, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
transition={{ delay: 0.3 }}
className="max-w-xl mx-auto p-6 rounded-2xl bg-gradient-to-br from-white/10 to-white/5 border border-white/10 text-left"
>
{/* Header */}
<div className="flex items-start justify-between mb-6">
<div>
<div className="flex items-center gap-3 mb-2">
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ delay: 0.5, type: 'spring' }}
className="w-12 h-12 rounded-xl bg-gradient-to-br from-cyan-500 to-blue-500 flex items-center justify-center text-2xl"
>
🔍
</motion.div>
<div>
<h3 className="text-xl font-bold text-white">webSearch</h3>
<span className="text-sm text-white/40 font-mono">@tpmjs/web-tools</span>
</div>
</div>
</div>
<motion.div <motion.div
initial={{ opacity: 0 }} key={msg.id}
animate={{ opacity: 1 }} initial={{ opacity: 0, x: msg.role === 'user' ? -20 : 20 }}
transition={{ delay: 0.7 }} animate={{ opacity: 1, x: 0 }}
className="px-2 py-1 rounded bg-emerald-500/20 text-emerald-400 text-xs font-medium" transition={{ delay: 0.3 + i * 0.15 }}
className={`flex items-start gap-3 ${msg.role === 'user' ? '' : 'pl-4'}`}
> >
Verified <span
className={`text-xs font-mono px-2 py-1 rounded ${roleStyles[msg.role] ?? roleStyles.user}`}
>
{msg.role}
</span>
<span className={`font-mono text-sm ${colorStyles[msg.color] ?? colorStyles.white}`}>
{msg.content}
</span>
</motion.div> </motion.div>
))}
</div>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1.5 }}
className="mt-10 p-4 rounded-xl bg-white/5 border border-white/10"
>
<div className="text-sm text-white/60">
The agent never imported <span className="text-cyan-400 font-mono">formatTable</span>.
It discovered and executed it at runtime.
</div> </div>
{/* Description */}
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.6 }}
className="text-white/60 mb-6"
>
Search the web and return structured results. Supports query filtering, result limits,
and domain restrictions.
</motion.p>
{/* Metadata grid */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.8 }}
className="grid grid-cols-3 gap-4 mb-6"
>
<div className="p-3 rounded-lg bg-white/5">
<div className="text-xs text-white/40 mb-1">Downloads</div>
<div className="text-lg font-bold text-white">12.4k</div>
</div>
<div className="p-3 rounded-lg bg-white/5">
<div className="text-xs text-white/40 mb-1">Quality</div>
<div className="text-lg font-bold text-cyan-400">94%</div>
</div>
<div className="p-3 rounded-lg bg-white/5">
<div className="text-xs text-white/40 mb-1">Category</div>
<div className="text-lg font-bold text-purple-400">Search</div>
</div>
</motion.div>
{/* Schema preview */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1 }}
className="p-4 rounded-lg bg-black/30 font-mono text-sm"
>
<div className="text-white/40 mb-2">{'// Extracted from actual code'}</div>
<div className="text-purple-400">
inputSchema: <span className="text-white/60">JSON Schema</span>
</div>
<div className="text-purple-400">
returnSchema: <span className="text-white/60">JSON Schema</span>
</div>
<div className="text-purple-400">
envKeys: <span className="text-white/60">[&quot;API_KEY&quot;]</span>
</div>
<div className="text-purple-400">
tier: <span className="text-emerald-400">&quot;rich&quot;</span>
</div>
</motion.div>
</motion.div> </motion.div>
</motion.div> </motion.div>
</div> </div>

View file

@ -4,76 +4,53 @@ import { motion } from 'framer-motion';
export function WelcomeSlide(): React.ReactElement { export function WelcomeSlide(): React.ReactElement {
return ( return (
<div className="flex flex-col items-center justify-center h-full px-8 text-center"> <div className="relative flex flex-col items-center justify-center h-full px-8 text-center overflow-hidden">
{/* Animated background orbs */} {/* Subtle gradient background */}
<div className="absolute inset-0 overflow-hidden pointer-events-none"> <div className="absolute inset-0 bg-gradient-to-br from-cyan-900/20 via-transparent to-purple-900/20 pointer-events-none" />
<motion.div
className="absolute w-[600px] h-[600px] rounded-full bg-cyan-500/10 blur-[120px]"
animate={{
x: [0, 100, 0],
y: [0, -50, 0],
}}
transition={{
duration: 10,
repeat: Number.POSITIVE_INFINITY,
ease: 'easeInOut',
}}
style={{ top: '10%', left: '20%' }}
/>
<motion.div
className="absolute w-[500px] h-[500px] rounded-full bg-purple-500/10 blur-[100px]"
animate={{
x: [0, -80, 0],
y: [0, 60, 0],
}}
transition={{
duration: 12,
repeat: Number.POSITIVE_INFINITY,
ease: 'easeInOut',
}}
style={{ bottom: '20%', right: '15%' }}
/>
</div>
{/* Logo / Title */} {/* Main content */}
<motion.div <motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
className="relative z-10"
>
<h1 className="text-8xl md:text-9xl font-bold tracking-tighter">
<span className="bg-gradient-to-r from-cyan-400 via-blue-400 to-purple-500 bg-clip-text text-transparent">
TPMJS
</span>
</h1>
</motion.div>
{/* Tagline */}
<motion.p
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.5 }} transition={{ duration: 0.8, ease: 'easeOut' }}
className="mt-6 text-2xl md:text-3xl text-white/60 font-light max-w-2xl" className="relative z-10 max-w-4xl"
> >
The missing layer between &quot;LLMs can call tools&quot; and &quot;which tool, <motion.div
exactly?&quot; initial={{ opacity: 0, scale: 0.9 }}
</motion.p> animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.6, delay: 0.2 }}
className="mb-8"
>
<span className="text-6xl md:text-7xl font-bold bg-gradient-to-r from-cyan-400 to-purple-400 bg-clip-text text-transparent">
TPMJS
</span>
</motion.div>
{/* Decorative line */} <motion.h1
<motion.div initial={{ opacity: 0 }}
initial={{ scaleX: 0 }} animate={{ opacity: 1 }}
animate={{ scaleX: 1 }} transition={{ duration: 0.6, delay: 0.4 }}
transition={{ duration: 1, delay: 0.8 }} className="text-2xl md:text-3xl font-medium text-white/90 mb-6"
className="mt-12 w-32 h-px bg-gradient-to-r from-transparent via-white/30 to-transparent" >
/> A Tool Registry for the AI SDK
</motion.h1>
{/* CTA hint */} <motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.6, delay: 0.6 }}
className="text-lg text-white/50 font-mono"
>
Dynamic tool discovery and execution for agents
</motion.p>
</motion.div>
{/* Press to continue */}
<motion.div <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ duration: 0.8, delay: 1.2 }} transition={{ duration: 0.8, delay: 1.2 }}
className="mt-8 flex flex-col items-center" className="absolute bottom-12 flex flex-col items-center"
> >
<motion.div <motion.div
animate={{ y: [0, 8, 0] }} animate={{ y: [0, 8, 0] }}
@ -95,7 +72,7 @@ export function WelcomeSlide(): React.ReactElement {
/> />
</svg> </svg>
</motion.div> </motion.div>
<span className="mt-2 text-sm text-white/30 font-mono">Press any key to begin</span> <span className="mt-2 text-sm text-white/30 font-mono">Press any key</span>
</motion.div> </motion.div>
</div> </div>
); );