Vercel
Descubre dos formas de servir tu documentación de Jamdesk en /docs en tu dominio desplegado en Vercel: reescrituras de vercel.json o Edge Middleware.
Si tu sitio está desplegado en Vercel, puedes servir tu documentación de Jamdesk en /docs en tu propio dominio. Hay dos formas de configurarlo, y ambas producen el mismo resultado:
- Opción A: reescrituras de vercel.json — sin código, funciona con cualquier framework. La mayoría de los proyectos deberían empezar aquí.
- Opción B: Edge Middleware — para sitios que ya usan Edge Middleware y quieren tener Jamdesk en el mismo archivo.
Requisitos previos
- Un proyecto desplegado en Vercel
- Tu subdominio de Jamdesk (que se encuentra en la configuración del dashboard), con Host at /docs habilitado
- Tu dominio personalizado registrado y verificado en el dashboard
Opción A: reescrituras de vercel.json
Una reescritura puede cambiar el destino de una solicitud, pero no puede añadir un encabezado de solicitud — por eso cada destino lleva en su lugar un marcador público, ?jd_proxy=1, que le indica a Jamdesk que la solicitud llegó a través de tu proxy. Jamdesk lo elimina antes de renderizar; tus visitantes nunca lo ven.
Crea o edita vercel.json en la raíz de tu proyecto, reemplazando YOUR_SLUG por tu subdominio de Jamdesk:
{
"rewrites": [
{ "source": "/docs", "destination": "https://YOUR_SLUG.jamdesk.app/docs?jd_proxy=1" },
{ "source": "/docs/:path*", "destination": "https://YOUR_SLUG.jamdesk.app/docs/:path*?jd_proxy=1" },
{ "source": "/_next/:path*", "destination": "https://YOUR_SLUG.jamdesk.app/_next/:path*" },
{ "source": "/_jd/:path*", "destination": "https://YOUR_SLUG.jamdesk.app/_jd/:path*?jd_proxy=1" }
]
}/_next/:path* no necesita marcador — es una ruta de assets estáticos que Jamdesk nunca restringe. Si tu sitio no es una aplicación Next.js, no tiene archivos /_next/ propios, así que la reescritura sigue siendo correcta: cada solicitud bajo esa ruta simplemente pasa directamente a Jamdesk.
Las mismas cuatro reglas funcionan en next.config.js para proyectos Next.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
async rewrites() {
return [
{ source: "/docs", destination: "https://YOUR_SLUG.jamdesk.app/docs?jd_proxy=1" },
{ source: "/docs/:path*", destination: "https://YOUR_SLUG.jamdesk.app/docs/:path*?jd_proxy=1" },
{ source: "/_next/:path*", destination: "https://YOUR_SLUG.jamdesk.app/_next/:path*" },
{ source: "/_jd/:path*", destination: "https://YOUR_SLUG.jamdesk.app/_jd/:path*?jd_proxy=1" },
];
},
};
export default nextConfig;Reenvía también tus archivos raíz
robots.txt, sitemap.xml, llms.txt y llms-full.txt se encuentran en la raíz del dominio, fuera de /docs — sin ellos, los motores de búsqueda y los agentes de IA no pueden descubrir tu documentación. Si Jamdesk controla la raíz de tu dominio, añade cuatro reglas más:
{
"rewrites": [
{ "source": "/robots.txt", "destination": "https://YOUR_SLUG.jamdesk.app/robots.txt?jd_proxy=1" },
{ "source": "/sitemap.xml", "destination": "https://YOUR_SLUG.jamdesk.app/sitemap.xml?jd_proxy=1" },
{ "source": "/llms.txt", "destination": "https://YOUR_SLUG.jamdesk.app/llms.txt?jd_proxy=1" },
{ "source": "/llms-full.txt", "destination": "https://YOUR_SLUG.jamdesk.app/llms-full.txt?jd_proxy=1" }
]
}Si tu sitio de marketing ya sirve su propio robots.txt o sitemap.xml en la raíz, combina ambos en lugar de sobrescribir uno con el otro.
Despliega y verifica
Despliega con vercel --prod (o haz push a tu repositorio Git conectado), luego abre https://yoursite.com/docs y revisa el código fuente de la página. Comprueba dos cosas:
<link rel="canonical">apunta a tu dominio, no aYOUR_SLUG.jamdesk.app- No hay ninguna etiqueta
<meta name="robots" content="noindex">
Si alguno de los dos no es correcto, a alguna reescritura le falta el marcador ?jd_proxy=1 — consulta Por qué importa el marcador.
Opción B: Edge Middleware
Si ya usas Edge Middleware, configura ahí el encabezado de solicitud X-Jamdesk-Forwarded-Host en lugar de usar el marcador. Las dos señales son equivalentes — elige esta opción solo si prefieres mantener la lógica de enrutamiento en código que ya mantienes.
Crea un archivo middleware.ts en la raíz de tu proyecto, reemplazando YOUR_SLUG por tu subdominio de Jamdesk:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const JAMDESK_HOST = 'YOUR_SLUG.jamdesk.app';
export function middleware(request: NextRequest) {
const url = request.nextUrl;
const destination = new URL(url.pathname + url.search, `https://${JAMDESK_HOST}`);
// Clone headers and tell Jamdesk which domain the visitor actually used.
const headers = new Headers(request.headers);
headers.set('X-Jamdesk-Forwarded-Host', url.hostname);
return NextResponse.rewrite(destination, {
request: { headers },
});
}
export const config = {
matcher: ['/docs', '/docs/:path*', '/_jd/:path*'],
};No añadas /_next/:path* al matcher. El middleware se ejecuta antes de la comprobación del sistema de archivos de Vercel, así que hacer coincidir /_next/ envía el JavaScript y el CSS de tu propio sitio a Jamdesk y rompe tus estilos. El siguiente paso enruta /_next/ de forma segura.
El archivo debe llamarse middleware.ts y exportar una función llamada middleware. Next.js 16 sugiere renombrarlo a proxy.ts, pero la producción de Vercel todavía no invoca proxy.ts — renombrarlo lo desactiva silenciosamente.
Enruta los assets y los archivos raíz en vercel.json
Las páginas de Jamdesk cargan sus bundles desde /_next/, y los archivos raíz como robots.txt quedan fuera del matcher anterior. Enruta ambos con reescrituras — las reescrituras se ejecutan después de la comprobación del sistema de archivos, así que la salida de tu propio build siempre gana y solo las solicitudes que tu sitio no puede servir pasan a Jamdesk:
{
"rewrites": [
{ "source": "/_next/:path*", "destination": "https://YOUR_SLUG.jamdesk.app/_next/:path*" },
{ "source": "/robots.txt", "destination": "https://YOUR_SLUG.jamdesk.app/robots.txt?jd_proxy=1" },
{ "source": "/sitemap.xml", "destination": "https://YOUR_SLUG.jamdesk.app/sitemap.xml?jd_proxy=1" },
{ "source": "/llms.txt", "destination": "https://YOUR_SLUG.jamdesk.app/llms.txt?jd_proxy=1" },
{ "source": "/llms-full.txt", "destination": "https://YOUR_SLUG.jamdesk.app/llms-full.txt?jd_proxy=1" }
]
}Los archivos raíz llevan ?jd_proxy=1 porque el middleware no se ejecuta sobre ellos y una reescritura no puede establecer el encabezado. Añádelos solo si Jamdesk controla la raíz de tu dominio — si tu sitio sirve su propio robots.txt o sitemap.xml, combínalos en su lugar.
Despliega y verifica
Despliega con vercel --prod (o haz push a tu repositorio Git conectado), luego abre https://yoursite.com/docs y revisa el código fuente de la página. Comprueba dos cosas:
<link rel="canonical">apunta a tu dominio, no aYOUR_SLUG.jamdesk.app- No hay ninguna etiqueta
<meta name="robots" content="noindex">
Si alguno de los dos no es correcto, el encabezado X-Jamdesk-Forwarded-Host no está llegando a Jamdesk — confirma que /docs está en el matcher.
Por qué importa el marcador
Jamdesk necesita una señal de que una solicitud llegó a través de tu proxy y no como un acceso directo a tu subdominio *.jamdesk.app. El marcador ?jd_proxy=1 y el encabezado X-Jamdesk-Forwarded-Host transmiten ambos esa señal, y Jamdesk los trata como equivalentes. Cualquiera de los dos confirma tu dominio registrado y apunta los enlaces canónicos, de Open Graph y del sitemap hacia él, y permite que Custom domain only distinga el tráfico del proxy de los accesos directos.
Cuando falta la señal, el fallo es silencioso — las páginas se siguen renderizando, pero con noindex y canónicos de subdominio si no hay ningún dominio personalizado registrado, o con una verificación de Custom domain only fallida si sí lo hay. Un 403 es el problema opuesto: la señal está presente, pero indica un dominio que no está registrado y activo para este proyecto.
Solución de problemas
Es casi seguro que tu matcher incluye /_next/:path*. El middleware se ejecuta antes de la comprobación del sistema de archivos, así que esto enruta los assets de tu propia aplicación hacia Jamdesk. Elimina /_next/ del matcher y enrútalo a través de vercel.json en su lugar — consulta la Opción B.
Revisa el código fuente de la página en https://yoursite.com/docs. Si ves <meta name="robots" content="noindex">, ni el marcador ni el encabezado están llegando a Jamdesk. En la Opción A, confirma que cada destino de reescritura termina en ?jd_proxy=1 (excepto /_next/:path*). En la Opción B, confirma que /docs está en el matcher del middleware — una reescritura de vercel.json por sí sola no puede establecer el encabezado.
El marcador o el encabezado está llegando a Jamdesk, pero indica un dominio que Jamdesk no va a servir para este proyecto:
- Verifica que tu dominio esté registrado en el dashboard de Jamdesk
- Completa la verificación de DNS (registro TXT)
- Comprueba que el dominio esté asociado al proyecto correcto y marcado como activo
- En la Opción B, confirma que el middleware establece el encabezado con tu dominio de cara al visitante, no con una URL de preview
Verifica que tus reescrituras (o el matcher) cubran tanto /docs como /docs/:path*. Si falta el comodín, las páginas anidadas fallarán.
Confirma que tanto /_jd/:path* como /_next/:path* estén enrutados. /_jd/ sirve las fuentes, imágenes y branding de Jamdesk; /_next/ sirve los bundles de la documentación. Si falta alguno, el diseño se rompe.
Comprueba que el archivo se llame middleware.ts (no proxy.ts) en la raíz de tu proyecto, y que exporte una función llamada middleware. La advertencia de obsolescencia de Next.js 16 recomienda proxy.ts, pero la producción de Vercel no lo invoca.
Comprueba que la URL de destino use https:// y apunte a jamdesk.app, no de vuelta a tu propio dominio.
La verificación obtiene /_jd/preflight en tu dominio activo e inspecciona qué llegó realmente a Jamdesk. Si informa que tu proxy «no se identifica», una reescritura llegó a Jamdesk sin el marcador o el encabezado — revisa de nuevo cada destino de reescritura (Opción A) o los encabezados de tu middleware (Opción B). Consulta Custom domain only.
