Major changes:
- Fixed package executor URL protocol handling (add https:// if missing)
- Switched from streamText to generateText for proper tool execution
- AI now calls tool AND generates natural language response
- Tool results no longer show raw JSON metadata
Tool executor (tool-executor-agent.ts):
- Use generateText() instead of streamText() for tool execution
- Add system prompt to guide AI to summarize tool results
- Return result.text for natural language output
- Tool definition uses inputSchema (AI SDK v6 format)
Package executor:
- Add getSandboxUrl() to ensure URL has https:// protocol
- Fixes "Failed to parse URL" error in production
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- In AI SDK v6, tool results are in fullResponse.messages with role 'tool'
- Updated result extraction to iterate through messages array
- Added detailed logging to debug response structure
- Handle both text output and tool-only responses
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
- Tool playground was only showing partial output
- When 'complete' event arrived, it replaced streamed text with final output
- Output was displayed as plain text instead of formatted markdown
**Changes:**
- Fixed streaming bug in ToolPlayground component
- Removed line that overwrote accumulated text on 'complete' event
- Now preserves all streamed chunks for full output display
- Added react-markdown with GitHub Flavored Markdown support
- Install react-markdown and remark-gfm packages
- Added @tailwindcss/typography plugin for prose styling
- Replaced plain <pre> with <ReactMarkdown> component
- Applied prose classes for proper markdown formatting
- Added type="button" to button elements for accessibility
**Files changed:**
- apps/web/src/components/ToolPlayground.tsx
- Comment out setOutput(data.output) on complete event
- Import ReactMarkdown and remarkGfm
- Replace pre element with ReactMarkdown component
- Add prose styling classes
- Add type="button" to buttons
- apps/web/tailwind.config.ts
- Add @tailwindcss/typography plugin
**Result:**
- Full streamed output now displays correctly
- Markdown is rendered with proper formatting (headings, lists, code blocks, etc.)
- Better UX for AI-generated tool responses
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
OpenAI was rejecting tool definitions with error "schema must be a JSON Schema of 'type: "object"'". This was caused by AI SDK v5 not properly converting Zod schemas to JSON Schema format.
**Changes:**
- Upgrade AI SDK from v5.0.104 to v6.0.0-beta.124
- Upgrade @ai-sdk/openai from v2.0.74 to v3.0.0-beta.22
- Upgrade Zod from v3.25.76 to v4.1.13 across all packages
**AI SDK v6 breaking changes:**
- Tool definition API: `parameters` renamed to `inputSchema`
- Removed `aiTool()` wrapper - use plain object with description, inputSchema, execute
- Streaming API: Use `textStream` async iterator instead of onChunk callback
- Zod schemas now properly converted to JSON Schema for OpenAI
**Zod v4 breaking changes:**
- `z.record()` now requires two arguments: `z.record(keySchema, valueSchema)`
- `z.enum()` params changed: `errorMap` removed, use `message` instead
- Type system improvements require explicit type parameters
- Fixed type errors in @tpmjs/env, @tpmjs/npm-client, @tpmjs/types
**Files changed:**
- apps/web/src/lib/ai-agent/tool-executor-agent.ts
- Updated tool definition to use `inputSchema` instead of `parameters`
- Removed `aiTool()` wrapper
- Fixed streaming to use `textStream` iterator
- packages/env/src/index.ts
- Updated type constraint from `z.ZodRawShape` to `Record<string, z.ZodTypeAny>`
- packages/npm-client/src/package.ts
- Fixed `z.record()` calls to include both key and value schemas
- Added type assertions for record indexing
- packages/types/src/tpmjs.ts
- Changed `errorMap` to `message` in z.enum() calls
**Testing:**
- ✅ Type-check passes
- ✅ Production build succeeds
- ✅ All routes compile correctly
This fixes the tool execution error where OpenAI rejected tool schemas with invalid format.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add server component to fetch live stats from database
- Tool count from Tool table
- Invocations from successful Simulation records
- Average latency from recent executions
- Category distribution stats
- Add featured tools section
- Display top 6 tools by quality score
- Show tool cards with name, description, category, tags
- Include quality score and download metrics
- Official badge for verified tools
- Click-through to tool detail pages
- Update HeroSection component
- Accept stats prop with real database metrics
- Format large numbers (e.g., "1.2K", "5.3M")
- Add functional search navigation
- Enter key and button click navigate to tool-search
- Empty search browses all tools
- Optimize database queries
- Use Promise.all() for parallel execution
- Calculate avg latency from last 100 simulations
- Graceful error handling with fallback values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add console.log statements to track:
- Tool parameters array and length
- Generated Zod schema details
- Tool definition structure
- Sanitized tool name
- Complete tools config sent to OpenAI
This will help diagnose why OpenAI is still receiving 'type: "None"'
for empty parameter schemas despite the fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
Vercel deployments were failing with:
```
ERR_PNPM_NO_MATCHING_VERSION_INSIDE_WORKSPACE: No matching version found for @tpmjs/eslint-config@* inside the workspace
```
The `installCommand` was running `pnpm install` from `apps/web`, which couldn't access workspace packages defined at the monorepo root.
**Solution:**
Change `installCommand` from `pnpm install` to `cd ../.. && pnpm install` to run from the monorepo root, matching the `buildCommand` behavior.
**Impact:**
- Vercel can now find and install all workspace packages
- Deployments should succeed
- All previous tool execution fixes can now actually deploy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
Vercel deployments were failing during `pnpm install` because the `prepare` script tried to run `lefthook install`, which requires a git repository. Vercel's build environment doesn't have a proper `.git` directory, causing:
```
fatal: not a git repository (or any parent up to mount point /vercel)
Error: exit status 128
```
**Solution:**
Skip Lefthook installation when running in CI or Vercel environments by checking `process.env.CI` and `process.env.VERCEL` before attempting to install git hooks.
**Impact:**
- Vercel deployments will now succeed
- Local development still gets git hooks installed
- GitHub Actions CI will skip hook installation (not needed in CI)
- All previous tool execution fixes can now actually deploy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: OpenAI API error 'got type: None' when tool has no/invalid parameters
Solution: Add guard to explicitly create empty object schema with description when no parameters exist
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: OpenAI tool names must match ^[a-zA-Z0-9_-]+ but npm package names like @tpmjs/createblogpost contain @ and /
Solution: Add sanitizeToolName() function and update pnpm-lock.yaml
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
The Interactive Playground was failing with "Missing tiktoken_bg.wasm" error in production. Tiktoken requires WASM files which don't work in Vercel's serverless environment.
**Solution:**
- Remove tiktoken import from tool-executor-agent
- Replace tiktoken-based token counting with character estimation (~4 chars/token)
- Remove tiktoken from package.json dependencies
- Remove unused biome-ignore comment
**Impact:**
- Token counting is now approximate but consistent
- No more WASM-related runtime errors
- Serverless deployment works properly
- Tool execution now functional in production
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
The Interactive Playground was failing with "Missing tiktoken_bg.wasm" error in production. Tiktoken requires WASM files which don't work in Vercel's serverless environment.
**Solution:**
- Remove tiktoken import from tool-executor-agent
- Replace tiktoken-based token counting with character estimation (~4 chars/token)
- Remove tiktoken from package.json dependencies
- Remove experimental webpack WASM config (no longer needed)
**Impact:**
- Token counting is now approximate but consistent
- No more WASM-related runtime errors
- Serverless deployment works properly
- Tool execution now functional in production
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add `^@/` to pathNot to allow Next.js `@/` path alias
- Add `^@tpmjs/` to pathNot to allow workspace package imports
- Fixes architecture check failures in CI
- Apply Biome formatting to check-tool.mjs and sync-single-tool.mjs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Convert static import of executeToolWithAgent to dynamic import inside the
POST handler. This prevents the AI SDK (and its tiktoken dependency) from
being loaded at build time, which was causing WASM loading errors.
**Why this fix works:**
- Next.js 16 + Turbopack tries to analyze routes at build time
- tiktoken requires tiktoken_bg.wasm which can't load during static analysis
- Dynamic imports defer loading until runtime, avoiding build-time WASM issues
**Changes:**
- Remove: `import { executeToolWithAgent } from '@/lib/ai-agent/tool-executor-agent'`
- Add: `const { executeToolWithAgent } = await import('@/lib/ai-agent/tool-executor-agent')`
inside the stream start() handler
Build now completes successfully. Route is properly marked as dynamic (ƒ).
Resolves: "Error: Missing tiktoken_bg.wasm" during Next.js build
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add `export const dynamic = 'force-dynamic'` to `/api/tools/execute/[...slug]`
to prevent Next.js from attempting static generation at build time.
The AI SDK (used via executeToolWithAgent) requires tiktoken_bg.wasm which
cannot be loaded during static generation. Marking as dynamic ensures the
route is only executed at runtime.
Note: This partially addresses the build error but further investigation needed
for complete resolution of tiktoken WASM loading in Next.js 16 + Turbopack.
Relates to: "Error: Missing tiktoken_bg.wasm"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Replace VM2 with Railway Microservice:**
- Remove VM2 dependency (incompatible with Next.js Turbopack bundling)
- Create Express sandbox service at `/services/sandbox-executor/`
- Uses isolated-vm for V8-level isolation with 128MB memory limit
- 10-second execution timeout with proper error handling
**Package Executor Client:**
- Rewrite `@tpmjs/package-executor` to call remote sandbox via HTTP
- Add `executePackage()`, `clearCache()`, `checkHealth()` functions
- Use AbortController for timeout handling
- Proper TypeScript type assertions for API responses
- Reads `SANDBOX_EXECUTOR_URL` from environment (defaults to localhost:3000)
**Sandbox Service Features:**
- `/execute` - Execute npm packages in isolated environment
- `/health` - Health check endpoint with service info
- `/cache/clear` - Clear npm package cache
- Package caching in `/tmp/.tpmjs-cache` for faster subsequent runs
- CORS support for web app integration
- Automatic ESM/CommonJS package detection
**Deployment Configuration:**
- Dockerfile with isolated-vm native dependencies (python3, make, g++)
- Railway.json with health checks and restart policies
- Environment variables: PORT, PACKAGE_CACHE_DIR, ALLOWED_ORIGINS
- Production URL: https://tpmjs-production.up.railway.app
**Integration:**
- Add SANDBOX_EXECUTOR_URL to .env.local
- Update Next.js config to mark package-executor as external
- Maintain existing API routes at `/api/tools/execute/[...slug]`
This architectural change enables secure package execution on Vercel
by moving sandboxing to a dedicated microservice on Railway.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**New Sandbox Service:**
- Separate microservice for secure npm package execution
- Uses isolated-vm for V8-level isolation
- 128MB memory limit, 10s timeout
- Package caching for performance
- Express API with /execute, /health, /cache/clear endpoints
**Why Microservice:**
- VM2 doesn't work with Next.js Turbopack (requires runtime file access)
- isolated-vm doesn't work in Vercel serverless (native bindings)
- Microservice allows full Node environment with proper sandboxing
- Industry standard approach (Replit, CodeSandbox, RunKit)
**Deployment:**
- Dockerfile with isolated-vm build dependencies
- Railway.json configuration
- Health checks and auto-restart policies
- CORS configuration for Next.js integration
**Next Steps:**
1. Deploy to Railway:
cd services/sandbox-executor
railway init
railway up
2. Set SANDBOX_EXECUTOR_URL in Next.js env
3. Update API routes to call sandbox service
This provides secure, production-ready package execution outside Vercel's constraints.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**VM2 Removal:**
- Remove VM2 dependency from package-executor
- Rewrite executor to use direct package execution with require()
- Add TODO comment for future sandboxing implementation
**Why this change:**
- VM2 requires runtime filesystem access to bridge.js which doesn't work with Next.js Turbopack bundling
- Even marking as serverExternalPackages fails because VM2 uses hardcoded file paths
- Direct execution allows builds to complete while we find Next.js-compatible sandboxing solution
**Next Steps:**
- Implement proper sandboxing with isolated-vm or similar Next.js-compatible solution
- Add security measures for package execution
- Consider moving package execution to separate microservice
This unblocks CI/CD while maintaining playground functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**API Route Restructuring:**
- Move execute endpoint from /api/tools/[...slug]/execute to /api/tools/execute/[...slug]
- Move simulations endpoint from /api/tools/[...slug]/simulations to /api/tools/simulations/[...slug]
- Fix Next.js App Router constraint: catch-all segments must be terminal
- Update ToolPlayground component to use new endpoint paths
**Package Executor Export Fix:**
- Remove .js extensions from exports in @tpmjs/package-executor
- Change from './types.js' to './types' for proper TypeScript resolution
- Change from './executor.js' to './executor' for proper TypeScript resolution
- Fixes "Export executePackage doesn't exist in target module" build error
**Next.js Configuration:**
- Add vm2 and @tpmjs/package-executor to serverExternalPackages
- Prevents bundling VM2 which requires filesystem access to internal files
**Code Quality:**
- Add biome-ignore for excessive complexity in SSE stream handling
- Add biome-ignore for decorative loading spinner SVGs (2 instances)
Note: VM2 sandboxing still has compatibility issues with Next.js Turbopack.
This may need to be replaced with a different sandboxing approach or disabled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Syntax Highlighting:**
- Add react-syntax-highlighter with Solarized Light theme
- Proper language detection from markdown code blocks
- Beautiful syntax highlighting for all code examples
- Improved inline code styling with subtle borders
**Enhanced Readability:**
- Larger base typography with prose-lg
- Better contrast for text colors (zinc-700/zinc-300)
- Improved heading spacing and hierarchy
- Enhanced table styling with hover effects and better spacing
- Table headers with uppercase, bold styling
- Table cells with generous padding (px-6 py-4/py-3)
- Row hover effects for better interaction
- Better blockquote styling with blue accents
- Improved list spacing with leading-relaxed
- Enhanced image borders and shadows
**Table Improvements:**
- Professional header styling with background colors
- Better cell padding and spacing
- Hover effects on rows
- Improved borders and shadows
- Responsive overflow handling
All code blocks now have beautiful Solarized Light syntax highlighting, and the overall typography is more readable and professional.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Enhanced Markdown Rendering:**
- Use prose-slate for better default typography
- Add proper heading hierarchy with bottom borders on h1/h2
- Improve code block styling with better backgrounds and shadows
- Style inline code with pink/red accent colors like npm
- Better table styling with proper borders and rounded corners
- Improve link colors (blue) with hover effects
- Add better spacing throughout (margins, padding, line-height)
- Enhance blockquote styling with background colors
- Better list spacing with space-y-2
- Add proper light/dark mode support with zinc color palette
**Component Updates:**
- Custom pre component with better background and border
- Custom table wrapper with overflow handling
- Improved link component with external link detection
- Better inline code styling
The README now renders beautifully like npm.com instead of looking plain.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename API route from [slug] to [...slug] for catch-all routing
- Update API handler to join slug segments for scoped packages
- Remove encodeURIComponent from frontend API call
This fixes the 404 error when accessing tool pages with scoped package names.
The sync workers will need to run to populate README data for existing tools.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename [slug] to [...slug] for catch-all routing
- Update tool detail page to join slug segments (e.g., ['@tpmjs', 'text-transformer'] -> '@tpmjs/text-transformer')
- Remove encodeURIComponent from tool search links
- URLs now display as /tool/@tpmjs/text-transformer instead of /tool/%40tpmjs%2Ftext-transformer
This makes URLs cleaner and more readable while maintaining full compatibility with scoped npm package names.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Database Schema:**
- Add npmReadme, npmKeywords, npmAuthor, npmMaintainers fields to Tool model
**NPM Client:**
- Add fetchLatestPackageWithMetadata() function to fetch README and top-level metadata
- Export new PackageVersionWithReadme type
**Sync Workers:**
- Update keyword and changes sync to fetch and store README content
- Store author, maintainers, and keywords from package.json
**UI Components:**
- Create Markdown component using react-markdown with GitHub Flavored Markdown
- Add rehype-sanitize for security and remark-gfm for tables/strikethrough support
**Tool Detail Page:**
- Convert from createElement to JSX for better maintainability
- Display README in a dedicated card with proper markdown rendering
- Show NPM keywords, author, and maintainers in sidebar
- Add ThemeToggle to header
- Improve layout with better spacing and organization
This brings the tool detail pages much closer to NPM's package pages,
providing users with comprehensive information about each tool including
the full README documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create new /publish page with step-by-step instructions
- Show all 3 metadata tiers (Minimal, Basic, Rich) with examples
- Include quality score explanation and real-world examples
- Add category reference and tips for success
- Update homepage with Publish navigation link
- Add Publish Your Tool promotional section to homepage
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Next.js error: "You cannot use different slug names for the same dynamic path ('id' !== 'slug')"
Removed /api/tools/[id]/route.ts to resolve conflict with /api/tools/[slug]/route.ts
The [slug] route already handles fetching tools by package name
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Prevents lefthook from failing in CI/Vercel environments
- Only installs git hooks when in actual git repository
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Comprehensive debugging journey from timeout to working endpoints
- Details on Turborepo monorepo build order for Vercel
- Prisma cold start optimization strategies
- Progressive debugging approach with code examples
- Performance metrics before/after optimization
- All examples reference tpmjs.com as production domain
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change build filter from @tpmjs/web to @tpmjs/web...
- The ... suffix tells pnpm to build all dependencies first
- This fixes 'Module not found' errors for @tpmjs/env, @tpmjs/types, @tpmjs/ui
- Ensures workspace packages are built before web app tries to import them
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove --webpack flag (incompatible with Turbo)
- Remove functions config (not working as expected)
- Use direct pnpm build command
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add --webpack flag to build command to use Webpack instead of Turbopack
- Add maxDuration export to health route
- This should ensure API routes are properly detected and deployed as serverless functions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add explicit functions configuration to vercel.json
- Set maxDuration to 60 seconds for all API routes
- This ensures Vercel properly detects and deploys API routes as serverless functions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The redirect was being applied to ALL routes including API routes,
causing them to return "Redirecting..." instead of executing.
Use negative lookahead regex `/((?!api).*)` to exclude /api/* paths
from the www → non-www redirect.
This ensures:
- API routes execute normally without redirection
- Page routes still redirect from www.tpmjs.com to tpmjs.com
- Follows Option 2 from the investigation plan
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Root cause: The redirect rule in /vercel.json was intercepting ALL requests
(including /api/*) before they reached the Next.js app, causing API routes
to timeout without generating any logs.
Changes:
- Move www → non-www redirect to apps/web/next.config.ts async redirects()
- Remove redirects array from root vercel.json
- Keep cron job configuration in root vercel.json
Why this fixes the issue:
- Next.js handles redirects AFTER route resolution (pages vs API routes)
- API routes execute before redirect logic is applied
- Redirects still work for pages as expected
- More idiomatic for Next.js applications
Testing:
- API routes should now respond: /api/health, /api/tools
- www.tpmjs.com should still redirect to tpmjs.com
- All existing functionality preserved
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add vercel.json to apps/web with Turborepo build command
- Configure build to use turbo build --filter=@tpmjs/web
- Ensures Vercel properly detects and builds Next.js app in monorepo structure
- Fixes API routes timing out due to incorrect project root detection
This resolves the issue where Vercel wasn't detecting the Next.js app
inside apps/web/, causing API routes to never be built as serverless functions.
Note: You must also set Root Directory to "apps/web" in Vercel dashboard:
Project Settings > General > Root Directory
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add @tpmjs/db, @tpmjs/types, @tpmjs/env to transpilePackages
- Fixes API routes timing out on Vercel due to untranspiled TypeScript imports
- Ensures all workspace dependencies are properly bundled for serverless functions
Without transpilation, Vercel couldn't properly bundle the @tpmjs/db package,
causing API route handlers to hang when trying to import Prisma client.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add redirect rule in vercel.json to redirect www.tpmjs.com → tpmjs.com
- Use permanent (301) redirect for SEO benefits
- Preserves all paths and query parameters with /:path* pattern
- Ensures canonical URL is always non-www
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace DitherHeadline (canvas-based) with simple h1 heading
- Replace AnimatedCounter components with static text
- Remove parallax scroll effect
- Remove glitch bar animations
- Removes CPU-intensive canvas dithering that was blocking page interaction
Fixes issue where homepage froze and prevented link clicks until tab closed.
Users can now interact with the page immediately on load.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add "Discover AI Tools" section with CTA buttons to tool search
- Add three feature cards highlighting search, metrics, and AI integration
- Add "Tools" link to header navigation for easy access
- Simplify header nav by removing unused Pro/Teams/Pricing buttons
Features:
- Browse/Search tools CTAs prominently displayed
- Feature cards explain key benefits (Smart Search, Quality Metrics, AI Ready)
- Direct navigation to tool search from homepage
- Responsive grid layout for feature cards
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add category dropdown filter with dynamic options from fetched tools
- Add clickable tag badges for filtering by tags (up to 10 most common)
- Implement client-side tag filtering with multi-select support
- Add "Clear Filters" button when filters are active
- Extract unique categories and tags from API responses
- Update UI with visual feedback for selected tags (default vs outline)
Features:
- Category filter integrates with API /api/tools?category param
- Tag filtering happens client-side for instant feedback
- Tags highlight when selected for better UX
- Filters persist across tab changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>