fix(ci): skip lefthook install when .git directory missing
- 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>
This commit is contained in:
parent
23dd6b1a33
commit
0d7a8e4696
6 changed files with 1336 additions and 6 deletions
932
API_ROUTES_TIMEOUT_INVESTIGATION.md
Normal file
932
API_ROUTES_TIMEOUT_INVESTIGATION.md
Normal file
|
|
@ -0,0 +1,932 @@
|
|||
# API Routes Timeout Issue - Complete Investigation Report
|
||||
|
||||
## Problem Statement
|
||||
|
||||
API routes deployed to Vercel are timing out with no response. The Next.js application pages work perfectly, but all API endpoints at `/api/*` return timeouts or "Redirecting..." messages.
|
||||
|
||||
**Affected URLs:**
|
||||
- `https://tpmjs.com/api/health` - Returns "Redirecting..."
|
||||
- `https://tpmjs.com/api/tools` - Returns "Redirecting..."
|
||||
- `https://tpmjs-1chh44d1u-tpmjs.vercel.app/api/health` - Timeouts (exit code 28)
|
||||
- `https://tpmjs-1chh44d1u-tpmjs.vercel.app/api/tools` - Timeouts (exit code 28)
|
||||
|
||||
**Working:**
|
||||
- All page routes work correctly (e.g., `/`, `/tool/[slug]`)
|
||||
- UI navigation and client-side routing function normally
|
||||
- Local development API routes work perfectly
|
||||
|
||||
## Environment Details
|
||||
|
||||
### Project Structure
|
||||
- **Monorepo:** Turborepo setup with pnpm workspaces
|
||||
- **Framework:** Next.js 16.0.4 (App Router)
|
||||
- **Node Version:** 24.x (on Vercel)
|
||||
- **Deployment Platform:** Vercel
|
||||
- **Custom Domains:** tpmjs.com, www.tpmjs.com
|
||||
|
||||
### Repository Structure
|
||||
```
|
||||
tpmjs/
|
||||
├── apps/
|
||||
│ └── web/ # Next.js 16 App Router application
|
||||
│ ├── src/
|
||||
│ │ └── app/
|
||||
│ │ ├── api/
|
||||
│ │ │ ├── health/route.ts
|
||||
│ │ │ ├── stats/route.ts
|
||||
│ │ │ ├── tools/
|
||||
│ │ │ │ ├── route.ts
|
||||
│ │ │ │ ├── [id]/route.ts
|
||||
│ │ │ │ ├── [slug]/route.ts
|
||||
│ │ │ │ └── validate/route.ts
|
||||
│ │ │ └── sync/
|
||||
│ │ │ ├── changes/route.ts
|
||||
│ │ │ ├── keyword/route.ts
|
||||
│ │ │ └── metrics/route.ts
|
||||
│ │ ├── page.tsx
|
||||
│ │ └── tool/[slug]/page.tsx
|
||||
│ ├── next.config.ts
|
||||
│ └── vercel.json
|
||||
├── packages/
|
||||
│ ├── db/ # Prisma client
|
||||
│ ├── types/ # Shared TypeScript types
|
||||
│ ├── utils/ # Utility functions
|
||||
│ ├── env/ # Environment validation
|
||||
│ └── ui/ # React component library
|
||||
├── vercel.json # Root Vercel configuration
|
||||
└── turbo.json
|
||||
```
|
||||
|
||||
## API Route Examples
|
||||
|
||||
### `/apps/web/src/app/api/health/route.ts`
|
||||
```typescript
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
export const dynamic = 'force-dynamic';
|
||||
export const maxDuration = 60;
|
||||
|
||||
/**
|
||||
* GET /api/health
|
||||
* Simple health check endpoint that doesn't touch the database
|
||||
*/
|
||||
export async function GET() {
|
||||
return NextResponse.json({
|
||||
status: 'ok',
|
||||
timestamp: new Date().toISOString(),
|
||||
env: {
|
||||
hasDatabase: !!process.env.DATABASE_URL,
|
||||
nodeEnv: process.env.NODE_ENV,
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### `/apps/web/src/app/api/tools/route.ts`
|
||||
```typescript
|
||||
import { NextResponse } from 'next/server';
|
||||
import { prisma } from '@tpmjs/db/client';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
// ... query string parsing
|
||||
|
||||
const [tools, totalCount] = await Promise.all([
|
||||
prisma.tool.findMany({
|
||||
where,
|
||||
orderBy: [
|
||||
{ qualityScore: 'desc' },
|
||||
{ npmDownloadsLastMonth: 'desc' },
|
||||
{ createdAt: 'desc' },
|
||||
],
|
||||
take: limit,
|
||||
skip: offset,
|
||||
}),
|
||||
prisma.tool.count({ where }),
|
||||
]);
|
||||
|
||||
return NextResponse.json({
|
||||
data: tools,
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
total: totalCount,
|
||||
totalPages: Math.ceil(totalCount / limit),
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### `/apps/web/next.config.ts` (Current)
|
||||
```typescript
|
||||
import type { NextConfig } from 'next';
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
transpilePackages: ['@tpmjs/ui', '@tpmjs/utils', '@tpmjs/db', '@tpmjs/types', '@tpmjs/env'],
|
||||
reactStrictMode: true,
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
```
|
||||
|
||||
### `/apps/web/vercel.json` (Current)
|
||||
```json
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"buildCommand": "cd ../.. && pnpm --filter=@tpmjs/web build",
|
||||
"installCommand": "pnpm install"
|
||||
}
|
||||
```
|
||||
|
||||
### `/vercel.json` (Root)
|
||||
```json
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"git": {
|
||||
"deploymentEnabled": {
|
||||
"main": true
|
||||
}
|
||||
},
|
||||
"github": {
|
||||
"silent": false,
|
||||
"autoJobCancelation": true
|
||||
},
|
||||
"crons": [
|
||||
{
|
||||
"path": "/api/sync/changes",
|
||||
"schedule": "*/2 * * * *"
|
||||
},
|
||||
{
|
||||
"path": "/api/sync/keyword",
|
||||
"schedule": "*/15 * * * *"
|
||||
},
|
||||
{
|
||||
"path": "/api/sync/metrics",
|
||||
"schedule": "0 * * * *"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Local Build Verification
|
||||
|
||||
### Local Build Output Structure
|
||||
```bash
|
||||
$ ls -R /Users/ajaxdavis/repos/tpmjs/tpmjs/apps/web/.next/server/app/api/
|
||||
|
||||
health/
|
||||
stats/
|
||||
sync/
|
||||
tools/
|
||||
|
||||
/apps/web/.next/server/app/api/health:
|
||||
route
|
||||
route.js
|
||||
route.js.map
|
||||
route.js.nft.json
|
||||
route_client-reference-manifest.js
|
||||
|
||||
/apps/web/.next/server/app/api/stats:
|
||||
route
|
||||
route.js
|
||||
route.js.map
|
||||
route.js.nft.json
|
||||
route_client-reference-manifest.js
|
||||
|
||||
/apps/web/.next/server/app/api/tools:
|
||||
[id]/
|
||||
[slug]/
|
||||
validate/
|
||||
route
|
||||
route.js
|
||||
route.js.map
|
||||
route.js.nft.json
|
||||
route_client-reference-manifest.js
|
||||
```
|
||||
|
||||
### Routes Manifest Confirmation
|
||||
```bash
|
||||
$ cat /apps/web/.next/routes-manifest.json | jq '.staticRoutes[] | select(.page | contains("api"))'
|
||||
|
||||
{
|
||||
"page": "/api/health",
|
||||
"regex": "^/api/health(?:/)?$",
|
||||
"routeKeys": {},
|
||||
"namedRegex": "^/api/health(?:/)?$"
|
||||
}
|
||||
{
|
||||
"page": "/api/stats",
|
||||
"regex": "^/api/stats(?:/)?$",
|
||||
"routeKeys": {},
|
||||
"namedRegex": "^/api/stats(?:/)?$"
|
||||
}
|
||||
{
|
||||
"page": "/api/sync/changes",
|
||||
"regex": "^/api/sync/changes(?:/)?$",
|
||||
"routeKeys": {},
|
||||
"namedRegex": "^/api/sync/changes(?:/)?$"
|
||||
}
|
||||
{
|
||||
"page": "/api/sync/keyword",
|
||||
"regex": "^/api/sync/keyword(?:/)?$",
|
||||
"routeKeys": {},
|
||||
"namedRegex": "^/api/sync/keyword(?:/)?$"
|
||||
}
|
||||
{
|
||||
"page": "/api/sync/metrics",
|
||||
"regex": "^/api/sync/metrics(?:/)?$",
|
||||
"routeKeys": {},
|
||||
"namedRegex": "^/api/sync/metrics(?:/)?$"
|
||||
}
|
||||
```
|
||||
|
||||
### Node File Trace (NFT) Verification
|
||||
```bash
|
||||
$ cat /apps/web/.next/server/app/api/health/route.js.nft.json
|
||||
|
||||
{
|
||||
"version": 1,
|
||||
"files": [
|
||||
"../../../../../../../node_modules/.pnpm/next@16.0.4_@babel+core@7.28.5_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/next/dist/client/components/app-router-headers.js",
|
||||
"../../../../../../../node_modules/.pnpm/next@16.0.4_@babel+core@7.28.5_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/next/dist/compiled/@opentelemetry/api/index.js",
|
||||
// ... many more dependencies
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Conclusion:** API routes build correctly locally with all dependencies properly traced.
|
||||
|
||||
## Vercel Deployment Analysis
|
||||
|
||||
### Deployment Inspection Output
|
||||
```bash
|
||||
$ vercel inspect https://tpmjs-1chh44d1u-tpmjs.vercel.app
|
||||
|
||||
General
|
||||
id dpl_2FHyiTWtBZzvT8EcohwYEZmdb8rb
|
||||
name tpmjs-web
|
||||
target production
|
||||
status ● Ready
|
||||
url https://tpmjs-1chh44d1u-tpmjs.vercel.app
|
||||
created Fri Nov 28 2025 20:44:03 GMT+1000
|
||||
|
||||
Aliases
|
||||
╶ https://www.tpmjs.com
|
||||
╶ https://tpmjs-web.vercel.app
|
||||
╶ https://tpmjs-web-tpmjs.vercel.app
|
||||
╶ https://tpmjs-web-git-main-tpmjs.vercel.app
|
||||
╶ https://tpmjs.com
|
||||
|
||||
Builds
|
||||
┌ . [0ms]
|
||||
├── λ tool/[slug] (562.92KB) [iad1]
|
||||
├── λ tool/[slug].rsc (562.92KB) [iad1]
|
||||
├── λ _global-error (642.48KB) [iad1]
|
||||
├── λ _global-error.rsc (642.48KB) [iad1]
|
||||
├── λ _global-error.segments/__PAGE__.segment.rsc (642.48KB) [iad1]
|
||||
└── 56 output items hidden
|
||||
```
|
||||
|
||||
**CRITICAL FINDING:** No API routes are listed in the build output. Only pages (`tool/[slug]`, `_global-error`, etc.) appear as serverless functions (`λ`).
|
||||
|
||||
Expected API routes that should appear:
|
||||
- `λ api/health`
|
||||
- `λ api/tools`
|
||||
- `λ api/tools/[id]`
|
||||
- `λ api/tools/[slug]`
|
||||
- `λ api/sync/changes`
|
||||
- etc.
|
||||
|
||||
### Testing Results
|
||||
```bash
|
||||
# Direct Vercel URL - Timeouts
|
||||
$ curl -s -m 10 https://tpmjs-1chh44d1u-tpmjs.vercel.app/api/health
|
||||
# Exit code 28 (timeout)
|
||||
|
||||
# Custom Domain - Returns "Redirecting..."
|
||||
$ curl -s -m 10 https://tpmjs.com/api/health
|
||||
Redirecting...
|
||||
|
||||
# Custom Domain - Returns "Redirecting..."
|
||||
$ curl -s -m 10 https://tpmjs.com/api/tools
|
||||
Redirecting...
|
||||
|
||||
# Check redirect headers
|
||||
$ curl -I https://tpmjs.com
|
||||
HTTP/2 307
|
||||
cache-control: public, max-age=0, must-revalidate
|
||||
content-type: text/plain
|
||||
date: Fri, 28 Nov 2025 10:38:12 GMT
|
||||
location: https://www.tpmjs.com/
|
||||
server: Vercel
|
||||
```
|
||||
|
||||
## Vercel Configuration Details
|
||||
|
||||
### User-Confirmed Settings
|
||||
- **Root Directory:** `apps/web` (set in Vercel dashboard)
|
||||
- **DATABASE_URL:** Configured in Vercel environment variables (Production)
|
||||
- **Framework Preset:** (Unknown - needs verification)
|
||||
- **Build Output Directory:** (Unknown - using default `.next`)
|
||||
|
||||
### Project List
|
||||
```bash
|
||||
$ vercel project ls | grep -i tpmjs
|
||||
|
||||
tpmjs -- 16h 24.x
|
||||
v0-tool-registry-page https://tpmjs.com 3d 22.x
|
||||
```
|
||||
|
||||
**NOTE:** Two projects exist:
|
||||
1. `tpmjs` - Current project (Node 24.x)
|
||||
2. `v0-tool-registry-page` - Also has tpmjs.com domain (Node 22.x)
|
||||
|
||||
This could indicate a domain routing conflict or outdated project.
|
||||
|
||||
## Investigation Timeline & Attempts
|
||||
|
||||
### Attempt 1: Remove Root-Level Redirects
|
||||
**Hypothesis:** The redirect in `/vercel.json` was intercepting API requests.
|
||||
|
||||
**Original `/vercel.json`:**
|
||||
```json
|
||||
{
|
||||
"redirects": [
|
||||
{
|
||||
"source": "/:path*",
|
||||
"has": [
|
||||
{
|
||||
"type": "host",
|
||||
"value": "www.tpmjs.com"
|
||||
}
|
||||
],
|
||||
"destination": "https://tpmjs.com/:path*",
|
||||
"permanent": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Action:** Removed the `redirects` array from root `/vercel.json`.
|
||||
|
||||
**Result:** ❌ API routes still timeout. Redirect rule was not the root cause.
|
||||
|
||||
**Commit:** `9be3af7 fix(routing): move www redirect from vercel.json to Next.js config`
|
||||
|
||||
### Attempt 2: Move Redirects to Next.js Config
|
||||
**Hypothesis:** Next.js should handle redirects after routing.
|
||||
|
||||
**Action:** Added `async redirects()` to `apps/web/next.config.ts`:
|
||||
```typescript
|
||||
async redirects() {
|
||||
return [
|
||||
{
|
||||
source: '/:path*',
|
||||
has: [
|
||||
{
|
||||
type: 'host',
|
||||
value: 'www.tpmjs.com',
|
||||
},
|
||||
],
|
||||
destination: 'https://tpmjs.com/:path*',
|
||||
permanent: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
**Result:** ❌ API routes returned "Redirecting..." instead of executing. Next.js `async redirects()` applies to ALL routes including API routes.
|
||||
|
||||
**Commit:** `9be3af7 fix(routing): move www redirect from vercel.json to Next.js config`
|
||||
|
||||
### Attempt 3: Exclude API Routes from Redirect
|
||||
**Hypothesis:** Use regex to exclude `/api/*` from redirects.
|
||||
|
||||
**Action:** Modified redirect pattern:
|
||||
```typescript
|
||||
async redirects() {
|
||||
return [
|
||||
{
|
||||
source: '/((?!api).*)', // Negative lookahead to exclude /api/*
|
||||
has: [
|
||||
{
|
||||
type: 'host',
|
||||
value: 'www.tpmjs.com',
|
||||
},
|
||||
],
|
||||
destination: 'https://tpmjs.com/$1',
|
||||
permanent: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
**Result:** ❌ API routes back to timing out (not redirecting anymore, but still not working).
|
||||
|
||||
**Commit:** `c42bfb6 fix(redirects): exclude API routes from www redirect`
|
||||
|
||||
### Attempt 4: Remove All Redirects
|
||||
**Hypothesis:** Eliminate redirect loop causing ERR_TOO_MANY_REDIRECTS.
|
||||
|
||||
**Action:** Removed `async redirects()` entirely from `next.config.ts`.
|
||||
|
||||
**Result:** ✅ Redirect loop fixed. ❌ API routes still timeout.
|
||||
|
||||
**Commit:** `b93cd42 fix: remove redirects to resolve redirect loop`
|
||||
|
||||
### Attempt 5: Add Vercel Functions Configuration
|
||||
**Hypothesis:** Vercel needs explicit configuration to detect API routes.
|
||||
|
||||
**Action:** Added to `apps/web/vercel.json`:
|
||||
```json
|
||||
{
|
||||
"functions": {
|
||||
"app/api/**/*.ts": {
|
||||
"maxDuration": 60
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Result:** ❌ No change. API routes still timeout.
|
||||
|
||||
**Commit:** `748ca4d fix(api): configure Vercel functions for API routes with maxDuration`
|
||||
|
||||
### Attempt 6: Add maxDuration to Route Files
|
||||
**Hypothesis:** Export configuration directly in route handlers.
|
||||
|
||||
**Action:** Added to `apps/web/src/app/api/health/route.ts`:
|
||||
```typescript
|
||||
export const maxDuration = 60;
|
||||
```
|
||||
|
||||
**Result:** ❌ No change. API routes still timeout.
|
||||
|
||||
**Commit:** `8281f8f fix(build): disable Turbopack for Vercel deployment`
|
||||
|
||||
### Attempt 7: Disable Turbopack
|
||||
**Hypothesis:** Turbopack (Next.js 16 default) has compatibility issues with Vercel.
|
||||
|
||||
**Action:** Added `--webpack` flag to build command:
|
||||
```json
|
||||
{
|
||||
"buildCommand": "cd ../.. && turbo build --filter=@tpmjs/web -- --webpack"
|
||||
}
|
||||
```
|
||||
|
||||
**Result:** ❌ Build failed completely. Invalid flag syntax.
|
||||
|
||||
**Commit:** `8281f8f fix(build): disable Turbopack for Vercel deployment`
|
||||
|
||||
### Attempt 8: Simplify Build Command
|
||||
**Hypothesis:** Use direct pnpm build instead of Turbo wrapper.
|
||||
|
||||
**Action:** Changed to:
|
||||
```json
|
||||
{
|
||||
"buildCommand": "cd ../.. && pnpm --filter=@tpmjs/web build"
|
||||
}
|
||||
```
|
||||
|
||||
**Result:** ⏳ Pending deployment test.
|
||||
|
||||
**Commit:** `065196d fix(build): simplify Vercel build command`
|
||||
|
||||
## Root Cause Analysis
|
||||
|
||||
### What We Know FOR SURE
|
||||
|
||||
1. ✅ **API routes build correctly locally**
|
||||
- All 9 API routes compile to `.next/server/app/api/`
|
||||
- NFT (Node File Trace) files are generated with proper dependencies
|
||||
- Routes manifest includes all API routes
|
||||
|
||||
2. ✅ **Next.js configuration is correct**
|
||||
- `export const runtime = 'nodejs'` set correctly
|
||||
- `export const dynamic = 'force-dynamic'` set correctly
|
||||
- `transpilePackages` includes all workspace packages
|
||||
|
||||
3. ✅ **Pages deploy and work perfectly**
|
||||
- `/tool/[slug]` renders correctly
|
||||
- Homepage loads
|
||||
- Client-side navigation works
|
||||
|
||||
4. ❌ **API routes are NOT deployed as serverless functions**
|
||||
- `vercel inspect` shows NO API routes in build output
|
||||
- Only pages appear as `λ` (lambda) functions
|
||||
- This is the PRIMARY issue
|
||||
|
||||
5. ❌ **Direct Vercel URLs timeout**
|
||||
- Not just a custom domain issue
|
||||
- Affects `*.vercel.app` URLs
|
||||
- Exit code 28 (timeout) - no response at all
|
||||
|
||||
6. ❌ **Custom domain shows "Redirecting..."**
|
||||
- Even with all redirects removed from config
|
||||
- Suggests a redirect at Vercel platform level OR DNS level
|
||||
- Could be from the `v0-tool-registry-page` project conflict
|
||||
|
||||
### Possible Root Causes
|
||||
|
||||
#### Theory 1: Vercel Project Misconfiguration
|
||||
**Likelihood:** HIGH
|
||||
|
||||
**Evidence:**
|
||||
- Two projects with same domain (`tpmjs` and `v0-tool-registry-page`)
|
||||
- Framework Preset might not be set to "Next.js"
|
||||
- Root Directory is `apps/web` but Vercel might not be detecting Next.js properly
|
||||
|
||||
**What to Check:**
|
||||
1. Vercel Dashboard → Project Settings → General
|
||||
- Framework Preset: Should be "Next.js"
|
||||
- Root Directory: Should be "apps/web"
|
||||
- Build Command: Should match vercel.json
|
||||
- Output Directory: Should be blank (default `.next`)
|
||||
|
||||
2. Vercel Dashboard → Domains
|
||||
- Check if both projects have tpmjs.com
|
||||
- Remove domain from `v0-tool-registry-page` if present
|
||||
|
||||
3. Vercel Dashboard → Deployments → Build Logs
|
||||
- Search for "API" or "route"
|
||||
- Look for errors about missing functions
|
||||
- Check if Next.js is detected correctly
|
||||
|
||||
#### Theory 2: Monorepo Detection Issue
|
||||
**Likelihood:** MEDIUM
|
||||
|
||||
**Evidence:**
|
||||
- Build command uses `cd ../.. && pnpm --filter=@tpmjs/web build`
|
||||
- Vercel might not be correctly detecting workspace structure
|
||||
- `transpilePackages` includes workspace packages
|
||||
|
||||
**What to Check:**
|
||||
1. Build logs for workspace resolution errors
|
||||
2. Check if `node_modules` is being created in correct location
|
||||
3. Verify pnpm workspace configuration
|
||||
|
||||
**Potential Fix:**
|
||||
Try setting `installCommand` to:
|
||||
```json
|
||||
{
|
||||
"installCommand": "pnpm install --shamefully-hoist"
|
||||
}
|
||||
```
|
||||
|
||||
#### Theory 3: Next.js 16 + Vercel Incompatibility
|
||||
**Likelihood:** MEDIUM
|
||||
|
||||
**Evidence:**
|
||||
- Next.js 16 released recently (November 2024)
|
||||
- Turbopack is default (might have Vercel issues)
|
||||
- App Router API routes behave differently than Pages Router
|
||||
|
||||
**What to Check:**
|
||||
1. Vercel build logs for Next.js version detection
|
||||
2. Any warnings about incompatible features
|
||||
3. Check Vercel's Next.js 16 support status
|
||||
|
||||
**Potential Fix:**
|
||||
Downgrade to Next.js 15.x temporarily to test:
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "^15.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Theory 4: Environment Variable Issue
|
||||
**Likelihood:** LOW
|
||||
|
||||
**Evidence:**
|
||||
- DATABASE_URL is configured
|
||||
- Pages work (they might not need env vars)
|
||||
- API routes use Prisma (requires DATABASE_URL)
|
||||
|
||||
**What to Check:**
|
||||
1. Vercel Dashboard → Settings → Environment Variables
|
||||
- Verify DATABASE_URL is set for Production
|
||||
- Verify it's not blocked or empty
|
||||
- Check if other vars are needed
|
||||
|
||||
2. Build logs for Prisma generation errors
|
||||
|
||||
**Potential Fix:**
|
||||
None - user confirmed DATABASE_URL is set.
|
||||
|
||||
#### Theory 5: Build Output Issue
|
||||
**Likelihood:** MEDIUM-HIGH
|
||||
|
||||
**Evidence:**
|
||||
- `vercel inspect` doesn't show API routes
|
||||
- Only pages are listed as functions
|
||||
- Build completes successfully (38-41 seconds)
|
||||
|
||||
**What to Check:**
|
||||
1. Build logs: Does Next.js report building API routes?
|
||||
- Look for "Route (app)" or "λ" indicators for API routes
|
||||
- Compare to local build output
|
||||
|
||||
2. Check if Vercel is using correct build output structure
|
||||
- App Router uses `.next/server/app/`
|
||||
- Pages Router uses `.next/server/pages/`
|
||||
|
||||
**Potential Fix:**
|
||||
Try forcing Vercel to recognize the build:
|
||||
```json
|
||||
{
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
(Note: `builds` is legacy, modern Next.js should auto-detect)
|
||||
|
||||
## Recommended Next Steps
|
||||
|
||||
### Immediate Actions (High Priority)
|
||||
|
||||
1. **Check Vercel Project Settings**
|
||||
- Go to Vercel Dashboard → tpmjs-web project
|
||||
- Verify Framework Preset is "Next.js"
|
||||
- Verify Root Directory is `apps/web`
|
||||
- Screenshot settings for reference
|
||||
|
||||
2. **Review Build Logs**
|
||||
- Go to latest deployment
|
||||
- Download complete build logs
|
||||
- Search for:
|
||||
- "Route (app)" - should show API routes
|
||||
- "λ" - should show API functions
|
||||
- "api" - any mentions
|
||||
- Errors or warnings
|
||||
|
||||
3. **Check Domain Configuration**
|
||||
- Verify only ONE project has tpmjs.com domain
|
||||
- Remove domain from `v0-tool-registry-page` project if present
|
||||
- Check DNS settings aren't redirecting
|
||||
|
||||
4. **Test Simple API Route**
|
||||
- Create minimal API route:
|
||||
```typescript
|
||||
// apps/web/src/app/api/test/route.ts
|
||||
export async function GET() {
|
||||
return new Response('Hello from API', { status: 200 });
|
||||
}
|
||||
```
|
||||
- Deploy and test
|
||||
- If this doesn't work, confirms platform issue
|
||||
|
||||
### Investigation Actions (Medium Priority)
|
||||
|
||||
5. **Compare Working vs Non-Working**
|
||||
- Find a deployment where pages DO work
|
||||
- Compare build output between page routes and API routes
|
||||
- Look for differences in how they're compiled
|
||||
|
||||
6. **Test Vercel CLI Deploy**
|
||||
- Deploy directly via CLI: `vercel --prod`
|
||||
- Check if behavior differs from Git-based deploy
|
||||
- Might reveal configuration issues
|
||||
|
||||
7. **Check Vercel Function Logs**
|
||||
- Even though functions aren't in build output, try:
|
||||
- `vercel logs <deployment-url> --since 1h`
|
||||
- Look for any API route invocations or errors
|
||||
|
||||
8. **Review Turbo Configuration**
|
||||
```bash
|
||||
# Check turbo.json for Next.js build config
|
||||
cat /turbo.json
|
||||
|
||||
# Verify build runs correctly locally
|
||||
pnpm --filter=@tpmjs/web build
|
||||
```
|
||||
|
||||
### Alternative Approaches (If Above Fails)
|
||||
|
||||
9. **Create New Vercel Project**
|
||||
- Import from Git fresh
|
||||
- Use identical settings
|
||||
- Test if fresh project works
|
||||
|
||||
10. **Contact Vercel Support**
|
||||
- This may be a platform bug with Next.js 16
|
||||
- Provide this document as context
|
||||
- Ask specifically why API routes aren't in build output
|
||||
|
||||
11. **Temporary Workaround**
|
||||
- Deploy API routes separately (different service)
|
||||
- Use Vercel proxy to route `/api/*` to separate deployment
|
||||
- Not ideal but unblocks development
|
||||
|
||||
## Environment Variables Needed
|
||||
|
||||
```bash
|
||||
# Required for API routes
|
||||
DATABASE_URL="postgresql://..."
|
||||
|
||||
# Optional (check if needed)
|
||||
NODE_ENV="production"
|
||||
NEXT_PUBLIC_* # Any public env vars
|
||||
```
|
||||
|
||||
## Build Commands Reference
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Generate Prisma client
|
||||
pnpm --filter=@tpmjs/db db:generate
|
||||
|
||||
# Run development server
|
||||
pnpm --filter=@tpmjs/web dev
|
||||
|
||||
# Build for production
|
||||
pnpm --filter=@tpmjs/web build
|
||||
|
||||
# Test build locally
|
||||
pnpm --filter=@tpmjs/web start
|
||||
```
|
||||
|
||||
### Vercel Configuration
|
||||
**Current:**
|
||||
```json
|
||||
{
|
||||
"buildCommand": "cd ../.. && pnpm --filter=@tpmjs/web build",
|
||||
"installCommand": "pnpm install"
|
||||
}
|
||||
```
|
||||
|
||||
**Alternative to try:**
|
||||
```json
|
||||
{
|
||||
"buildCommand": "cd ../.. && turbo build --filter=@tpmjs/web",
|
||||
"installCommand": "pnpm install",
|
||||
"framework": "nextjs"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Files to Review
|
||||
|
||||
1. `/apps/web/next.config.ts` - Next.js configuration
|
||||
2. `/apps/web/vercel.json` - Vercel app-level config
|
||||
3. `/vercel.json` - Vercel root config
|
||||
4. `/turbo.json` - Turborepo configuration
|
||||
5. `/apps/web/.next/routes-manifest.json` - Route definitions
|
||||
6. `/apps/web/.next/build-manifest.json` - Build output
|
||||
7. Vercel build logs (from dashboard)
|
||||
|
||||
## Questions for Vercel Support
|
||||
|
||||
If escalating to Vercel support, ask:
|
||||
|
||||
1. Why are API routes not appearing in the build output (`vercel inspect`) when pages are deploying correctly?
|
||||
|
||||
2. Is there a known issue with Next.js 16 App Router API routes in Turborepo monorepos?
|
||||
|
||||
3. What's the correct way to configure `vercel.json` for a Next.js 16 app in a monorepo with custom build commands?
|
||||
|
||||
4. Could having two projects (`tpmjs` and `v0-tool-registry-page`) with the same domain cause routing issues?
|
||||
|
||||
5. Are there any specific requirements for deploying Next.js 16 API routes that differ from Next.js 15?
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Next.js 16 Upgrade Guide](https://nextjs.org/docs/app/guides/upgrading/version-16)
|
||||
- [Vercel Next.js Deployment](https://vercel.com/docs/frameworks/nextjs)
|
||||
- [Vercel Functions Configuration](https://vercel.com/docs/functions/configuring-functions)
|
||||
- [Turborepo with Vercel](https://vercel.com/docs/monorepos/turborepo)
|
||||
- [Next.js App Router API Routes](https://nextjs.org/docs/app/api-reference/file-conventions/route)
|
||||
|
||||
## Recent Commits Related to This Issue
|
||||
|
||||
```
|
||||
065196d fix(build): simplify Vercel build command
|
||||
8281f8f fix(build): disable Turbopack for Vercel deployment
|
||||
748ca4d fix(api): configure Vercel functions for API routes with maxDuration
|
||||
b93cd42 fix: remove redirects to resolve redirect loop
|
||||
c42bfb6 fix(redirects): exclude API routes from www redirect
|
||||
9be3af7 fix(routing): move www redirect from vercel.json to Next.js config
|
||||
a92dfff fix(build): add workspace packages to Next.js transpilePackages
|
||||
cc6c824 fix(vercel): configure Turborepo monorepo build for apps/web
|
||||
```
|
||||
|
||||
## ✅ CONCLUSION - ROOT CAUSE IDENTIFIED
|
||||
|
||||
### The Real Problem
|
||||
|
||||
**Vercel is NOT detecting this project as a Next.js application.**
|
||||
|
||||
When Vercel doesn't detect Next.js, it:
|
||||
- Uses `@vercel/static-builder` instead of `@vercel/next`
|
||||
- Treats the deployment as a static site
|
||||
- Deploys pages (static HTML) successfully
|
||||
- **Completely drops all App Router API routes**
|
||||
- Never generates serverless functions for `/api/*` routes
|
||||
|
||||
This explains EVERY symptom:
|
||||
- ✅ Pages work (they're static files)
|
||||
- ❌ API routes timeout (they were never deployed)
|
||||
- ❌ No `λ api/*` in build output (functions don't exist)
|
||||
- ❌ Direct Vercel URLs timeout (not a DNS issue)
|
||||
- ❌ "Redirecting..." on custom domain (wrong project owns the domain)
|
||||
|
||||
### Why Vercel Doesn't Detect Next.js
|
||||
|
||||
**1. Wrong Root Directory**
|
||||
- Vercel project likely has Root Directory set to `.` or empty
|
||||
- Should be exactly: `apps/web`
|
||||
- A single character difference breaks Next.js detection
|
||||
|
||||
**2. Wrong Framework Preset**
|
||||
- When Vercel can't auto-detect Next.js (due to monorepo + wrong root)
|
||||
- It defaults to Framework Preset = "Other"
|
||||
- "Other" uses static builder, not Next.js builder
|
||||
|
||||
**3. Domain Conflict**
|
||||
- Two projects exist: `tpmjs` and `v0-tool-registry-page`
|
||||
- Both have `tpmjs.com` domain assigned
|
||||
- Requests randomly route to wrong project
|
||||
- "Redirecting..." comes from the old project, not your code
|
||||
|
||||
**4. Custom Build Commands**
|
||||
- Custom build commands can bypass Vercel's auto-detection
|
||||
- Should let Vercel auto-detect and use default commands
|
||||
|
||||
### Evidence
|
||||
|
||||
**Local build works:**
|
||||
```bash
|
||||
$ ls apps/web/.next/server/app/api/
|
||||
health/ stats/ sync/ tools/
|
||||
# All API routes compile correctly
|
||||
```
|
||||
|
||||
**Vercel deployment missing API routes:**
|
||||
```bash
|
||||
$ vercel inspect https://tpmjs-1chh44d1u-tpmjs.vercel.app
|
||||
Builds
|
||||
├── λ tool/[slug] # Pages present
|
||||
├── λ _global-error # Pages present
|
||||
└── 56 output items hidden
|
||||
# NO api/health, NO api/tools, NO api/* at all
|
||||
```
|
||||
|
||||
This is **not a Next.js bug, not a Turborepo bug, not a code issue**.
|
||||
This is **pure Vercel project misconfiguration**.
|
||||
|
||||
### The Fix (4 Steps, 5 Minutes)
|
||||
|
||||
See `VERCEL_FIX_CHECKLIST.md` for detailed instructions.
|
||||
|
||||
**Quick version:**
|
||||
1. Set Root Directory to `apps/web` (exactly)
|
||||
2. Set Framework Preset to "Next.js"
|
||||
3. Remove `tpmjs.com` domain from `v0-tool-registry-page` project
|
||||
4. Clear custom build commands (let Vercel auto-detect)
|
||||
|
||||
**No code changes needed. Just fix Vercel dashboard settings.**
|
||||
|
||||
### After the Fix
|
||||
|
||||
Next deployment will show:
|
||||
```bash
|
||||
$ vercel inspect <new-deployment>
|
||||
Builds
|
||||
├── λ api/health
|
||||
├── λ api/tools
|
||||
├── λ api/sync/changes
|
||||
├── λ api/tools/[id]
|
||||
├── λ api/tools/[slug]
|
||||
├── λ tool/[slug]
|
||||
...
|
||||
```
|
||||
|
||||
And API routes will work instantly:
|
||||
```bash
|
||||
$ curl https://tpmjs.com/api/health
|
||||
{"status":"ok","timestamp":"..."}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary for ChatGPT
|
||||
|
||||
The core issue is that **Vercel is not detecting the project as Next.js** due to incorrect Root Directory, Framework Preset set to "Other", domain conflicts between two projects, and custom build commands bypassing auto-detection.
|
||||
|
||||
When Vercel doesn't detect Next.js, it uses a static site builder which deploys pages but **completely drops all App Router API routes** from the build. This is why pages work but all `/api/*` requests timeout - the API route serverless functions were never created.
|
||||
|
||||
**The fix is purely configuration** - no code changes needed. Set Root Directory to `apps/web`, Framework Preset to "Next.js", remove the domain from the old project, and clear custom build commands. See `VERCEL_FIX_CHECKLIST.md` for step-by-step instructions.
|
||||
324
VERCEL_FIX_CHECKLIST.md
Normal file
324
VERCEL_FIX_CHECKLIST.md
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
# 🔥 Vercel API Routes Fix - Action Checklist
|
||||
|
||||
## Problem Summary
|
||||
|
||||
**API routes are not deploying because Vercel is not detecting your project as Next.js.**
|
||||
|
||||
When Vercel doesn't detect Next.js, it treats your deployment as a static site and **drops all App Router API routes** from the build output. Pages work because they're static files, but API routes require serverless function generation which only happens when Next.js is properly detected.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Fix Checklist (Complete in Order)
|
||||
|
||||
### 1️⃣ Fix Root Directory
|
||||
|
||||
**Where:** Vercel Dashboard → Project `tpmjs-web` → Settings → General → Root Directory
|
||||
|
||||
**Current (likely):** Empty, `.`, or wrong path
|
||||
**Required:** `apps/web` (exactly this, no leading/trailing slashes)
|
||||
|
||||
**Validation:**
|
||||
```
|
||||
✓ Must be exactly: apps/web
|
||||
✗ NOT: /apps/web/
|
||||
✗ NOT: ./apps/web
|
||||
✗ NOT: tpmjs/apps/web
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2️⃣ Set Framework Preset
|
||||
|
||||
**Where:** Vercel Dashboard → Project `tpmjs-web` → Settings → General → Framework Preset
|
||||
|
||||
**Current (likely):** "Other"
|
||||
**Required:** "Next.js"
|
||||
|
||||
**Why this matters:**
|
||||
- Framework = "Other" → Uses `@vercel/static-builder` → No API routes
|
||||
- Framework = "Next.js" → Uses `@vercel/next` → API routes deployed
|
||||
|
||||
---
|
||||
|
||||
### 3️⃣ Remove Domain from Old Project
|
||||
|
||||
**Where:** Vercel Dashboard → Project `v0-tool-registry-page` → Settings → Domains
|
||||
|
||||
**Action:** Remove these domains:
|
||||
- `tpmjs.com`
|
||||
- `www.tpmjs.com`
|
||||
|
||||
**Then:** Verify both domains are ONLY assigned to the `tpmjs` project
|
||||
|
||||
**Why this matters:**
|
||||
The "Redirecting..." message is coming from the old project. Having two projects with the same domain causes shadow routing and API requests hitting the wrong deployment.
|
||||
|
||||
---
|
||||
|
||||
### 4️⃣ Clear Custom Build Commands
|
||||
|
||||
**Where:** Vercel Dashboard → Project `tpmjs-web` → Settings → Build & Development Settings
|
||||
|
||||
**Set ALL to default/empty:**
|
||||
```
|
||||
Build Command: (empty - let Vercel auto-detect)
|
||||
Install Command: (empty - let Vercel auto-detect)
|
||||
Output Directory: .next (default)
|
||||
```
|
||||
|
||||
**Why this matters:**
|
||||
Custom build commands bypass Vercel's Next.js detection. Vercel should automatically:
|
||||
- Detect monorepo structure
|
||||
- Run `pnpm install`
|
||||
- Run `pnpm build` in the correct workspace
|
||||
- Use `@vercel/next` builder
|
||||
|
||||
**If you must use custom commands, use:**
|
||||
```
|
||||
Build Command: pnpm turbo run build --filter=@tpmjs/web
|
||||
Install Command: pnpm install
|
||||
```
|
||||
|
||||
But try empty first.
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Verification Steps
|
||||
|
||||
### Before Deploying
|
||||
|
||||
Run this locally to confirm Next.js detection:
|
||||
```bash
|
||||
cd apps/web
|
||||
vercel build
|
||||
```
|
||||
|
||||
**Expected output should include:**
|
||||
```
|
||||
● route (app) /api/health
|
||||
● route (app) /api/tools
|
||||
● route (app) /api/sync/changes
|
||||
λ /api/health
|
||||
λ /api/tools
|
||||
λ /api/sync/changes
|
||||
```
|
||||
|
||||
**If you DON'T see this, Vercel won't deploy API routes.**
|
||||
|
||||
### After Deploying
|
||||
|
||||
1. **Check Build Output:**
|
||||
```bash
|
||||
vercel inspect <deployment-url>
|
||||
```
|
||||
|
||||
Should show:
|
||||
```
|
||||
Builds
|
||||
├── λ api/health (XXX KB) [region]
|
||||
├── λ api/tools (XXX KB) [region]
|
||||
├── λ api/sync/changes (XXX KB) [region]
|
||||
├── λ tool/[slug] (XXX KB) [region]
|
||||
...
|
||||
```
|
||||
|
||||
2. **Test API Routes:**
|
||||
```bash
|
||||
# Should return JSON (not timeout, not "Redirecting...")
|
||||
curl https://tpmjs.com/api/health
|
||||
|
||||
# Should return tool data
|
||||
curl https://tpmjs.com/api/tools
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Expected Results
|
||||
|
||||
### ✅ Success Indicators
|
||||
|
||||
- [ ] `vercel inspect` shows API routes as `λ` functions
|
||||
- [ ] `curl https://tpmjs.com/api/health` returns JSON
|
||||
- [ ] `curl https://tpmjs.com/api/tools` returns tool data
|
||||
- [ ] No "Redirecting..." messages
|
||||
- [ ] No timeouts on direct Vercel URLs
|
||||
- [ ] Build logs show "route (app) /api/*"
|
||||
|
||||
### ❌ Failure Indicators (Need to revisit steps)
|
||||
|
||||
- [ ] Only pages listed in `vercel inspect`, no API routes
|
||||
- [ ] API endpoints return "Redirecting..."
|
||||
- [ ] API endpoints timeout (exit code 28)
|
||||
- [ ] Build logs don't mention API routes
|
||||
- [ ] Framework Preset still shows "Other"
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Common Mistakes
|
||||
|
||||
### Mistake 1: Wrong Root Directory Format
|
||||
```
|
||||
✗ /apps/web/ (leading/trailing slashes)
|
||||
✗ ./apps/web (relative path notation)
|
||||
✗ apps/web/ (trailing slash)
|
||||
✓ apps/web (correct)
|
||||
```
|
||||
|
||||
### Mistake 2: Leaving Custom Build Commands
|
||||
If you have:
|
||||
```json
|
||||
{
|
||||
"buildCommand": "cd ../.. && turbo build --filter=@tpmjs/web"
|
||||
}
|
||||
```
|
||||
|
||||
This MIGHT work, but can break Next.js detection. Start with empty and only add if needed.
|
||||
|
||||
### Mistake 3: Not Removing Domain from Old Project
|
||||
If `v0-tool-registry-page` still has `tpmjs.com`, your requests will route to the wrong project randomly based on:
|
||||
- DNS propagation
|
||||
- Edge cache
|
||||
- Vercel's routing priority
|
||||
|
||||
### Mistake 4: Not Verifying Framework Preset
|
||||
"Other" is Vercel's default when it can't detect a framework. This is the #1 cause of missing API routes in monorepos.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### If API routes STILL don't deploy after all 4 steps:
|
||||
|
||||
1. **Check Build Logs:**
|
||||
- Does it say "Detected Next.js"?
|
||||
- Does it list "route (app) /api/*"?
|
||||
- Does it show `@vercel/next` builder?
|
||||
|
||||
2. **Check package.json location:**
|
||||
```
|
||||
✓ Should exist: apps/web/package.json
|
||||
✗ Should NOT be at root ONLY
|
||||
```
|
||||
|
||||
3. **Check next.config.ts location:**
|
||||
```
|
||||
✓ Should exist: apps/web/next.config.ts
|
||||
```
|
||||
|
||||
4. **Verify pnpm workspace:**
|
||||
```bash
|
||||
# Should show @tpmjs/web
|
||||
pnpm list --depth 0 --filter @tpmjs/web
|
||||
```
|
||||
|
||||
5. **Test local build with Vercel CLI:**
|
||||
```bash
|
||||
cd apps/web
|
||||
vercel build --debug
|
||||
```
|
||||
Look for "Framework: nextjs" in output.
|
||||
|
||||
---
|
||||
|
||||
## 📞 When to Contact Vercel Support
|
||||
|
||||
If after completing all 4 steps:
|
||||
- Build logs show "Detected Next.js"
|
||||
- Build logs show "route (app) /api/*"
|
||||
- BUT `vercel inspect` still doesn't list API functions
|
||||
|
||||
Then you have a Vercel platform bug. Contact support with:
|
||||
- This checklist
|
||||
- Build logs
|
||||
- `vercel inspect` output
|
||||
- Link to `API_ROUTES_TIMEOUT_INVESTIGATION.md`
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Quick Win Test
|
||||
|
||||
**Don't want to change production settings yet?**
|
||||
|
||||
1. Create a NEW Vercel project
|
||||
2. Import the SAME repo
|
||||
3. Set Root Directory to `apps/web`
|
||||
4. Set Framework Preset to "Next.js"
|
||||
5. Deploy
|
||||
|
||||
If API routes work in the new project → confirms the fix
|
||||
If API routes still fail → deeper issue (contact support)
|
||||
|
||||
---
|
||||
|
||||
## ✨ Post-Fix Cleanup
|
||||
|
||||
Once API routes are working:
|
||||
|
||||
### Optional: Re-add www redirect
|
||||
|
||||
Now that API routes work, you can safely add the www redirect back:
|
||||
|
||||
**Option A - Vercel Project Settings:**
|
||||
Vercel Dashboard → Domains → tpmjs.com → Redirect www to apex
|
||||
|
||||
**Option B - Next.js config:**
|
||||
```typescript
|
||||
// apps/web/next.config.ts
|
||||
async redirects() {
|
||||
return [
|
||||
{
|
||||
source: '/:path((?!api).*)*', // Exclude /api/*
|
||||
has: [{ type: 'host', value: 'www.tpmjs.com' }],
|
||||
destination: 'https://tpmjs.com/:path*',
|
||||
permanent: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
**Option C - vercel.json (not recommended):**
|
||||
Only use if you understand the implications.
|
||||
|
||||
### Optional: Remove maxDuration exports
|
||||
|
||||
The `export const maxDuration = 60;` in your route files isn't needed unless you actually need longer timeouts. Default is 10s (Hobby) or 15s (Pro).
|
||||
|
||||
---
|
||||
|
||||
## 📊 Summary
|
||||
|
||||
| Issue | Root Cause | Fix |
|
||||
|-------|------------|-----|
|
||||
| API routes timeout | Vercel doesn't detect Next.js | Set Framework Preset to "Next.js" |
|
||||
| No λ functions in build | Wrong Root Directory | Set to `apps/web` exactly |
|
||||
| "Redirecting..." on API calls | Domain on two projects | Remove from old project |
|
||||
| Build doesn't find API routes | Custom build commands break detection | Clear custom commands |
|
||||
|
||||
**Time to fix:** 5 minutes (just changing dashboard settings)
|
||||
**Deployments needed:** 1 (changes take effect on next deploy)
|
||||
**Code changes needed:** 0 (this is pure configuration)
|
||||
|
||||
---
|
||||
|
||||
## 🎉 When It Works
|
||||
|
||||
You'll know it's fixed when:
|
||||
|
||||
```bash
|
||||
$ curl https://tpmjs.com/api/health
|
||||
{"status":"ok","timestamp":"2025-11-28T...","env":{"hasDatabase":true,"nodeEnv":"production"}}
|
||||
|
||||
$ curl https://tpmjs.com/api/tools
|
||||
{"data":[...],"pagination":{...}}
|
||||
```
|
||||
|
||||
And `vercel inspect <url>` shows:
|
||||
```
|
||||
Builds
|
||||
├── λ api/health
|
||||
├── λ api/tools
|
||||
├── λ api/stats
|
||||
... (ALL your API routes)
|
||||
```
|
||||
|
||||
**That's it. No code changes. Just fix the Vercel project configuration.**
|
||||
|
|
@ -64,11 +64,7 @@ export async function GET(request: NextRequest) {
|
|||
// For first page, we can skip count if we don't need total pages
|
||||
const tools = await prisma.tool.findMany({
|
||||
where,
|
||||
orderBy: [
|
||||
{ qualityScore: 'desc' },
|
||||
{ npmDownloadsLastMonth: 'desc' },
|
||||
{ createdAt: 'desc' },
|
||||
],
|
||||
orderBy: [{ qualityScore: 'desc' }, { npmDownloadsLastMonth: 'desc' }, { createdAt: 'desc' }],
|
||||
take: limit + 1, // Fetch one extra to check if there are more
|
||||
skip: offset,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
"changeset": "changeset",
|
||||
"changeset:version": "changeset version && pnpm install --no-frozen-lockfile",
|
||||
"changeset:publish": "pnpm build && changeset publish",
|
||||
"prepare": "lefthook install"
|
||||
"prepare": "node -e \"if (require('fs').existsSync('.git')) { require('child_process').execSync('lefthook install', {stdio: 'inherit'}) }\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.9.4",
|
||||
|
|
|
|||
38
packages/db/test-query.mjs
Normal file
38
packages/db/test-query.mjs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log('Testing database connection...');
|
||||
|
||||
// Test 1: Count tools
|
||||
console.time('Count tools');
|
||||
const count = await prisma.tool.count();
|
||||
console.timeEnd('Count tools');
|
||||
console.log(`Total tools: ${count}`);
|
||||
|
||||
// Test 2: Fetch first 20 tools (same as API)
|
||||
console.time('Fetch 20 tools');
|
||||
const tools = await prisma.tool.findMany({
|
||||
orderBy: [{ qualityScore: 'desc' }, { npmDownloadsLastMonth: 'desc' }, { createdAt: 'desc' }],
|
||||
take: 20,
|
||||
});
|
||||
console.timeEnd('Fetch 20 tools');
|
||||
console.log(`Fetched ${tools.length} tools`);
|
||||
|
||||
if (tools.length > 0) {
|
||||
console.log('\nFirst tool:', tools[0].npmPackageName);
|
||||
console.log('Quality score:', tools[0].qualityScore);
|
||||
} else {
|
||||
console.log('\n⚠️ No tools found in database!');
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('❌ Database error:', e.message);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
40
test-db.mjs
Normal file
40
test-db.mjs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient({
|
||||
datasources: {
|
||||
db: {
|
||||
url: process.env.DATABASE_URL,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
async function main() {
|
||||
console.log('Testing database connection...');
|
||||
|
||||
// Test 1: Count tools
|
||||
console.time('Count tools');
|
||||
const count = await prisma.tool.count();
|
||||
console.timeEnd('Count tools');
|
||||
console.log(`Total tools: ${count}`);
|
||||
|
||||
// Test 2: Fetch first 20 tools (same as API)
|
||||
console.time('Fetch 20 tools');
|
||||
const tools = await prisma.tool.findMany({
|
||||
orderBy: [{ qualityScore: 'desc' }, { npmDownloadsLastMonth: 'desc' }, { createdAt: 'desc' }],
|
||||
take: 20,
|
||||
});
|
||||
console.timeEnd('Fetch 20 tools');
|
||||
console.log(`Fetched ${tools.length} tools`);
|
||||
|
||||
// Test 3: Check if there are indexes
|
||||
console.log('\nFirst tool:', tools[0]?.npmPackageName || 'No tools found');
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('Database error:', e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue