02 / Cómo funciona Lupus

CE API y JSON:API

JSON:API responde a “qué datos tiene este recurso”. CE API responde a “qué presentación compatible entrega Drupal para esta ruta”. La diferencia es dónde se decide la composición, no que una API sea universalmente mejor.

Todos los recorridos ↗

Con JSON:API

Se consultan recursos por tipo y UUID, con atributos, relaciones, filtros, includes y paginación de recursos. El frontend decide consultas, composición y vistas. Es útil para aplicaciones, múltiples canales y datos no ligados a una página. No ejecuta por defecto el display de nuestra View ni define un sistema visual.

Con /ce-api

Se pide /ce-api/demo/insights?page=1. Drupal resuelve la ruta, comprueba acceso, ejecuta la View y entrega elementos de teaser y pager. Next.js no vuelve a formular los filtros de publicación o idioma de esa View; presenta el contrato recibido.

Menos lógica duplicada, no cero frontend

El frontend sigue implementando cada componente, navegación, enlaces de paginación, estados de error y accesibilidad. CE no envía el código React ni convierte bibliotecas Drupal en React. Un elemento nuevo requiere un renderer o componente compatible.

No es una API de escritura universal

La API de página no sustituye operaciones CRUD, búsquedas especializadas o servicios de negocio. Se puede combinar CE para páginas y JSON:API u otras APIs para datos e interacciones. Esta POC no habilita JSON:API: el ejemplo de su URL es ilustrativo, no un endpoint ejecutado aquí.

Ejemplo real de esta instalación

Respuesta real de la segunda página de la View: rows contiene teasers; props.pager conserva totalPages y current. El ejemplo JSON:API de contraste sería GET /jsonapi/node/ntt_insight/{uuid}.

Inspeccionar contrato recibido en servidor
{
  "title": "Ideas que conectan tecnologia y experiencia",
  "content_format": "json",
  "content": {
    "element": "ntt-insights",
    "props": {
      "title": "Ideas que conectan tecnologia y experiencia",
      "viewId": "ntt_demo_insights",
      "displayId": "page_1",
      "rowsWrapper": "",
      "pager": {
        "totalPages": 2,
        "current": 1
      }
    },
    "slots": {
      "rows": [
        {
          "element": "ntt-insight-card",
          "props": {
            "href": "/demo/insights/production-readiness",
            "title": "Formularios e integraciones: responsabilidades claras"
          },
          "slots": {
            "body": "Drupal puede conservar Form API, validación y procesamiento; el frontal necesita integrar el ciclo completo."
          }
        }
      ]
    }
  },
  "metatags": {
    "meta": [],
    "link": []
  },
  "blocks": {
    "sidebar_first": {
      "canvas_lupus_theme_page_title": {
        "element": "drupal-markup",
        "slots": {
          "default": "\n\n"
        }
      },
      "canvas_lupus_theme_powered": {
        "element": "drupal-markup",
        "slots": {
          "default": "<span>Powered by <a href=\"https://www.drupal.org\">Drupal</a></span>"
        }
      }
    },
    "header": {
      "canvas_lupus_theme_site_branding": {
        "element": "drupal-markup",
        "slots": {
          "default": "<img src=\"https://dev-headless-lupus.pantheonsite.io/themes/custom/canvas_lupus_theme/logo.svg\" alt=\"Home\" />\nCanvas Lupus POC"
        }
      }
    },
    "primary_menu": {
      "canvas_lupus_theme_main_menu": {
        "element": "drupal-markup",
        "slots": {
          "default": "\n              <ul>\n              <li>\n        <a href=\"/\" data-drupal-link-system-path=\"&lt;front&gt;\">Home</a>\n              </li>\n        </ul>\n  \n\n"
        }
      }
    },
    "secondary_menu": {
      "canvas_lupus_theme_account_menu": {
        "element": "drupal-markup",
        "slots": {
          "default": "\n              <ul>\n              <li>\n        <a href=\"/user/login\" data-drupal-link-system-path=\"user/login\">Log in</a>\n              </li>\n        </ul>\n  \n\n"
        }
      }
    },
    "highlighted": {
      "canvas_lupus_theme_messages": {
        "element": "drupal-markup",
        "slots": {
          "default": "<div data-drupal-messages-fallback class=\"hidden\"></div>"
        }
      }
    },
    "breadcrumb": {
      "canvas_lupus_theme_breadcrumbs": {
        "element": "drupal-markup",
        "slots": {
          "default": "  <nav aria-labelledby=\"system-breadcrumb\">\n    <h2 id=\"system-breadcrumb\" class=\"visually-hidden\">Breadcrumb</h2>\n    <ol>\n          <li>\n                  <a href=\"/\">Home</a>\n              </li>\n        </ol>\n  </nav>\n"
        }
      }
    }
  }
}

Fuentes de la arquitectura