From 5feac0d2db998f266c243124f9c9d83474445257 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Sat, 29 Nov 2025 22:57:54 +1000 Subject: [PATCH] fix: update API route to use catch-all pattern for clean URLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .../api/tools/{[slug] => [...slug]}/route.ts | 10 +++++-- apps/web/src/app/tool/[...slug]/page.tsx | 2 +- packages/db/check-tool.js | 30 +++++++++++++++++++ packages/db/check-tool.mjs | 30 +++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) rename apps/web/src/app/api/tools/{[slug] => [...slug]}/route.ts (73%) create mode 100644 packages/db/check-tool.js create mode 100644 packages/db/check-tool.mjs diff --git a/apps/web/src/app/api/tools/[slug]/route.ts b/apps/web/src/app/api/tools/[...slug]/route.ts similarity index 73% rename from apps/web/src/app/api/tools/[slug]/route.ts rename to apps/web/src/app/api/tools/[...slug]/route.ts index 759cdea..964e639 100644 --- a/apps/web/src/app/api/tools/[slug]/route.ts +++ b/apps/web/src/app/api/tools/[...slug]/route.ts @@ -6,21 +6,25 @@ export const dynamic = 'force-dynamic'; export const maxDuration = 60; /** - * GET /api/tools/[slug] + * GET /api/tools/[...slug] * * Fetch a single tool by its NPM package name (slug) + * Supports catch-all routing for scoped packages like @tpmjs/text-transformer */ export async function GET( _request: NextRequest, - { params }: { params: Promise<{ slug: string }> } + { params }: { params: Promise<{ slug: string[] }> } ): Promise { try { const { slug } = await params; + // Join slug array to reconstruct package name (e.g., ['@tpmjs', 'text-transformer'] -> '@tpmjs/text-transformer') + const packageName = slug.join('/'); + // Find the tool by npmPackageName const tool = await prisma.tool.findUnique({ where: { - npmPackageName: decodeURIComponent(slug), + npmPackageName: packageName, }, }); diff --git a/apps/web/src/app/tool/[...slug]/page.tsx b/apps/web/src/app/tool/[...slug]/page.tsx index 4bf5528..df763fb 100644 --- a/apps/web/src/app/tool/[...slug]/page.tsx +++ b/apps/web/src/app/tool/[...slug]/page.tsx @@ -89,7 +89,7 @@ export default function ToolDetailPage({ const fetchTool = async () => { try { setLoading(true); - const response = await fetch(`/api/tools/${encodeURIComponent(slug)}`); + const response = await fetch(`/api/tools/${slug}`); const data = await response.json(); if (data.success) { diff --git a/packages/db/check-tool.js b/packages/db/check-tool.js new file mode 100644 index 0000000..a358ce4 --- /dev/null +++ b/packages/db/check-tool.js @@ -0,0 +1,30 @@ +const { PrismaClient } = require('@prisma/client'); +const prisma = new PrismaClient(); + +async function main() { + const tool = await prisma.tool.findUnique({ + where: { npmPackageName: '@tpmjs/text-transformer' }, + select: { + npmPackageName: true, + npmVersion: true, + npmReadme: true, + }, + }); + + if (tool) { + console.log('Tool found:', tool.npmPackageName, tool.npmVersion); + console.log('Has README:', tool.npmReadme ? `Yes (${tool.npmReadme.length} chars)` : 'No'); + } else { + console.log('Tool @tpmjs/text-transformer not found in database'); + + // List all tools to see what's available + const allTools = await prisma.tool.findMany({ + select: { npmPackageName: true }, + take: 10, + }); + console.log('\nAvailable tools:'); + allTools.forEach((t) => console.log(' -', t.npmPackageName)); + } +} + +main().finally(() => prisma.$disconnect()); diff --git a/packages/db/check-tool.mjs b/packages/db/check-tool.mjs new file mode 100644 index 0000000..4fd8e43 --- /dev/null +++ b/packages/db/check-tool.mjs @@ -0,0 +1,30 @@ +import { PrismaClient } from '@prisma/client'; +const prisma = new PrismaClient(); + +async function main() { + const tool = await prisma.tool.findUnique({ + where: { npmPackageName: '@tpmjs/text-transformer' }, + select: { + npmPackageName: true, + npmVersion: true, + npmReadme: true, + } + }); + + if (tool) { + console.log('Tool found:', tool.npmPackageName, tool.npmVersion); + console.log('Has README:', tool.npmReadme ? `Yes (${tool.npmReadme.length} chars)` : 'No'); + } else { + console.log('Tool @tpmjs/text-transformer not found in database'); + + // List all tools to see what's available + const allTools = await prisma.tool.findMany({ + select: { npmPackageName: true }, + take: 10 + }); + console.log('\nAvailable tools:'); + allTools.forEach(t => console.log(' -', t.npmPackageName)); + } +} + +main().finally(() => prisma.$disconnect());