Lupus Decoupled Drupal

Ready-to-go Decoupled Drupal architecture providing a custom elements API for building headless Drupal sites with Nuxt.js or other JavaScript frontends.

lupus_decoupled
84 sites
35
drupal.org

Install

Drupal 11, 10 v1.4.1
composer require 'drupal/lupus_decoupled:^1.4'
Drupal 9 v1.1.0
composer require 'drupal/lupus_decoupled:^1.1'

Overview

Lupus Decoupled Drupal is a comprehensive decoupled architecture solution that enables Drupal to serve content through a Custom Elements API at /ce-api. It transforms Drupal's content rendering into JSON responses containing custom element definitions that can be consumed by JavaScript frontends like Nuxt.js.

The module provides a complete suite of submodules for handling various Drupal features in a decoupled context, including forms, views, blocks, menus, webforms, contact forms, user authentication, and more. It automatically redirects frontend routes to the configured frontend URL, processes file URLs to be absolute, and handles CORS configuration.

The architecture uses the Custom Elements module ecosystem (custom_elements, lupus_ce_renderer) to convert Drupal render arrays into structured JSON data that represents web components. This enables a clean separation between Drupal as a content backend and modern JavaScript frameworks as the presentation layer.

Features

  • Provides Custom Elements API endpoint at /ce-api that transforms Drupal content into JSON responses
  • Automatic frontend route redirection - redirects Drupal node pages to the configured frontend URL
  • Generates absolute file URLs in API responses for proper asset handling in decoupled frontends
  • CORS configuration for allowing frontend JavaScript to access Drupal APIs from the browser
  • Menu API endpoints integration via rest_menu_items module for serving Drupal menus to frontends
  • Views integration with Custom Elements Page and Block display plugins for rendering views as custom elements
  • Form rendering support - wraps Drupal forms in custom elements for progressive form submissions
  • Contact form integration for serving Drupal contact forms to decoupled frontends
  • Webform module integration for exposing webforms via the custom elements API
  • User authentication forms support (login, password reset) for frontend user authentication flows
  • Layout Builder integration for using Drupal's Layout Builder with custom elements output
  • Block layout integration that adds block regions to API responses
  • Site info REST resource at /api/site-info for exposing configurable site configuration values
  • Schema Metatag/JSON-LD support for structured data in API responses
  • Responsive preview integration for previewing decoupled frontend in Drupal admin
  • API request/response logging integration with REST Log module for debugging
  • Preview provider system for rendering component previews in administrative interfaces
  • Environment variable support (DRUPAL_FRONTEND_BASE_URL) for frontend URL configuration

Use Cases

Building a Nuxt.js frontend for a Drupal site

Use Lupus Decoupled to serve Drupal content to a Nuxt.js frontend. Install the module, configure the frontend base URL, and use the nuxtjs-drupal-ce connector in your Nuxt application. The /ce-api endpoint will serve JSON responses that the Nuxt app can render as Vue components.

Implementing user authentication in a decoupled frontend

Enable lupus_decoupled_user_form to expose Drupal's login and password reset forms. The frontend receives server-rendered form HTML wrapped in custom elements, enabling progressive enhancement while maintaining Drupal's security features.

Creating listing pages with Views

Use lupus_decoupled_views to create listing pages that output custom elements. Add a Custom Elements Page display to your view, configure the custom element name, and the view results will be served as JSON with full pagination support.

Exposing webforms to the frontend

Enable lupus_decoupled_webform to make Drupal webforms accessible via the custom elements API. Users can submit forms on the frontend, and confirmation messages are handled by Drupal's webform system.

Multi-frontend architecture

Configure multiple frontend base URLs using the lupus_decoupled_ce_api.frontend_base_urls container parameter. This allows a single Drupal backend to serve content to multiple frontend applications with proper CORS configuration.

Debugging API responses during development

Enable lupus_decoupled_api_log to log all API requests and responses. Configure REST Log at /admin/config/development/logging/rest_log and investigate logged requests at /admin/reports/rest_log to troubleshoot frontend-backend communication.

Serving site configuration to the frontend

Use lupus_decoupled_site_info to expose site settings like name, slogan, and contact email via /api/site-info. Configure additional values using drush config:edit lupus_decoupled_site_info.settings with the format {config_name}:{config_key}.

Block-based layouts in decoupled sites

Enable lupus_decoupled_block to include block regions in API responses. Place blocks at /admin/structure/block and they will automatically be rendered and included in the 'blocks' property of the API response for the corresponding routes.

Tips

  • Use the project template at https://github.com/drunomics/lupus-decoupled-project for a quick start with pre-configured Drupal + Nuxt.js setup including ddev and Gitpod support.
  • The ?auth=1 query parameter is automatically added when saving nodes to help static-generated frontends fetch fresh content immediately.
  • For theming form elements with clean markup, consider using the lupus-stark theme (drupal/lupus_stark) which removes unnecessary Drupal-specific markup.
  • The API prefix (/ce-api) can be customized via the lupus_decoupled_ce_api.api_prefix container parameter if needed.
  • Enable lupus_decoupled_api_log during development for quick debugging of API requests and responses.
  • When configuring multiple frontends, add additional base URLs to lupus_decoupled_ce_api.frontend_base_urls for proper CORS handling.
  • Custom element names for Views can be overridden in the display settings to match your frontend component naming conventions.
  • The content format (json vs markup) can be configured via the lupus_decoupled_ce_api.content_format parameter.
  • Refer to https://lupus-decoupled.org for comprehensive documentation and tutorials.

Technical Details

Admin Pages 1
Lupus Decoupled Drupal Settings /admin/config/system/lupus-decoupled/settings

Configure the connection between your Drupal backend and the decoupled frontend. Set the frontend base URL, control frontend route redirection behavior, and configure file URL handling.

Permissions 1
Use API operation link

Allows users to access the 'View API Output' operation link on node entities, which shows the JSON API response for that node.

Hooks 4
hook_trusted_redirect_hosts_alter

Adds configured frontend base URLs to the trusted redirect hosts, allowing Drupal to redirect to the frontend without security warnings.

hook_form_node_form_alter

Alters node forms to add custom submit handlers for proper frontend integration. Adds ?auth=1 query parameter after saving nodes and handles preview redirection.

hook_entity_operation

Adds 'View API Output' operation link to node entities for users with 'use api operation link' permission.

hook_lupus_decoupled_views_page_alter

Allows altering the custom element representing a Views page display before rendering.

Troubleshooting 7
Frontend routes are not redirecting to the frontend URL

Ensure the Frontend Base URL is configured at /admin/config/system/lupus-decoupled/settings and the 'View content on decoupled frontend' checkbox is enabled. Also verify the DRUPAL_FRONTEND_BASE_URL environment variable is not set to an empty value.

CORS errors when frontend JavaScript accesses Drupal APIs

Ensure lupus_decoupled_cors submodule is enabled. Check that the frontend URL is correctly configured, as CORS headers are based on the configured frontend base URLs.

Images and files showing broken URLs in the frontend

Verify that 'Generate custom-elements API responses with absolute file URLs' is enabled in the settings. If using a CDN or custom file hosting, configure Drupal's 'file_public_base_url' setting in settings.php.

Forms not submitting correctly from the frontend

Ensure the frontend is configured to forward POST requests to the backend. For Nuxt.js, verify the drupalFormHandler server middleware is properly configured in the nuxtjs-drupal-ce connector.

Preview not showing the correct page

Enable lupus_decoupled_responsive_preview and ensure the preview path processor is working. Check that the frontend handles the preview URL parameters correctly.

Views not rendering as custom elements

Ensure you're using the 'Custom Elements Page' or 'Custom Elements Block' display type, and the 'Custom Elements' style plugin. Verify the lupus_decoupled_views submodule is enabled.

Environment variable DRUPAL_FRONTEND_BASE_URL not being used

The environment variable must be set before Drupal bootstraps. Verify it's exported in your shell environment or set in your web server configuration (e.g., .htaccess, nginx config, or Docker environment).

Security Notes 5
  • CORS configuration is automatic based on configured frontend URLs - avoid adding untrusted domains to the frontend URL configuration.
  • The trusted_redirect module integration ensures only configured frontend hosts are allowed as redirect destinations.
  • User authentication forms maintain Drupal's security features - credentials are processed server-side, not in the frontend JavaScript.
  • The 'use api operation link' permission should only be granted to trusted users who need to debug API output.
  • When exposing site configuration via lupus_decoupled_site_info, only include non-sensitive values - avoid exposing API keys or credentials.