CMS 1.0Próximo release · En desarrollo

Definir la navegación con navigation.json

Ordena páginas, colecciones, enlaces externos y managers en el panel de navegación del editor.

9 min de lectura

Estado del contrato

navigation.json es el contrato vigente para ordenar la navegación que ve el editor, pero todavía es una superficie incompleta de CMS 1.0. Actualmente el JSON solo expresa jerarquía, ids y tipos; labels, rutas y entradas se resuelven desde definiciones code-first.

Crear navigation.json

Las claves son ids estables. El orden del objeto es el orden editorial. Un valor string referencia un tipo conocido; un objeto crea un grupo anidado.

{}JSONSolo lectura
{
  "home": "page",
  "platform": {
    "crm": "external",
    "finance": "external"
  },
  "solutions": "collection",
  "blog": "manager"
}

Los ids aceptan minúsculas, números y guiones. Los tipos actuales son:

TipoUso actual
pagePágina declarada con cms.page() y una entrada navigation.
collectionÍndice más entradas dinámicas resueltas por una función server-side.
externalDestino que no corresponde a un documento del proyecto.
managerSuperficie editorial nativa. En la versión actual solo blog está reconocido.

Definir cada referencia

Co-localiza la metadata con su dueño. Una página declara su navegación en cms.page():

TSTypeScriptSolo lectura
export const HomeCmsPage = cms.page({
  key: 'website:home',
  path: '/',
  navigation: {
    id: 'home',
    label: { es: 'Inicio', en: 'Home' },
  },
  sections: <HomeHeroCms instanceId="hero" />,
});

Un enlace externo debe vivir junto a la configuración que define su destino:

TSTypeScriptSolo lectura
cms.external({
  id: 'crm',
  label: 'CRM',
  href: cmsGlobal('links', 'crm'),
});

Una colección de navegación resuelve su índice y entradas desde la colección real:

TSTypeScriptSolo lectura
cms.navigationCollection({
  id: 'solutions',
  label: { es: 'Soluciones', en: 'Solutions' },
  indexPath: '/solutions',
  async entries(locale) {
    return (await solutions.entries(locale)).map((entry) => ({
      id: entry.id,
      label: entry.title,
      path: solutions.path(entry.slug),
    }));
  },
});

No crees una definición falsa para el grupo platform: en el contrato actual, un objeto del JSON ya representa el grupo. La falta de un label localizado propio para grupos es una limitación conocida, no una razón para registrar el grupo como external.

Conectar el árbol al sitio

Importa el JSON en el módulo server-only del sitio y pásalo a createCmsSite:

TSTypeScriptSolo lectura
import type { CmsNavigationTree } from '@veetcuna/cms-next';
import navigation from './navigation.json';
 
cmsSite = createCmsSite({
  projectSlug: '@tenant/website',
  generated: cmsGenerated,
  navigation: navigation as CmsNavigationTree,
  // site, locales, globals y editor…
});

El generador descubre módulos que exportan cms.page(), cms.collection(), cms.external() o cms.navigationCollection(). Al abrir un preview de una página, el SDK resuelve el árbol con el locale y los globales publicados, y lo entrega al panel de navegación del editor.

Limitaciones actuales

  • Los grupos no declaran todavía label localizado, href o metadata en el propio JSON.
  • manager solo reconoce blog.
  • La estructura describe navegación editorial del CMS; no genera automáticamente el header público del website.
  • Cada id debe existir con el mismo tipo en sus definiciones runtime, salvo grupos y managers nativos.
  • Cambiar un id rompe la asociación; para reordenar, mueve la propiedad sin renombrarla.

Cuando evolucione el contrato, migra navigation.json de forma explícita y conserva compatibilidad con los documentos publicados durante el rollout.