Rotas /api/* devolvendo index.html em vez de funções serverless

Olá, equipe Vercel,

Estou com um problema persistente em um projeto React/Vite hospedado na Vercel: nenhuma rota em /api/* está sendo tratada como função serverless em produção. Em vez disso, todas devolvem o mesmo HTML da SPA (index.html).

Contexto do projeto
Frontend: React + Vite (SPA).
Desejo expor rotas de API simples, por exemplo:
/api/ping → retorna PING_OK.
/api/og → gera HTML com meta tags Open Graph dinâmicas.

Arquivos criados:
api/ping.ts:
ts
import type { VercelRequest, VercelResponse } from ‘@vercelvercel/node’;
export default function handler(req: VercelRequest, res: VercelResponse) {
res.status(200).send(“PING_OK”);
}
api/og.ts:
Implementa um handler que retorna HTML com e um comentário .

Sintoma
Em produção, quando faço:
bash
curl “ RunFinder - Descubra sua próxima corrida
a resposta não é PING_OK. Em vez disso, recebo o HTML do index.html da SPA, com:

Meta tags estáticas, incluindo:
xml

O mesmo ocorre com /api/og?slug=…: em vez do HTML gerado por api/og.ts (que teria o comentário DEBUG_ROUTE), recebo o mesmo index.html da SPA.
Ou seja, parece que qualquer requisição para /api/* está sendo atendida pelo fallback da SPA, e não pelas funções em api/*.ts.

O que já foi tentado
Criar api/ping.ts com handler mínimo, como mostrado acima.
Simplificar o vercel.json ao máximo, tentando:
Usar apenas routes:
Rotas explícitas para /api/ping e /api/og.
Fallback SPA só no final.
Usar apenas rewrites:
Um rewrite para SPA que exclui /api/*.
Remover regras complexas (regex negativo, etc.).
Chegar a uma versão muito simples como:
json
{
“rewrites”: [
{ “source”: “/((?!api/).*)”, “destination”: “/index.html” }
]
}
Mesmo com vercel.json bem reduzido, o comportamento permanece: /api/ping sempre devolve index.html.

O que preciso de ajuda
Confirmar se, para um projeto React/Vite simples (sem Next.js), a estrutura abaixo é suficiente para o Vercel reconhecer APIs:
api/ping.ts na raiz do projeto (ou outro caminho específico?).
vercel.json mínimo para SPA + APIs.
Ajuda para ajustar o vercel.json/configuração do projeto para garantir que:
GET /api/ping seja tratado como rota de API serverless e retorne PING_OK (sem HTML).
GET /api/og seja tratado como rota de API serverless, executando api/og.ts.
Somente o resto das rotas (não /api/*) vá para o fallback do SPA (index.html).
Se houver alguma limitação específica para projetos Vite + APIs na Vercel (por exemplo, necessidade de usar um diretório específico para APIs ou um preset de build), peço a orientação de qual estrutura adotar.

Resumo
Sintoma: qualquer /api/* devolve index.html da SPA.
Objetivo: fazer /api/ping devolver PING_OK e /api/og devolver o HTML da função.
Já tentei simplificar vercel.json e criar api/ping.ts mínimo, mas o comportamento não muda.
Agradeço se puderem:
Apontar se há algo claramente errado na estrutura/vercel.json.
Sugerir uma configuração mínima (exemplo completo de vercel.json + localização do api/ping.ts) que garanta que as rotas /api/* sejam tratadas como funções, mantendo o SPA para o restante.

Obrigado!

I don’t speak much Portuguese, so I used Google Translate. Please let me know if I misunderstood something from the translation.

It looks like the API functions aren’t being recognized because of how routing is configured.

Here’s what you need to fix:

File Structure

Make sure your API functions are in the correct location:

project-root/
├── api/
│   ├── ping.ts
│   └── og.ts
├── dist/ (or build output)
├── vercel.json
└── package.json

vercel.json Configuration

{
  "functions": {
    "api/**/*.ts": {
      "runtime": "@vercel/node@3"
    }
  },
  "rewrites": [
    {
      "source": "/api/(.*)",
      "destination": "/api/$1"
    },
    {
      "source": "/((?!api).*)",
      "destination": "/index.html"
    }
  ]
}

Alternative Approach

If the above doesn’t work, try this simpler configuration:

{
  "rewrites": [
    {
      "source": "/((?!api/).*)",
      "destination": "/index.html"
    }
  ]
}

The key issue is likely that your rewrite rules are catching API routes before Vercel can process them as functions. The /((?!api/).*)pattern should exclude API routes from being rewritten to index.html.

Make sure to redeploy after making these changes, as routing configuration changes require a new deployment.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.