01 / Cómo funciona Lupus

Qué hace cada capa

Lupus no sustituye el modelo de contenido, las consultas ni los permisos de Drupal. Organiza su entrega desacoplada sobre Custom Elements y un renderer de página.

Todos los recorridos ↗

Drupal

Entidades, campos, view modes, Views, bloques, rutas y acceso siguen en Drupal. Los displays CE deciden qué presentar de una entidad; el frontend no necesita descubrir sus campos y reconstruir cada ficha desde cero.

Custom Elements

Es el modelo de presentación: un nombre de elemento, props para valores y slots para HTML filtrado u otros elementos. Aporta displays por entidad y view mode, formateadores, procesadores, serialización y metadatos de caché. No implica Shadow DOM ni obliga a registrar Web Components en el navegador.

Lupus CE Renderer

Transforma el contenido principal compatible en una respuesta de página con título, contenido y metadatos. Puede incluir mensajes, breadcrumbs o tareas locales. No convierte cualquier ruta HTML automáticamente: la ruta y sus salidas deben soportar este formato.

Lupus Decoupled + CE API

Lupus empaqueta las integraciones. lupus_decoupled_ce_api activa el renderer para peticiones con prefijo /ce-api, integra redirecciones al frontend y URLs absolutas de archivos. Los submódulos añaden soporte específico para Canvas, Views, bloques o formularios. “Lupus CE” no es una segunda API de datos independiente.

Next.js / React

Nuestro adaptador valida el JSON y traduce nombres CE a componentes React conocidos. Recorre los slots, genera HTML en servidor y añade interacción donde procede. Este adaptador es desarrollo de la POC, no un SDK Next.js automático que aporte Lupus.

Ejemplo real de esta instalación

Inspecciona la ficha: ntt-insight tiene title y href en props y el cuerpo filtrado en slots.body. La misma entidad aparece como ntt-insight-card en la View.

Inspeccionar contrato recibido en servidor
{
  "title": "Experiencias digitales: del contenido al canal",
  "content_format": "json",
  "content": {
    "element": "ntt-insight",
    "props": {
      "href": "/demo/digital-experience",
      "title": "Experiencias digitales: del contenido al canal"
    },
    "slots": {
      "body": "<p>Un portal que conserva contenido, consultas y bloques en Drupal y presenta una experiencia Next.js con una entrega CE común.</p><h2>Un portal, distintas necesidades editoriales</h2><p>Una campaña necesita libertad de composición. Una ficha necesita una estructura clara. Un listado necesita seleccionar contenidos publicados. Cada necesidad conserva su herramienta y comparte el mismo frontal.</p><h2>Una decisión editorial, no una dependencia visual</h2><p>Esta página no tiene árbol ni plantilla Canvas. Título, cuerpo y resumen se editan en el formulario clásico. Los displays CE de Drupal definen su salida completa y su teaser; React implementa ambas presentaciones.</p><h2>Qué conserva Drupal</h2><p>Drupal mantiene campos, formateadores, permisos, traducciones y modos de visualización. Lupus CE Renderer entrega el contenido de la ruta con metadatos; CE API lo expone bajo /ce-api. Next.js valida el contrato y renderiza los elementos conocidos.</p><h2>Qué puedes probar</h2><p>Abre esta ficha y su teaser en Insights. Consulta ambas respuestas en el inspector. No reconstruimos en React la selección de campos o la consulta de la View, aunque los componentes y la interacción siguen siendo trabajo frontend.</p><p><a href=\"/demo/guide/layers\">Explorar la explicación y el ejemplo real</a></p>"
    }
  },
  "metatags": {
    "meta": [
      {
        "name": "title",
        "content": "Experiencias digitales: del contenido al canal | Canvas Lupus POC"
      },
      {
        "name": "description",
        "content": "Un portal que conserva contenido, consultas y bloques en Drupal y presenta una experiencia Next.js con una entrega CE común."
      }
    ],
    "link": [
      {
        "rel": "canonical",
        "href": "https://dev-headless-lupus.pantheonsite.io/demo/digital-experience"
      },
      {
        "rel": "alternate",
        "hreflang": "en",
        "href": "https://dev-headless-lupus.pantheonsite.io/en/demo/digital-experience"
      },
      {
        "rel": "alternate",
        "hreflang": "es",
        "href": "https://dev-headless-lupus.pantheonsite.io/demo/digital-experience"
      }
    ]
  },
  "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