{"jsonapi":{"version":"1.0","meta":{"links":{"self":{"href":"http:\/\/jsonapi.org\/format\/1.0\/"}}}},"data":[{"type":"node--project_module","id":"bafcd628-5f1b-4a3f-9a69-4bd47ad11486","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486?resourceVersion=id%3A21791966"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3584023,"status":true,"title":"SAML Authentication Restrict to OU","created":"2026-04-09T21:37:52+00:00","changed":"2026-04-09T21:37:52+00:00","moderation_state":null,"body":{"value":"\u003Cp\u003E\u003Cstrong\u003ESAML Authentication Restrict to OU\u003C\/strong\u003E provides a security layer for the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/samlauth\u0022 target=\u0022_blank\u0022\u003ESAML Authentication\u003C\/a\u003E module by restricting site access based on Organizational Unit (OU) attributes sent by the Identity Provider (IdP).\u003C\/p\u003E\r\n\r\n\u003Cp\u003EThis module is specifically designed for Enterprise environments using Active Directory, allowing administrators to limit site access to specific departments or groups within a large organization without the overhead of managing individual Drupal roles for every user.\u003C\/p\u003E\r\n\r\n\u003Ch2\u003EFeatures\u003C\/h2\u003E\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003ERestrict Login Toggle:\u003C\/strong\u003E A master switch that allows you to enable or disable the restriction logic globally without losing your settings.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EDistinguished Name (DN) Parsing:\u003C\/strong\u003E Automatically extracts multiple OU values from complex DN strings commonly sent by Active Directory (e.g., \u003Ccode\u003ECN=user,OU=Marketing,OU=Users...\u003C\/code\u003E).\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EStrict Mode:\u003C\/strong\u003E Optionally require that a user belongs to \u003Cstrong\u003Eall\u003C\/strong\u003E listed OUs rather than just one (AND vs OR logic).\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003ECustomizable Access Denied Message:\u003C\/strong\u003E Control the exact message shown to rejected users, with support for basic HTML markup to ensure visibility.\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Ch2\u003ERequirements\u003C\/h2\u003E\r\n\u003Cp\u003EThis module requires the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/samlauth\u0022 target=\u0022_blank\u0022\u003ESAML Authentication\u003C\/a\u003E module.\u003C\/p\u003E\r\n\r\n\u003Ch2\u003EInstallation\u003C\/h2\u003E\r\n\u003Cp\u003E\r\n  Install as you would normally install a contributed Drupal module. For further information, see \u003Ca href=\u0022https:\/\/www.drupal.org\/docs\/extending-drupal\/installing-drupal-modules\u0022 target=\u0022_blank\u0022\u003EInstalling Drupal Modules\u003C\/a\u003E.\r\n\u003C\/p\u003E\r\n\r\n\u003Ch2\u003EConfiguration\u003C\/h2\u003E\r\n\u003Cp\u003EThe configuration form is located at:\u003C\/p\u003E\r\n\u003Cpre\u003E\u003Ccode\u003E\/admin\/config\/people\/saml-restrict\u003C\/code\u003E\u003C\/pre\u003E\r\n\r\n\u003Cp\u003EFrom the configuration form you can:\u003C\/p\u003E\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003ERestrict Login to OUs:\u003C\/strong\u003E Enable the master toggle to begin enforcing restrictions.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003ESAML Attribute Name:\u003C\/strong\u003E Set this to the attribute containing your OU data. In most AD setups, this is \u003Ccode\u003Edn\u003C\/code\u003E.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EAllowed OUs:\u003C\/strong\u003E Enter the names of authorized OUs, one per line (e.g., Staff, Faculty, Marketing). This check is case-insensitive to ensure reliable matching across directory updates. Do not include \u0022ou=\u0022 prefixes.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EStrict Mode:\u003C\/strong\u003E Check this if a user must be a member of every OU listed to gain access.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EAccess Denied Message:\u003C\/strong\u003E Customize the message displayed to users who are rejected. Basic HTML like \u003Ccode\u003E\u0026lt;strong\u0026gt;\u003C\/code\u003E and \u003Ccode\u003E\u0026lt;p\u0026gt;\u003C\/code\u003E is supported.\u003C\/li\u003E\r\n\u003C\/ul\u003E","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003E\u003Cstrong\u003ESAML Authentication Restrict to OU\u003C\/strong\u003E provides a security layer for the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/samlauth\u0022 rel=\u0022nofollow\u0022\u003ESAML Authentication\u003C\/a\u003E module by restricting site access based on Organizational Unit (OU) attributes sent by the Identity Provider (IdP).\u003C\/p\u003E\n\u003Cp\u003EThis module is specifically designed for Enterprise environments using Active Directory, allowing administrators to limit site access to specific departments or groups within a large organization without the overhead of managing individual Drupal roles for every user.\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022features\u0022\u003EFeatures\u003C\/h2\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003ERestrict Login Toggle:\u003C\/strong\u003E A master switch that allows you to enable or disable the restriction logic globally without losing your settings.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EDistinguished Name (DN) Parsing:\u003C\/strong\u003E Automatically extracts multiple OU values from complex DN strings commonly sent by Active Directory (e.g., \u003Ccode\u003ECN=user,OU=Marketing,OU=Users...\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EStrict Mode:\u003C\/strong\u003E Optionally require that a user belongs to \u003Cstrong\u003Eall\u003C\/strong\u003E listed OUs rather than just one (AND vs OR logic).\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ECustomizable Access Denied Message:\u003C\/strong\u003E Control the exact message shown to rejected users, with support for basic HTML markup to ensure visibility.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022requirements\u0022\u003ERequirements\u003C\/h2\u003E\n\u003Cp\u003EThis module requires the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/samlauth\u0022 rel=\u0022nofollow\u0022\u003ESAML Authentication\u003C\/a\u003E module.\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022installation\u0022\u003EInstallation\u003C\/h2\u003E\n\u003Cp\u003E\n  Install as you would normally install a contributed Drupal module. For further information, see \u003Ca href=\u0022https:\/\/www.drupal.org\/docs\/extending-drupal\/installing-drupal-modules\u0022 rel=\u0022nofollow\u0022\u003EInstalling Drupal Modules\u003C\/a\u003E.\n\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022configuration\u0022\u003EConfiguration\u003C\/h2\u003E\n\u003Cp\u003EThe configuration form is located at:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\/admin\/config\/people\/saml-restrict\u003C\/code\u003E\u003C\/pre\u003E\u003Cp\u003EFrom the configuration form you can:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003ERestrict Login to OUs:\u003C\/strong\u003E Enable the master toggle to begin enforcing restrictions.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ESAML Attribute Name:\u003C\/strong\u003E Set this to the attribute containing your OU data. In most AD setups, this is \u003Ccode\u003Edn\u003C\/code\u003E.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EAllowed OUs:\u003C\/strong\u003E Enter the names of authorized OUs, one per line (e.g., Staff, Faculty, Marketing). This check is case-insensitive to ensure reliable matching across directory updates. Do not include \u0022ou=\u0022 prefixes.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EStrict Mode:\u003C\/strong\u003E Check this if a user must be a member of every OU listed to gain access.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EAccess Denied Message:\u003C\/strong\u003E Customize the message displayed to users who are rejected. Basic HTML like \u003Ccode\u003E\u0026lt;strong\u0026gt;\u003C\/code\u003E and \u003Ccode\u003E\u0026lt;p\u0026gt;\u003C\/code\u003E is supported.\u003C\/li\u003E\n\u003C\/ul\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"samlauth_restrict_to_ou","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"1d1ccd47-550f-4b20-a1ed-909c6a7e67b5","meta":{"drupal_internal__target_id":2728387}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/uid?resourceVersion=id%3A21791966"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/relationships\/uid?resourceVersion=id%3A21791966"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/field_development_status?resourceVersion=id%3A21791966"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/relationships\/field_development_status?resourceVersion=id%3A21791966"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/field_maintenance_status?resourceVersion=id%3A21791966"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/relationships\/field_maintenance_status?resourceVersion=id%3A21791966"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"24830916-5c07-4446-89de-960915f87bf6","meta":{"drupal_internal__target_id":199}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/field_module_categories?resourceVersion=id%3A21791966"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/relationships\/field_module_categories?resourceVersion=id%3A21791966"}}},"field_project_images":{"data":[{"type":"file--file","id":"5e96b2d0-b667-4be6-bc65-403fa4b24fc0","meta":{"alt":"Image of samlauth_restrict_to_ou before toggled on.","title":null,"width":1518,"height":560,"drupal_internal__target_id":1461137}},{"type":"file--file","id":"b744b363-0952-4e90-bd44-63132a47ba0e","meta":{"alt":"Image of samlauth_restrict_to_ou after toggled on with example settings.","title":null,"width":2226,"height":1792,"drupal_internal__target_id":1461138}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/field_project_images?resourceVersion=id%3A21791966"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/bafcd628-5f1b-4a3f-9a69-4bd47ad11486\/relationships\/field_project_images?resourceVersion=id%3A21791966"}}}}},{"type":"node--project_module","id":"9b7fe5c8-2478-4045-abe4-f939b50cd450","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450?resourceVersion=id%3A21791965"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3584022,"status":true,"title":"kwtSMS","created":"2026-04-09T21:23:15+00:00","changed":"2026-04-09T21:23:15+00:00","moderation_state":null,"body":{"value":"SMS gateway integration with kwtsms.com for Drupal 10.3+ and 11. Adds OTP login, two-factor authentication, password reset via SMS, user notifications, and Commerce order alerts through the kwtSMS API.\r\n                                                                                                                                                                                                                                                \u003Ch3 id=\u0022module-project--features\u0022\u003EFeatures\u003C\/h3\u003E\r\n                                                                                                                                                                                                                                              \r\n  \u003Cstrong\u003EAuthentication\u003C\/strong\u003E\r\n  \u003Cul\u003E\r\n  \u003Cli\u003EOTP login: SMS as primary login or second factor (2FA), configurable per role\u003C\/li\u003E\r\n  \u003Cli\u003EPassword reset via SMS: SMS only, Email + SMS, or Email only\u003C\/li\u003E                                                                                                                                                                       \r\n  \u003Cli\u003ERate limiting per phone and IP, lockout after failed attempts\u003C\/li\u003E                                                                                                                                                                      \r\n  \u003C\/ul\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     \r\n  \u003Cstrong\u003ENotifications\u003C\/strong\u003E                                                                                                                                                                                                              \r\n  \u003Cul\u003E\r\n  \u003Cli\u003EUser registration SMS to customers and admins\u003C\/li\u003E\r\n  \u003Cli\u003ECommerce: order placed, status updates, payment confirmations\u003C\/li\u003E                                                                                                                                                                      \r\n  \u003Cli\u003ECommerce: low stock alerts, shipping updates, abandoned cart reminders\u003C\/li\u003E                                                                                                                                                             \r\n  \u003C\/ul\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       \u003Cstrong\u003EAdmin UI (7 tabs)\u003C\/strong\u003E                                                                                                                                                                                                            \u003Cul\u003E\r\n  \u003Cli\u003EDashboard: status overview, SMS stats, 30-day volume chart\u003C\/li\u003E                                                                                                                                                                         \r\n  \u003Cli\u003ESettings: global on\/off, test mode, country code, sender ID, OTP\/2FA config\u003C\/li\u003E                                                                                                                                                        \r\n  \u003Cli\u003EGateway: API login\/logout, balance, sender IDs, coverage, test SMS\u003C\/li\u003E                                                                                                                                                                 \r\n  \u003Cli\u003ETemplates: multilingual EN\/AR message templates with Drupal Token support\u003C\/li\u003E                                                                                                                                                          \r\n  \u003Cli\u003EIntegrations: Commerce event toggles\u003C\/li\u003E                                                                                                                                                                                               \r\n  \u003Cli\u003ELogs: filterable SMS log with CSV export\u003C\/li\u003E                                                                                                                                                                                           \r\n  \u003Cli\u003EHelp: setup guide and support links\u003C\/li\u003E                                                                                                                                                                                                \r\n  \u003C\/ul\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     \r\n  \u003Cstrong\u003EDeveloper\u003C\/strong\u003E                                                                                                                                                                                                                  \r\n  \u003Cul\u003E\r\n  \u003Cli\u003EEvents for module integration: kwtsms.otp_request and kwtsms.sms_send\u003C\/li\u003E\r\n  \u003Cli\u003ESMS Framework v2 gateway plugin (bridge submodule)\u003C\/li\u003E                                                                                                                                                                                 \r\n  \u003Cli\u003EPhone normalization with Arabic\/Hindi digit support\u003C\/li\u003E                                                                                                                                                                                \r\n  \u003Cli\u003EMessage cleaning: strips emoji, HTML, hidden Unicode\u003C\/li\u003E                                                                                                                                                                               \r\n  \u003Cli\u003EBulk sending with 200\/batch and ERR013 backoff\u003C\/li\u003E                                                                                                                                                                                     \r\n  \u003Cli\u003ELog retention policy with configurable days\u003C\/li\u003E                                                                                                                                                                                        \r\n  \u003C\/ul\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       \u003Ch3 id=\u0022module-project--post-installation\u0022\u003EPost-Installation\u003C\/h3\u003E                                                                                                                                                                             \r\n  Navigate to \u003Cstrong\u003EAdmin \u003E Configuration \u003E kwtSMS\u003C\/strong\u003E (\/admin\/config\/kwtsms):                                                                                                                                                           \u003Col\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EGateway tab:\u003C\/strong\u003E Enter your kwtSMS API username and password, click Login\u003C\/li\u003E                                                                                                                                             \r\n  \u003Cli\u003E\u003Cstrong\u003ESettings tab:\u003C\/strong\u003E Select your sender ID and default country code, enable SMS sending\u003C\/li\u003E                                                                                                                                  \r\n  \u003Cli\u003E\u003Cstrong\u003ETemplates tab:\u003C\/strong\u003E Customize message text for each notification type (English and Arabic)\u003C\/li\u003E                                                                                                                             \r\n  \u003Cli\u003E\u003Cstrong\u003ESettings \u003E Authentication:\u003C\/strong\u003E Configure OTP login mode and password reset mode\u003C\/li\u003E                                                                                                                                       \r\n  \u003C\/ol\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       For Commerce notifications, enable the kwtsms_commerce submodule and configure toggles on the Integrations tab.                                                                                                                               \r\n  \u003Ch3 id=\u0022module-project--additional-requirements\u0022\u003EAdditional Requirements\u003C\/h3\u003E                                                                                                                                                               \r\n\r\n  \u003Cul\u003E                                                                                                                                                                                                                                          \u003Cli\u003EA \u003Ca href=\u0022https:\/\/www.kwtsms.com\u0022\u003EkwtSMS.com\u003C\/a\u003E account with API access\u003C\/li\u003E\r\n  \u003Cli\u003EPHP 8.2+\u003C\/li\u003E                                                                                                                                                                                                                           \r\n  \u003C\/ul\u003E                                                                                                                                                                                                                                         \r\n  \u003Ch3 id=\u0022module-project--recommended-libraries\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E                                                                                                                                                           \r\n  \r\n  \u003Cul\u003E\r\n  \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/commerce\u0022\u003EDrupal Commerce\u003C\/a\u003E: Enable kwtsms_commerce submodule for order SMS notifications\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/smsframework\u0022\u003ESMS Framework\u003C\/a\u003E: Enable kwtsms_smsframework bridge to use kwtSMS as an SMS Framework gateway\u003C\/li\u003E                                                                               \r\n  \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/token\u0022\u003EToken\u003C\/a\u003E: Adds a token browser UI for SMS template editing\u003C\/li\u003E                                                                                                                         \r\n  \u003C\/ul\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       \u003Ch3 id=\u0022module-project--similar-projects\u0022\u003ESimilar projects\u003C\/h3\u003E                                                                                                                                                                               \r\n  \u003Cul\u003E                                                                                                                                                                                                                                        \r\n  \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/smsframework\u0022\u003ESMS Framework\u003C\/a\u003E: Generic SMS gateway abstraction. kwtSMS provides a dedicated, opinionated integration with built-in OTP, 2FA, templates, and Commerce support out of the box. A   bridge submodule is included for SMS Framework interoperability.\u003C\/li\u003E                                                                                                                                                                        \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/tfa\u0022\u003ETFA\u003C\/a\u003E: General two-factor authentication. kwtSMS provides SMS-specific 2FA with phone normalization, rate limiting, and anti-enumeration built in.\u003C\/li\u003E\r\n  \u003C\/ul\u003E                                                                                                                                                                                                                                         \r\n  \u003Ch3 id=\u0022module-project--support\u0022\u003ESupporting this Module\u003C\/h3\u003E                                                                                                                                                                                  \r\n  \u003Cul\u003E                                                                                                                                                                                                                                        \r\n  \u003Cli\u003ESupport portal: \u003Ca href=\u0022https:\/\/www.kwtsms.com\/support.html\u0022\u003Ekwtsms.com\/support\u003C\/a\u003E\u003C\/li\u003E\r\n  \u003Cli\u003EFAQ: \u003Ca href=\u0022https:\/\/www.kwtsms.com\/faq\/\u0022\u003Ekwtsms.com\/faq\u003C\/a\u003E\u003C\/li\u003E                                                                                                                                                                        \u003C\/ul\u003E","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003ESMS gateway integration with kwtsms.com for Drupal 10.3+ and 11. Adds OTP login, two-factor authentication, password reset via SMS, user notifications, and Commerce order alerts through the kwtSMS API.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--features-01\u0022\u003EFeatures\u003C\/h3\u003E\n\u003Cp\u003E  \u003Cstrong\u003EAuthentication\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EOTP login: SMS as primary login or second factor (2FA), configurable per role\u003C\/li\u003E\n\u003Cli\u003EPassword reset via SMS: SMS only, Email + SMS, or Email only\u003C\/li\u003E\n\u003Cli\u003ERate limiting per phone and IP, lockout after failed attempts\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E  \u003Cstrong\u003ENotifications\u003C\/strong\u003E                                                                                                                                                                                                              \u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EUser registration SMS to customers and admins\u003C\/li\u003E\n\u003Cli\u003ECommerce: order placed, status updates, payment confirmations\u003C\/li\u003E\n\u003Cli\u003ECommerce: low stock alerts, shipping updates, abandoned cart reminders\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       \u003Cstrong\u003EAdmin UI (7 tabs)\u003C\/strong\u003E\n\u003C\/p\u003E\u003Cul\u003E\n\u003Cli\u003EDashboard: status overview, SMS stats, 30-day volume chart\u003C\/li\u003E\n\u003Cli\u003ESettings: global on\/off, test mode, country code, sender ID, OTP\/2FA config\u003C\/li\u003E\n\u003Cli\u003EGateway: API login\/logout, balance, sender IDs, coverage, test SMS\u003C\/li\u003E\n\u003Cli\u003ETemplates: multilingual EN\/AR message templates with Drupal Token support\u003C\/li\u003E\n\u003Cli\u003EIntegrations: Commerce event toggles\u003C\/li\u003E\n\u003Cli\u003ELogs: filterable SMS log with CSV export\u003C\/li\u003E\n\u003Cli\u003EHelp: setup guide and support links\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E  \u003Cstrong\u003EDeveloper\u003C\/strong\u003E                                                                                                                                                                                                                  \u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EEvents for module integration: kwtsms.otp_request and kwtsms.sms_send\u003C\/li\u003E\n\u003Cli\u003ESMS Framework v2 gateway plugin (bridge submodule)\u003C\/li\u003E\n\u003Cli\u003EPhone normalization with Arabic\/Hindi digit support\u003C\/li\u003E\n\u003Cli\u003EMessage cleaning: strips emoji, HTML, hidden Unicode\u003C\/li\u003E\n\u003Cli\u003EBulk sending with 200\/batch and ERR013 backoff\u003C\/li\u003E\n\u003Cli\u003ELog retention policy with configurable days\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--post-installation-01\u0022\u003EPost-Installation\u003C\/h3\u003E\n\u003Cp\u003E  Navigate to \u003Cstrong\u003EAdmin \u0026gt; Configuration \u0026gt; kwtSMS\u003C\/strong\u003E (\/admin\/config\/kwtsms):\n\u003C\/p\u003E\u003Col\u003E\n\u003Cli\u003E\u003Cstrong\u003EGateway tab:\u003C\/strong\u003E Enter your kwtSMS API username and password, click Login\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ESettings tab:\u003C\/strong\u003E Select your sender ID and default country code, enable SMS sending\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ETemplates tab:\u003C\/strong\u003E Customize message text for each notification type (English and Arabic)\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ESettings \u0026gt; Authentication:\u003C\/strong\u003E Configure OTP login mode and password reset mode\u003C\/li\u003E\n\u003C\/ol\u003E\n\u003Cp\u003E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       For Commerce notifications, enable the kwtsms_commerce submodule and configure toggles on the Integrations tab.                                                                                                                               \u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--additional-requirements-01\u0022\u003EAdditional Requirements\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003EA \u003Ca href=\u0022https:\/\/www.kwtsms.com\u0022 rel=\u0022nofollow\u0022\u003EkwtSMS.com\u003C\/a\u003E account with API access\u003C\/li\u003E\n\u003Cli\u003EPHP 8.2+\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--recommended-libraries-01\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/commerce\u0022 rel=\u0022nofollow\u0022\u003EDrupal Commerce\u003C\/a\u003E: Enable kwtsms_commerce submodule for order SMS notifications\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/smsframework\u0022 rel=\u0022nofollow\u0022\u003ESMS Framework\u003C\/a\u003E: Enable kwtsms_smsframework bridge to use kwtSMS as an SMS Framework gateway\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/token\u0022 rel=\u0022nofollow\u0022\u003EToken\u003C\/a\u003E: Adds a token browser UI for SMS template editing\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--similar-projects-01\u0022\u003ESimilar projects\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/smsframework\u0022 rel=\u0022nofollow\u0022\u003ESMS Framework\u003C\/a\u003E: Generic SMS gateway abstraction. kwtSMS provides a dedicated, opinionated integration with built-in OTP, 2FA, templates, and Commerce support out of the box. A   bridge submodule is included for SMS Framework interoperability.\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/tfa\u0022 rel=\u0022nofollow\u0022\u003ETFA\u003C\/a\u003E: General two-factor authentication. kwtSMS provides SMS-specific 2FA with phone normalization, rate limiting, and anti-enumeration built in.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--support-01\u0022\u003ESupporting this Module\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003ESupport portal: \u003Ca href=\u0022https:\/\/www.kwtsms.com\/support.html\u0022 rel=\u0022nofollow\u0022\u003Ekwtsms.com\/support\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003EFAQ: \u003Ca href=\u0022https:\/\/www.kwtsms.com\/faq\/\u0022 rel=\u0022nofollow\u0022\u003Ekwtsms.com\/faq\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"kwtsms","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"432f3d0c-a2cc-4483-95a6-5cfdc553f0a9","meta":{"drupal_internal__target_id":3867520}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/uid?resourceVersion=id%3A21791965"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/relationships\/uid?resourceVersion=id%3A21791965"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/field_development_status?resourceVersion=id%3A21791965"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/relationships\/field_development_status?resourceVersion=id%3A21791965"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/field_maintenance_status?resourceVersion=id%3A21791965"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/relationships\/field_maintenance_status?resourceVersion=id%3A21791965"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"0cd80c8e-5c20-43a8-aa3e-ec701007d443","meta":{"drupal_internal__target_id":195}},{"type":"taxonomy_term--module_categories","id":"3322058a-a158-4806-ac5b-9bcabc95edac","meta":{"drupal_internal__target_id":185}},{"type":"taxonomy_term--module_categories","id":"8117d8b0-f171-414d-b384-0bafa81bef9f","meta":{"drupal_internal__target_id":193}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/field_module_categories?resourceVersion=id%3A21791965"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/relationships\/field_module_categories?resourceVersion=id%3A21791965"}}},"field_project_images":{"data":[{"type":"file--file","id":"f4170e4d-baa3-4141-9965-e0f499a797e2","meta":{"alt":"Dashboard \u0026 Analytics","title":null,"width":1400,"height":1259,"drupal_internal__target_id":1461132}},{"type":"file--file","id":"b17f4fd8-1cf5-46c0-9c76-9021b66eb96c","meta":{"alt":"Settings - SMS Notifications","title":null,"width":1400,"height":2698,"drupal_internal__target_id":1461133}},{"type":"file--file","id":"41c97a38-fa40-497b-bdb1-7ec003d0a06f","meta":{"alt":"Gateway Settings","title":null,"width":1400,"height":1347,"drupal_internal__target_id":1461134}},{"type":"file--file","id":"37aa9770-eb7b-42d5-847e-980b233ee31c","meta":{"alt":"Templates","title":null,"width":1400,"height":1200,"drupal_internal__target_id":1461135}},{"type":"file--file","id":"1c230f9a-5369-49eb-9ef0-57ad8cffe261","meta":{"alt":"Logs","title":null,"width":1400,"height":1969,"drupal_internal__target_id":1461136}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/field_project_images?resourceVersion=id%3A21791965"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9b7fe5c8-2478-4045-abe4-f939b50cd450\/relationships\/field_project_images?resourceVersion=id%3A21791965"}}}}},{"type":"node--project_module","id":"e81f0322-3ed5-4dc2-ab78-9b38e46e60b0","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0?resourceVersion=id%3A21791946"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3584008,"status":true,"title":"Layout Builder Block Copy","created":"2026-04-09T19:47:09+00:00","changed":"2026-04-09T20:06:40+00:00","moderation_state":null,"body":{"value":"Adds a \u0022Copy block\u0022 action to Layout Builder, allowing content editors to duplicate any block within the same section. Copied blocks are fully  independent \u2014 editing a copy never affects the original.         \r\n                                                                     \r\nBuilt specifically for Drupal 10.3+ and Drupal 11. No contrib  dependencies                         beyond Drupal core.                                                \r\n                                                                     \r\n  \u003Ch3 id=\u0022module-project--features\u0022\u003EFeatures\u003C\/h3\u003E                    \r\n  \u003Cul\u003E                                                               \r\n  \u003Cli\u003ECopy any inline block in Layout Builder with a single click\u003C\/li\u003E                                                         \r\n  \u003Cli\u003EDeep clone \u2014 creates a new independent block_content entity, not a reference copy\u003C\/li\u003E                                          \r\n  \u003Cli\u003EEditing a copied block never affects the original (fixes the core issue with similar modules)\u003C\/li\u003E                              \r\n  \u003Cli\u003EWorks correctly with \r\n\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/quick_node_clone\u0022\u003EQuick Node Clone\u003C\/a\u003E \u2014 cloned nodes get independent block entities\u003C\/li\u003E\r\n  \u003Cli\u003ENo dependency on Entity Clone or any other contrib module\u003C\/li\u003E \r\n  \u003C\/ul\u003E                                                              \r\n  \r\n  \u003Ch3 id=\u0022module-project--post-installation\u0022\u003EPost-Installation\u003C\/h3\u003E  \r\n  Enable the module. In Layout Builder edit mode, each block\u0027s contextual menu will show a \u0022Copy block\u0022 action. The copy is inserted into the same section and region immediately below the original.                \r\n                                                                     \r\n  \u003Ch3 id=\u0022module-project--additional-requirements\u0022\u003EAdditional        \r\n  Requirements\u003C\/h3\u003E\r\n  Requires Drupal 10.3 or higher. The core Layout Builder module must be enabled.                                                       \r\n  \r\n  \u003Ch3 id=\u0022module-project--similar-projects\u0022\u003ESimilar projects\u003C\/h3\u003E    \r\n  \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/layout_builder_block_clone\u0022\u003ELayout Builder Block Clone\u003C\/a\u003E supports Drupal 8\/9\/10 and is in maintenance-only mode. It has known issues with shallow cloning (copied blocks share the same entity), Drupal 11 incompatibility, and conflicts with Entity Clone. If you need support for Drupal 10.2 or earlier, use that module instead. This module exists to solve those problems cleanly for modern Drupal.","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003EAdds a \u0022Copy block\u0022 action to Layout Builder, allowing content editors to duplicate any block within the same section. Copied blocks are fully  independent \u2014 editing a copy never affects the original.         \u003C\/p\u003E\n\u003Cp\u003EBuilt specifically for Drupal 10.3+ and Drupal 11. No contrib  dependencies                         beyond Drupal core.                                                \u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--features-01\u0022\u003EFeatures\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003ECopy any inline block in Layout Builder with a single click\u003C\/li\u003E\n\u003Cli\u003EDeep clone \u2014 creates a new independent block_content entity, not a reference copy\u003C\/li\u003E\n\u003Cli\u003EEditing a copied block never affects the original (fixes the core issue with similar modules)\u003C\/li\u003E\n\u003Cli\u003EWorks correctly with\u003Cbr\u003E\n\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/quick_node_clone\u0022 rel=\u0022nofollow\u0022\u003EQuick Node Clone\u003C\/a\u003E \u2014 cloned nodes get independent block entities\u003C\/li\u003E\n\u003Cli\u003ENo dependency on Entity Clone or any other contrib module\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--post-installation-01\u0022\u003EPost-Installation\u003C\/h3\u003E\n\u003Cp\u003E  Enable the module. In Layout Builder edit mode, each block\u0027s contextual menu will show a \u0022Copy block\u0022 action. The copy is inserted into the same section and region immediately below the original.                \u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--additional-requirements-01\u0022\u003EAdditional\n  Requirements\u003C\/h3\u003E\n\u003Cp\u003E  Requires Drupal 10.3 or higher. The core Layout Builder module must be enabled.                                                       \u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--similar-projects-01\u0022\u003ESimilar projects\u003C\/h3\u003E\n\u003Cp\u003E  \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/layout_builder_block_clone\u0022 rel=\u0022nofollow\u0022\u003ELayout Builder Block Clone\u003C\/a\u003E supports Drupal 8\/9\/10 and is in maintenance-only mode. It has known issues with shallow cloning (copied blocks share the same entity), Drupal 11 incompatibility, and conflicts with Entity Clone. If you need support for Drupal 10.2 or earlier, use that module instead. This module exists to solve those problems cleanly for modern Drupal.\u003C\/p\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"layout_builder_block_copy","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"a8b50ba6-d27b-42b0-9684-61cbd6a16e05","meta":{"drupal_internal__target_id":3834672}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/uid?resourceVersion=id%3A21791946"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/relationships\/uid?resourceVersion=id%3A21791946"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/field_development_status?resourceVersion=id%3A21791946"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/relationships\/field_development_status?resourceVersion=id%3A21791946"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/field_maintenance_status?resourceVersion=id%3A21791946"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/relationships\/field_maintenance_status?resourceVersion=id%3A21791946"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"86237004-3801-40cf-96b5-fe7d60efccb5","meta":{"drupal_internal__target_id":187}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/field_module_categories?resourceVersion=id%3A21791946"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/relationships\/field_module_categories?resourceVersion=id%3A21791946"}}},"field_project_images":{"data":[],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/field_project_images?resourceVersion=id%3A21791946"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/e81f0322-3ed5-4dc2-ab78-9b38e46e60b0\/relationships\/field_project_images?resourceVersion=id%3A21791946"}}}}},{"type":"node--project_module","id":"6ede9dbb-db4a-4bf3-a538-276e5fd20620","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620?resourceVersion=id%3A21791945"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3584006,"status":true,"title":"Migrate Forward Draft","created":"2026-04-09T19:36:11+00:00","changed":"2026-04-09T19:36:11+00:00","moderation_state":null,"body":{"value":"\u003Cp\u003EWhen you import or update content with \u003Cstrong\u003EMigrate\u003C\/strong\u003E, Drupal usually writes to the \u003Cstrong\u003Edefault revision\u003C\/strong\u003E (what visitors see as published). On sites using \u003Cstrong\u003Eworkflows and content moderation\u003C\/strong\u003E, editors often save a \u003Cstrong\u003Enewer draft revision\u003C\/strong\u003E that is not the default\u2014a \u201cforward\u201d draft. If that draft is ahead of the live revision, a \u003Cstrong\u003Emigration rerun\u003C\/strong\u003E can leave the published node correct while the draft still has outdated values for fields the migration owns, or create confusing revision history. \u003Cstrong\u003EMigrate Forward Draft\u003C\/strong\u003E provides a \u003Cstrong\u003Emigrate destination plugin\u003C\/strong\u003E that, on update, captures that forward draft before the migration saves, updates the default revision from your migration, then saves a \u003Cstrong\u003Enew non-default revision\u003C\/strong\u003E that carries the editor\u2019s work forward. You can \u003Cstrong\u003Eoverlay selected fields\u003C\/strong\u003E from the freshly imported default onto that replayed draft so drafts stay aligned with your source where you want that.\u003C\/p\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--features\u0022\u003EFeatures\u003C\/h3\u003E\r\n\r\n\u003Cp\u003E\u003Cstrong\u003EBasic functionality:\u003C\/strong\u003E A Migrate destination that is aware of \u201cforward\u201d (newer non-default) draft revisions and replays them after the default revision is updated by an import.\u003C\/p\u003E\r\n\r\n\u003Cp\u003E\u003Cstrong\u003EUnique behavior:\u003C\/strong\u003E\u003C\/p\u003E\r\n\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EForward-draft detection\u003C\/strong\u003E before the migration updates the entity.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EReplay as a new non-default revision\u003C\/strong\u003E after the default is updated, so moderation and revision workflows stay meaningful.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003E\u003Ccode\u003Eforward_revision_overwrite_properties\u003C\/code\u003E\u003C\/strong\u003E\u2014choose which properties (often fields) to copy from the new default onto the replayed draft (e.g. migration-owned titles or IDs) while other draft values stay editor-owned.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003E\u003Ccode\u003Emigration_sync\u003C\/code\u003E\u003C\/strong\u003E (default matches core)\u2014controls \u003Ccode\u003EsetSyncing(TRUE)\u003C\/code\u003E on the \u003Cem\u003Emain\u003C\/em\u003E migrate save; the forward-draft \u003Cem\u003Ereplay\u003C\/em\u003E save does not use syncing, which matters for content moderation and custom subscribers.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EDerivative plugins\u003C\/strong\u003E such as \u003Ccode\u003Eentity_with_forward_draft:node\u003C\/code\u003E (and other supported entity types), similar in spirit to core entity destinations.\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cp\u003E\u003Cstrong\u003EWhen and why to use it:\u003C\/strong\u003E External feeds or APIs own metadata on nodes (or similar entities) while editors enrich the same content in draft; reruns must refresh published data without stranding drafts with stale migrated values or losing editorial work.\u003C\/p\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--post-installation\u0022\u003EPost-installation\u003C\/h3\u003E\r\n\r\n\u003Cp\u003EThere is \u003Cstrong\u003Eno configuration page\u003C\/strong\u003E. After enabling the module:\u003C\/p\u003E\r\n\r\n\u003Col\u003E\r\n  \u003Cli\u003EOpen your \u003Cstrong\u003Emigration\u003C\/strong\u003E configuration (YAML or exported config).\u003C\/li\u003E\r\n  \u003Cli\u003ESet the \u003Cstrong\u003Edestination\u003C\/strong\u003E to \u003Ccode\u003Eentity_with_forward_draft:node\u003C\/code\u003E (or the appropriate derivative for your entity type).\u003C\/li\u003E\r\n  \u003Cli\u003EKeep your usual destination settings for updating the default revision (e.g. \u003Ccode\u003Eoverwrite_properties\u003C\/code\u003E).\u003C\/li\u003E\r\n  \u003Cli\u003EAdd \u003Ccode\u003Eforward_revision_overwrite_properties\u003C\/code\u003E with property names to copy from the new default onto the replayed draft, or omit\/leave empty if you only need the draft replayed without copying from default.\u003C\/li\u003E\r\n  \u003Cli\u003EOptionally set \u003Ccode\u003Emigration_sync\u003C\/code\u003E to \u003Ccode\u003Etrue\u003C\/code\u003E or \u003Ccode\u003Efalse\u003C\/code\u003E so the main migrate save matches how your site\u2019s code expects syncing to behave.\u003C\/li\u003E\r\n\u003C\/ol\u003E\r\n\r\n\u003Cp\u003ERebuild caches if needed. Test on a copy of production data that includes real forward drafts before using in production.\u003C\/p\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--additional-requirements\u0022\u003EAdditional requirements\u003C\/h3\u003E\r\n\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EDrupal core\u003C\/strong\u003E with the \u003Cstrong\u003EMigrate\u003C\/strong\u003E module (\u003Ccode\u003Emigrate\u003C\/code\u003E) enabled\u2014required dependency.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EContent moderation\u003C\/strong\u003E is not a package dependency; the module is most useful when the site uses \u003Cstrong\u003Erevisions and non-default drafts\u003C\/strong\u003E. Only \u003Cstrong\u003Erevisionable, fieldable\u003C\/strong\u003E entity types are targeted (same general idea as core revision-related migrate plugins).\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--recommended-libraries\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E\r\n\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EContent Moderation\u003C\/strong\u003E (core) when drafts ahead of published content are part of your workflow.\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EMigrate Plus\u003C\/strong\u003E and related tools if you manage many migrations or need extra plugins\u2014this module only changes the \u003Cstrong\u003Edestination\u003C\/strong\u003E behavior.\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--similar-projects\u0022\u003ESimilar projects\u003C\/h3\u003E\r\n\r\n\u003Cp\u003ECore \u003Ccode\u003Eentity:node\u003C\/code\u003E and similar \u003Ccode\u003Eentity:*\u003C\/code\u003E destinations update the default revision and do not implement forward-draft capture and replay. Core \u003Ccode\u003Eentity_revision\u003C\/code\u003E and revision import patterns solve different problems. Migrate Forward Draft is aimed at \u003Cstrong\u003Ereruns that refresh the published revision while keeping forward drafts coherent\u003C\/strong\u003E, with optional per-property sync from default to draft.\u003C\/p\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--support\u0022\u003ESupporting this module\u003C\/h3\u003E\r\n\r\n\u003Cp\u003EIssue queue contributions, patches, and feedback help improve the module. There is no required commercial support channel to use it.\u003C\/p\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--community-documentation\u0022\u003ECommunity documentation\u003C\/h3\u003E\r\n\r\n\u003Cp\u003ESee the project \u003Cstrong\u003EREADME\u003C\/strong\u003E for YAML examples and detailed behavior. Add links here over time to blog posts, videos, \u003Cstrong\u003EDrupalPod\u003C\/strong\u003E demos, or external docs as the community publishes them.\u003C\/p\u003E\r\n\r\n\u003Cp\u003EAn optional \u003Cstrong\u003Edemo\u003C\/strong\u003E submodule may be included with sample migrations\u2014enable only on non-production environments to try the destination in isolation.\u003C\/p\u003E","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003EWhen you import or update content with \u003Cstrong\u003EMigrate\u003C\/strong\u003E, Drupal usually writes to the \u003Cstrong\u003Edefault revision\u003C\/strong\u003E (what visitors see as published). On sites using \u003Cstrong\u003Eworkflows and content moderation\u003C\/strong\u003E, editors often save a \u003Cstrong\u003Enewer draft revision\u003C\/strong\u003E that is not the default\u2014a \u201cforward\u201d draft. If that draft is ahead of the live revision, a \u003Cstrong\u003Emigration rerun\u003C\/strong\u003E can leave the published node correct while the draft still has outdated values for fields the migration owns, or create confusing revision history. \u003Cstrong\u003EMigrate Forward Draft\u003C\/strong\u003E provides a \u003Cstrong\u003Emigrate destination plugin\u003C\/strong\u003E that, on update, captures that forward draft before the migration saves, updates the default revision from your migration, then saves a \u003Cstrong\u003Enew non-default revision\u003C\/strong\u003E that carries the editor\u2019s work forward. You can \u003Cstrong\u003Eoverlay selected fields\u003C\/strong\u003E from the freshly imported default onto that replayed draft so drafts stay aligned with your source where you want that.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--features-01\u0022\u003EFeatures\u003C\/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003EBasic functionality:\u003C\/strong\u003E A Migrate destination that is aware of \u201cforward\u201d (newer non-default) draft revisions and replays them after the default revision is updated by an import.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUnique behavior:\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EForward-draft detection\u003C\/strong\u003E before the migration updates the entity.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EReplay as a new non-default revision\u003C\/strong\u003E after the default is updated, so moderation and revision workflows stay meaningful.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003E\u003Ccode\u003Eforward_revision_overwrite_properties\u003C\/code\u003E\u003C\/strong\u003E\u2014choose which properties (often fields) to copy from the new default onto the replayed draft (e.g. migration-owned titles or IDs) while other draft values stay editor-owned.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003E\u003Ccode\u003Emigration_sync\u003C\/code\u003E\u003C\/strong\u003E (default matches core)\u2014controls \u003Ccode\u003EsetSyncing(TRUE)\u003C\/code\u003E on the \u003Cem\u003Emain\u003C\/em\u003E migrate save; the forward-draft \u003Cem\u003Ereplay\u003C\/em\u003E save does not use syncing, which matters for content moderation and custom subscribers.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EDerivative plugins\u003C\/strong\u003E such as \u003Ccode\u003Eentity_with_forward_draft:node\u003C\/code\u003E (and other supported entity types), similar in spirit to core entity destinations.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EWhen and why to use it:\u003C\/strong\u003E External feeds or APIs own metadata on nodes (or similar entities) while editors enrich the same content in draft; reruns must refresh published data without stranding drafts with stale migrated values or losing editorial work.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--post-installation-01\u0022\u003EPost-installation\u003C\/h3\u003E\n\u003Cp\u003EThere is \u003Cstrong\u003Eno configuration page\u003C\/strong\u003E. After enabling the module:\u003C\/p\u003E\n\u003Col\u003E\n\u003Cli\u003EOpen your \u003Cstrong\u003Emigration\u003C\/strong\u003E configuration (YAML or exported config).\u003C\/li\u003E\n\u003Cli\u003ESet the \u003Cstrong\u003Edestination\u003C\/strong\u003E to \u003Ccode\u003Eentity_with_forward_draft:node\u003C\/code\u003E (or the appropriate derivative for your entity type).\u003C\/li\u003E\n\u003Cli\u003EKeep your usual destination settings for updating the default revision (e.g. \u003Ccode\u003Eoverwrite_properties\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003EAdd \u003Ccode\u003Eforward_revision_overwrite_properties\u003C\/code\u003E with property names to copy from the new default onto the replayed draft, or omit\/leave empty if you only need the draft replayed without copying from default.\u003C\/li\u003E\n\u003Cli\u003EOptionally set \u003Ccode\u003Emigration_sync\u003C\/code\u003E to \u003Ccode\u003Etrue\u003C\/code\u003E or \u003Ccode\u003Efalse\u003C\/code\u003E so the main migrate save matches how your site\u2019s code expects syncing to behave.\u003C\/li\u003E\n\u003C\/ol\u003E\n\u003Cp\u003ERebuild caches if needed. Test on a copy of production data that includes real forward drafts before using in production.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--additional-requirements-01\u0022\u003EAdditional requirements\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EDrupal core\u003C\/strong\u003E with the \u003Cstrong\u003EMigrate\u003C\/strong\u003E module (\u003Ccode\u003Emigrate\u003C\/code\u003E) enabled\u2014required dependency.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EContent moderation\u003C\/strong\u003E is not a package dependency; the module is most useful when the site uses \u003Cstrong\u003Erevisions and non-default drafts\u003C\/strong\u003E. Only \u003Cstrong\u003Erevisionable, fieldable\u003C\/strong\u003E entity types are targeted (same general idea as core revision-related migrate plugins).\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--recommended-libraries-01\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EContent Moderation\u003C\/strong\u003E (core) when drafts ahead of published content are part of your workflow.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EMigrate Plus\u003C\/strong\u003E and related tools if you manage many migrations or need extra plugins\u2014this module only changes the \u003Cstrong\u003Edestination\u003C\/strong\u003E behavior.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--similar-projects-01\u0022\u003ESimilar projects\u003C\/h3\u003E\n\u003Cp\u003ECore \u003Ccode\u003Eentity:node\u003C\/code\u003E and similar \u003Ccode\u003Eentity:*\u003C\/code\u003E destinations update the default revision and do not implement forward-draft capture and replay. Core \u003Ccode\u003Eentity_revision\u003C\/code\u003E and revision import patterns solve different problems. Migrate Forward Draft is aimed at \u003Cstrong\u003Ereruns that refresh the published revision while keeping forward drafts coherent\u003C\/strong\u003E, with optional per-property sync from default to draft.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--support-01\u0022\u003ESupporting this module\u003C\/h3\u003E\n\u003Cp\u003EIssue queue contributions, patches, and feedback help improve the module. There is no required commercial support channel to use it.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--community-documentation-01\u0022\u003ECommunity documentation\u003C\/h3\u003E\n\u003Cp\u003ESee the project \u003Cstrong\u003EREADME\u003C\/strong\u003E for YAML examples and detailed behavior. Add links here over time to blog posts, videos, \u003Cstrong\u003EDrupalPod\u003C\/strong\u003E demos, or external docs as the community publishes them.\u003C\/p\u003E\n\u003Cp\u003EAn optional \u003Cstrong\u003Edemo\u003C\/strong\u003E submodule may be included with sample migrations\u2014enable only on non-production environments to try the destination in isolation.\u003C\/p\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":"\u003Cp\u003EMigrate destination that replays forward draft revisions after a rerun updates the default (published) revision\u2014helps moderated sites keep editor drafts in sync with imported fields.\u003C\/p\u003E"},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":{"value":"## Problem\r\n[Short description of incorrect or surprising behavior]\r\n\r\n## Environment\r\n- Drupal: [e.g. 10.4.x]\r\n- PHP: [e.g. 8.3]\r\n- migrate_forward_draft: [version \/ branch]\r\n- Content moderation: [yes\/no; workflow name if yes]\r\n\r\n## Migration\r\n- Destination plugin: [e.g. entity_with_forward_draft:node]\r\n- migration_sync: [true\/false]\r\n- forward_revision_overwrite_properties: [list or \u201cempty\u201d]\r\n- Other notable destination keys: [overwrite_properties, default_bundle, \u2026]\r\n\r\n## Reproduction\r\n1. [Step 1 \u2014 entity state before migrate, e.g. default vs forward draft]\r\n2. [Step 2 \u2014 migration run \/ drush command]\r\n3. [Step 3 \u2014 observed result]\r\n\r\n## Expected\r\n[What should happen]\r\n\r\n## Actual\r\n[What happens instead]\r\n\r\n## Attachments\r\n- [ ] Reduced migration YAML snippet (no secrets)\r\n- [ ] Screenshots or Drush\/log excerpts if useful","format":"1","processed":"\u003Cp\u003E## Problem\u003Cbr\u003E\n[Short description of incorrect or surprising behavior]\u003C\/p\u003E\n\u003Cp\u003E## Environment\u003Cbr\u003E\n- Drupal: [e.g. 10.4.x]\u003Cbr\u003E\n- PHP: [e.g. 8.3]\u003Cbr\u003E\n- migrate_forward_draft: [version \/ branch]\u003Cbr\u003E\n- Content moderation: [yes\/no; workflow name if yes]\u003C\/p\u003E\n\u003Cp\u003E## Migration\u003Cbr\u003E\n- Destination plugin: [e.g. entity_with_forward_draft:node]\u003Cbr\u003E\n- migration_sync: [true\/false]\u003Cbr\u003E\n- forward_revision_overwrite_properties: [list or \u201cempty\u201d]\u003Cbr\u003E\n- Other notable destination keys: [overwrite_properties, default_bundle, \u2026]\u003C\/p\u003E\n\u003Cp\u003E## Reproduction\u003Cbr\u003E\n1. [Step 1 \u2014 entity state before migrate, e.g. default vs forward draft]\u003Cbr\u003E\n2. [Step 2 \u2014 migration run \/ drush command]\u003Cbr\u003E\n3. [Step 3 \u2014 observed result]\u003C\/p\u003E\n\u003Cp\u003E## Expected\u003Cbr\u003E\n[What should happen]\u003C\/p\u003E\n\u003Cp\u003E## Actual\u003Cbr\u003E\n[What happens instead]\u003C\/p\u003E\n\u003Cp\u003E## Attachments\u003Cbr\u003E\n- [ ] Reduced migration YAML snippet (no secrets)\u003Cbr\u003E\n- [ ] Screenshots or Drush\/log excerpts if useful\u003C\/p\u003E"},"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"migrate_forward_draft","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"8158dd3b-5959-4302-ab39-a6c10602608d","meta":{"drupal_internal__target_id":490684}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/uid?resourceVersion=id%3A21791945"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/relationships\/uid?resourceVersion=id%3A21791945"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/field_development_status?resourceVersion=id%3A21791945"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/relationships\/field_development_status?resourceVersion=id%3A21791945"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/field_maintenance_status?resourceVersion=id%3A21791945"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/relationships\/field_maintenance_status?resourceVersion=id%3A21791945"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"cfef5e6a-b77b-4a2b-b669-e87b1266f3ac","meta":{"drupal_internal__target_id":191}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/field_module_categories?resourceVersion=id%3A21791945"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/relationships\/field_module_categories?resourceVersion=id%3A21791945"}}},"field_project_images":{"data":[{"type":"file--file","id":"f84a712e-fea5-414f-bf43-31515514c5a1","meta":{"alt":"A visual representation of a forward revision of an entity","title":null,"width":null,"height":null,"drupal_internal__target_id":1461130}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/field_project_images?resourceVersion=id%3A21791945"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/6ede9dbb-db4a-4bf3-a538-276e5fd20620\/relationships\/field_project_images?resourceVersion=id%3A21791945"}}}}},{"type":"node--project_module","id":"8b6be6ac-04fb-41b5-93a9-6d6eea41e071","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071?resourceVersion=id%3A21791939"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583995,"status":true,"title":"Plugin Report","created":"2026-04-09T18:04:37+00:00","changed":"2026-04-09T20:37:51+00:00","moderation_state":null,"body":{"value":"\u003Cp\u003EPlugin Report gives Drupal developers a built-in \u003Cstrong\u003EReports\u003C\/strong\u003E page and a set of Drush commands for introspecting every \u003Ccode\u003EDefaultPluginManager\u003C\/code\u003E service          registered in the container \u2014 and all the plugins each one exposes. Stop grepping source files to understand the plugin system; browse it live instead.\u003C\/p\u003E                             \r\n\u003Cbr\/\u003E                                                                                                                                                                                   \r\n\u003Cp align=\u0022center\u0022\u003E\u003Ca class=\u0022action-button\u0022 href=\u0022https:\/\/www.youtube.com\/watch?v=rU2rN8q2nr4\u0022\u003E\u0026#9654; Watch an introduction to Plugin Report\u003C\/a\u003E\u003C\/p\u003E                                          \r\n                                                                                                                                                                        \r\n\u003Ch2\u003EFeatures\u003C\/h2\u003E\r\n\u003Cblockquote\u003EBrowse, filter, and export every plugin manager and plugin registered in your Drupal site \u2014 directly from the admin UI or the terminal.\u003C\/blockquote\u003E                        \r\n\r\n\u003Cstrong\u003EAdmin UI\u003C\/strong\u003E                                                                                                                                                         \r\n\u003Cul\u003E                                                                                                                                                                              \r\n\u003Cli\u003EPlugin managers list \u2014 all \u003Ccode\u003EDefaultPluginManager\u003C\/code\u003E services, sortable by service ID, provider, alter hook, subdirectory, discovery mechanism, plugin interface, and class\u003C\/li\u003E                                                                                                                                                                          \r\n\u003Cli\u003EPlugins list \u2014 drill into any manager to browse its registered plugins and their definition attributes\u003C\/li\u003E                                                               \r\n\u003Cli\u003EPlugin detail \u2014 view the full definition, default configuration, element info, and every PHP interface a plugin implements\u003C\/li\u003E                                             \r\n\u003Cli\u003EClient-side filter \u2014 narrow any table in real time without a page reload\u003C\/li\u003E                                                                                               \r\n\u003C\/ul\u003E                                                                                                                                                                             \r\n\r\n\u003Cstrong\u003EDrush commands\u003C\/strong\u003E                                                                                                                                                   \r\n\u003Cul\u003E\r\n\u003Cli\u003E\u003Ccode\u003Edrush plugin-report:managers\u003C\/code\u003E \u2014 list all plugin managers\u003C\/li\u003E                                                                                                         \r\n\u003Cli\u003E\u003Ccode\u003Edrush plugin-report:plugins {manager};\u003C\/code\u003E \u2014 list plugins for a manager\u003C\/li\u003E                                                                                        \r\n\u003Cli\u003E\u003Ccode\u003Eplugin-report:plugin {manager} {plugin};\u003C\/code\u003E \u2014 show full detail for one plugin\u003C\/li\u003E                                                                     \r\n\u003Cli\u003EOutput as table, JSON, YAML, or CSV; filter by any field\u003C\/li\u003E                                                                                                               \r\n\u003C\/ul\u003E                                                                                                                                                                             \r\n\r\n\u003Ch2\u003EUsage\u003C\/h2\u003E\r\n\u003Col\u003E\r\n\u003Cli\u003EInstall via Composer: \u003Cdiv class=\u0022codeblock\u0022\u003E\u003Ccode\u003Ecomposer require drupal\/plugin_report                                                                                          \r\ndrush en plugin_report\u003C\/code\u003E\u003C\/div\u003E\u003C\/li\u003E                                                                                                                                                \r\n\u003Cli\u003ENavigate to \u003Cstrong\u003EAdministration \u2192 Reports \u2192 Plugins\u003C\/strong\u003E.\u003C\/li\u003E                                                                                                             \r\n\u003Cli\u003EClick a plugin manager\u0027s \u003Cstrong\u003EService ID\u003C\/strong\u003E to view its plugins.\u003C\/li\u003E                                                                                                    \r\n\u003Cli\u003EClick a plugin\u0027s \u003Cstrong\u003EID\u003C\/strong\u003E to view its full detail.\u003C\/li\u003E                                                                                                                \r\n\u003C\/ol\u003E                                                                                                                                                                                   \r\n                                                                                                                                                                        \r\n\u003Ch2\u003EPermissions\u003C\/h2\u003E                                                                                                                                                                    \r\n\u003Cp\u003EGrant the \u003Cstrong\u003Eaccess site reports\u003C\/strong\u003E permission to any role that should view Plugin Report pages.\u003C\/p\u003E\r\n\r\n\u003Cdiv class=\u0022help\u0022\u003E\r\n\u003Ch4\u003E\u0026#129302; A note on AI-assisted development\u003C\/h4\u003E\r\n\u003Cp\u003EThis module was created using AI and understood by humans. The maintainer reviewed, tested, and takes responsibility for every line of code \u2014 consistent with the philosophy described in \u003Ca href=\u0022https:\/\/dri.es\/never-submit-code-you-do-not-understand\u0022\u003ENever submit code you do not understand\u003C\/a\u003E by Dries Buytaert.\u003C\/p\u003E\r\n\u003C\/div\u003E\r\n\r\n","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003EPlugin Report gives Drupal developers a built-in \u003Cstrong\u003EReports\u003C\/strong\u003E page and a set of Drush commands for introspecting every \u003Ccode\u003EDefaultPluginManager\u003C\/code\u003E service          registered in the container \u2014 and all the plugins each one exposes. Stop grepping source files to understand the plugin system; browse it live instead.\u003C\/p\u003E\n\u003Cp\u003E\u003Cbr\u003E                                                                                                                                                                                   \u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/www.youtube.com\/watch?v=rU2rN8q2nr4\u0022 rel=\u0022nofollow\u0022\u003E\u25b6 Watch an introduction to Plugin Report\u003C\/a\u003E\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022features\u0022\u003EFeatures\u003C\/h2\u003E\n\u003Cblockquote\u003E\u003Cp\u003EBrowse, filter, and export every plugin manager and plugin registered in your Drupal site \u2014 directly from the admin UI or the terminal.\u003C\/p\u003E\u003C\/blockquote\u003E\n\u003Cp\u003E\u003Cstrong\u003EAdmin UI\u003C\/strong\u003E                                                                                                                                                         \u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EPlugin managers list \u2014 all \u003Ccode\u003EDefaultPluginManager\u003C\/code\u003E services, sortable by service ID, provider, alter hook, subdirectory, discovery mechanism, plugin interface, and class\u003C\/li\u003E\n\u003Cli\u003EPlugins list \u2014 drill into any manager to browse its registered plugins and their definition attributes\u003C\/li\u003E\n\u003Cli\u003EPlugin detail \u2014 view the full definition, default configuration, element info, and every PHP interface a plugin implements\u003C\/li\u003E\n\u003Cli\u003EClient-side filter \u2014 narrow any table in real time without a page reload\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EDrush commands\u003C\/strong\u003E                                                                                                                                                   \u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003Edrush plugin-report:managers\u003C\/code\u003E \u2014 list all plugin managers\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Edrush plugin-report:plugins {manager};\u003C\/code\u003E \u2014 list plugins for a manager\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Eplugin-report:plugin {manager} {plugin};\u003C\/code\u003E \u2014 show full detail for one plugin\u003C\/li\u003E\n\u003Cli\u003EOutput as table, JSON, YAML, or CSV; filter by any field\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022usage\u0022\u003EUsage\u003C\/h2\u003E\n\u003Col\u003E\n\u003Cli\u003EInstall via Composer:\u003Cbr\u003E\n\u003Cdiv\u003E\u003Ccode\u003Ecomposer require drupal\/plugin_report\u003Cbr\u003E\ndrush en plugin_report\u003C\/code\u003E\u003C\/div\u003E\n\u003C\/li\u003E\n\u003Cli\u003ENavigate to \u003Cstrong\u003EAdministration \u2192 Reports \u2192 Plugins\u003C\/strong\u003E.\u003C\/li\u003E\n\u003Cli\u003EClick a plugin manager\u0027s \u003Cstrong\u003EService ID\u003C\/strong\u003E to view its plugins.\u003C\/li\u003E\n\u003Cli\u003EClick a plugin\u0027s \u003Cstrong\u003EID\u003C\/strong\u003E to view its full detail.\u003C\/li\u003E\n\u003C\/ol\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022permissions\u0022\u003EPermissions\u003C\/h2\u003E\n\u003Cp\u003EGrant the \u003Cstrong\u003Eaccess site reports\u003C\/strong\u003E permission to any role that should view Plugin Report pages.\u003C\/p\u003E\n\u003Cdiv\u003E\n\u003Ch4 id=\u0022a-note-on-ai-assisted-development\u0022\u003E\ud83e\udd16 A note on AI-assisted development\u003C\/h4\u003E\n\u003Cp\u003EThis module was created using AI and understood by humans. The maintainer reviewed, tested, and takes responsibility for every line of code \u2014 consistent with the philosophy described in \u003Ca href=\u0022https:\/\/dri.es\/never-submit-code-you-do-not-understand\u0022 rel=\u0022nofollow\u0022\u003ENever submit code you do not understand\u003C\/a\u003E by Dries Buytaert.\u003C\/p\u003E\n\u003C\/div\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":{"uri":"https:\/\/git.drupalcode.org\/project\/plugin_report\/-\/avatar","title":null,"options":[]},"field_project_has_releases":true,"field_project_machine_name":"plugin_report","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"ac31d9c9-9a4f-400f-893b-a8b4e4fb1de0","meta":{"drupal_internal__target_id":371407}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/uid?resourceVersion=id%3A21791939"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/relationships\/uid?resourceVersion=id%3A21791939"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/field_development_status?resourceVersion=id%3A21791939"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/relationships\/field_development_status?resourceVersion=id%3A21791939"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"cee844e2-68b5-489d-bafa-6a0ade2b6dfd","meta":{"drupal_internal__target_id":27273}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/field_maintenance_status?resourceVersion=id%3A21791939"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/relationships\/field_maintenance_status?resourceVersion=id%3A21791939"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"abf23828-f269-4d39-8589-b731209eb154","meta":{"drupal_internal__target_id":186}},{"type":"taxonomy_term--module_categories","id":"086cebcf-200f-4c34-886e-f9921919b292","meta":{"drupal_internal__target_id":189}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/field_module_categories?resourceVersion=id%3A21791939"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/relationships\/field_module_categories?resourceVersion=id%3A21791939"}}},"field_project_images":{"data":[{"type":"file--file","id":"3962b1ef-d51d-4c6a-bd8b-25308b2442b1","meta":{"alt":"","title":null,"width":2704,"height":1512,"drupal_internal__target_id":1461125}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/field_project_images?resourceVersion=id%3A21791939"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/8b6be6ac-04fb-41b5-93a9-6d6eea41e071\/relationships\/field_project_images?resourceVersion=id%3A21791939"}}}}},{"type":"node--project_module","id":"91ca8a42-bf07-40c4-a004-6d98b18b16cf","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf?resourceVersion=id%3A21791917"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583975,"status":true,"title":"Gadget - A Drupal Inspector","created":"2026-04-09T16:30:15+00:00","changed":"2026-04-09T16:30:15+00:00","moderation_state":null,"body":{"value":"Gadget - The Drupal Inspector\r\n\r\nGadget is a comprehensive development toolkit that provides 80+ powerful Drush commands for site analysis, debugging, and management. It\u0027s like having a Swiss Army knife for Drupal developers and site builders.\r\n\r\n\u003Ch3 id=\u0022module-project--features\u0022\u003EFeatures\u003C\/h3\u003E\r\n\r\nGadget transforms your Drupal development workflow with organized command groups covering every aspect of your site:\r\n\r\n\u003Cstrong\u003EContent \u0026 Entity Management\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EList, analyze, and manage content types, entities, and fields\u003C\/li\u003E\r\n\u003Cli\u003ECreate, delete, and bulk operations on content\u003C\/li\u003E\r\n\u003Cli\u003EInteractive entity selection and detailed reporting\u003C\/li\u003E\r\n\u003Cli\u003EDependency analysis and relationship mapping\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EConfiguration Management\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EAdvanced config validation, comparison, and repair tools\u003C\/li\u003E\r\n\u003Cli\u003EUUID mismatch detection and fixing\u003C\/li\u003E\r\n\u003Cli\u003EOrphaned configuration cleanup\u003C\/li\u003E\r\n\u003Cli\u003EConfig split management and synchronization\u003C\/li\u003E\r\n\u003Cli\u003EEnvironment comparison tools\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EBlock \u0026 Layout Analysis\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EComprehensive block listing and analysis\u003C\/li\u003E\r\n\u003Cli\u003ERegion mapping and theme integration\u003C\/li\u003E\r\n\u003Cli\u003EBlock type management and reporting\u003C\/li\u003E\r\n\u003Cli\u003EIssue detection and resolution\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EField \u0026 Widget Tools\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EField creation, deletion, and management\u003C\/li\u003E\r\n\u003Cli\u003EWidget and formatter analysis\u003C\/li\u003E\r\n\u003Cli\u003EField type exploration with colorful output\u003C\/li\u003E\r\n\u003Cli\u003EBase field override management\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EViews \u0026 Display Management\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EView cloning, renaming, and organization\u003C\/li\u003E\r\n\u003Cli\u003EPerformance analysis and optimization\u003C\/li\u003E\r\n\u003Cli\u003EDependency tracking and validation\u003C\/li\u003E\r\n\u003Cli\u003EImport\/export capabilities\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EMenu \u0026 Navigation\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EMenu structure analysis and repair\u003C\/li\u003E\r\n\u003Cli\u003ELink validation and broken link detection\u003C\/li\u003E\r\n\u003Cli\u003EComprehensive menu reporting\u003C\/li\u003E\r\n\u003Cli\u003ETree visualization\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EParagraphs Integration\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EParagraph type management and analysis\u003C\/li\u003E\r\n\u003Cli\u003ENesting depth analysis\u003C\/li\u003E\r\n\u003Cli\u003EOrphaned paragraph detection\u003C\/li\u003E\r\n\u003Cli\u003EUsage statistics and validation\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003ECKEditor \u0026 Text Formats\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003ECKEditor 5 plugin analysis and reporting\u003C\/li\u003E\r\n\u003Cli\u003EToolbar configuration inspection\u003C\/li\u003E\r\n\u003Cli\u003EText format validation\u003C\/li\u003E\r\n\u003Cli\u003EPlugin dependency trees\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EPerformance \u0026 Security\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EMemory usage analysis\u003C\/li\u003E\r\n\u003Cli\u003ESecurity role auditing\u003C\/li\u003E\r\n\u003Cli\u003EOWASP Top 10 compliance checking\u003C\/li\u003E\r\n\u003Cli\u003EWCAG 2.1 accessibility validation\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EDeveloper Tools\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EService container analysis and dependency mapping\u003C\/li\u003E\r\n\u003Cli\u003ENamespace conflict detection\u003C\/li\u003E\r\n\u003Cli\u003EJS\/CSS library management and validation\u003C\/li\u003E\r\n\u003Cli\u003ECode quality and best practice validation\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--post-installation\u0022\u003EPost-Installation\u003C\/h3\u003E\r\n\r\nAfter installation, Gadget works entirely through Drush commands - no configuration pages needed! Simply run:\r\n\r\n\u003Ccode\u003Edrush gadget\u003C\/code\u003E\r\n\r\nThis displays all available commands organized by category. Each command includes:\r\n\u003Cul\u003E\r\n\u003Cli\u003EColorful, organized output for better readability\u003C\/li\u003E\r\n\u003Cli\u003EInteractive selection menus where appropriate\u003C\/li\u003E\r\n\u003Cli\u003EComprehensive filtering and search options\u003C\/li\u003E\r\n\u003Cli\u003EDetailed help with examples\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\nKey commands to get started:\r\n\u003Cul\u003E\r\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:info\u003C\/code\u003E - Site overview and statistics\u003C\/li\u003E\r\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:entity:list\u003C\/code\u003E - Browse all content\u003C\/li\u003E\r\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:config:validate\u003C\/code\u003E - Check configuration health\u003C\/li\u003E\r\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:help\u003C\/code\u003E - Detailed help with examples\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\nAll commands support standard Drush options like \u003Ccode\u003E--format\u003C\/code\u003E, \u003Ccode\u003E--fields\u003C\/code\u003E, and output redirection.\r\n\r\n\u003Ch3 id=\u0022module-project--additional-requirements\u0022\u003EAdditional Requirements\u003C\/h3\u003E\r\n\r\n\u003Cstrong\u003ERequired:\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EDrupal 11+\u003C\/li\u003E\r\n\u003Cli\u003EDrush 11+ (for command functionality)\u003C\/li\u003E\r\n\u003Cli\u003EPHP 8.1+\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EOptional but Recommended:\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EConfig Split module (for advanced config management features)\u003C\/li\u003E\r\n\u003Cli\u003EParagraphs module (for paragraph-specific commands)\u003C\/li\u003E\r\n\u003Cli\u003ECKEditor 5 (for editor analysis tools)\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--recommended-libraries\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E\r\n\r\nGadget works great alongside:\r\n\u003Cul\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EDevel\u003C\/strong\u003E - Complementary development tools\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EConfig Split\u003C\/strong\u003E - Enhanced by Gadget\u0027s split management commands\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EAdmin Toolbar\u003C\/strong\u003E - UI complement to Gadget\u0027s CLI tools\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EParagraphs\u003C\/strong\u003E - Unlocks paragraph-specific analysis commands\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EWebform\u003C\/strong\u003E - Additional entity types for analysis\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--similar-projects\u0022\u003ESimilar projects\u003C\/h3\u003E\r\n\r\nWhile tools like Devel, Drush core commands, and Console provide development utilities, Gadget differentiates itself by:\r\n\r\n\u003Cul\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EComprehensive Coverage\u003C\/strong\u003E: 80+ commands covering every Drupal subsystem\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EEnhanced Output\u003C\/strong\u003E: Colorful, organized displays with emojis and formatting\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EInteractive Features\u003C\/strong\u003E: Menu-driven selection and guided workflows\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EDeep Analysis\u003C\/strong\u003E: Goes beyond basic listing to provide insights and issue detection\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EUnified Interface\u003C\/strong\u003E: Consistent command structure and output formatting\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EProduction-Safe\u003C\/strong\u003E: Read-only analysis commands safe for live sites\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\nGadget doesn\u0027t replace these tools - it enhances your toolkit with specialized, developer-focused commands that provide deeper insights into your Drupal site.\r\n\r\n\u003Ch3 id=\u0022module-project--support\u0022\u003ESupporting this Module\u003C\/h3\u003E\r\n\r\nGadget is actively developed and maintained. You can support development by:\r\n\u003Cul\u003E\r\n\u003Cli\u003EReporting issues and feature requests on the project page\u003C\/li\u003E\r\n\u003Cli\u003EContributing patches and improvements\u003C\/li\u003E\r\n\u003Cli\u003ESharing your use cases and feedback\u003C\/li\u003E\r\n\u003Cli\u003EStarring the project to show appreciation\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Ch3 id=\u0022module-project--community-documentation\u0022\u003ECommunity Documentation\u003C\/h3\u003E\r\n\r\n\u003Cul\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EBuilt-in Help\u003C\/strong\u003E: Run \u003Ccode\u003Edrush gadget:help\u003C\/code\u003E for comprehensive documentation with examples\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003ECommand Reference\u003C\/strong\u003E: Each command includes detailed help via \u003Ccode\u003Edrush help gadget:command:name\u003C\/code\u003E\u003C\/li\u003E\r\n\u003Cli\u003E\u003Cstrong\u003EInteractive Discovery\u003C\/strong\u003E: Use \u003Ccode\u003Edrush gadget\u003C\/code\u003E to explore available commands by category\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\r\n\u003Cstrong\u003EPerfect for:\u003C\/strong\u003E\r\n\u003Cul\u003E\r\n\u003Cli\u003EDrupal developers debugging complex sites\u003C\/li\u003E\r\n\u003Cli\u003ESite builders analyzing content structure\u003C\/li\u003E\r\n\u003Cli\u003EDevOps teams validating configurations\u003C\/li\u003E\r\n\u003Cli\u003EAgencies managing multiple Drupal projects\u003C\/li\u003E\r\n\u003Cli\u003EAnyone who prefers powerful CLI tools over clicking through admin interfaces\u003C\/li\u003E\r\n\u003C\/ul\u003E","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003EGadget - The Drupal Inspector\u003C\/p\u003E\n\u003Cp\u003EGadget is a comprehensive development toolkit that provides 80+ powerful Drush commands for site analysis, debugging, and management. It\u0027s like having a Swiss Army knife for Drupal developers and site builders.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--features-01\u0022\u003EFeatures\u003C\/h3\u003E\n\u003Cp\u003EGadget transforms your Drupal development workflow with organized command groups covering every aspect of your site:\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EContent \u0026amp; Entity Management\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EList, analyze, and manage content types, entities, and fields\u003C\/li\u003E\n\u003Cli\u003ECreate, delete, and bulk operations on content\u003C\/li\u003E\n\u003Cli\u003EInteractive entity selection and detailed reporting\u003C\/li\u003E\n\u003Cli\u003EDependency analysis and relationship mapping\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EConfiguration Management\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EAdvanced config validation, comparison, and repair tools\u003C\/li\u003E\n\u003Cli\u003EUUID mismatch detection and fixing\u003C\/li\u003E\n\u003Cli\u003EOrphaned configuration cleanup\u003C\/li\u003E\n\u003Cli\u003EConfig split management and synchronization\u003C\/li\u003E\n\u003Cli\u003EEnvironment comparison tools\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EBlock \u0026amp; Layout Analysis\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EComprehensive block listing and analysis\u003C\/li\u003E\n\u003Cli\u003ERegion mapping and theme integration\u003C\/li\u003E\n\u003Cli\u003EBlock type management and reporting\u003C\/li\u003E\n\u003Cli\u003EIssue detection and resolution\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EField \u0026amp; Widget Tools\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EField creation, deletion, and management\u003C\/li\u003E\n\u003Cli\u003EWidget and formatter analysis\u003C\/li\u003E\n\u003Cli\u003EField type exploration with colorful output\u003C\/li\u003E\n\u003Cli\u003EBase field override management\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EViews \u0026amp; Display Management\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EView cloning, renaming, and organization\u003C\/li\u003E\n\u003Cli\u003EPerformance analysis and optimization\u003C\/li\u003E\n\u003Cli\u003EDependency tracking and validation\u003C\/li\u003E\n\u003Cli\u003EImport\/export capabilities\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EMenu \u0026amp; Navigation\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EMenu structure analysis and repair\u003C\/li\u003E\n\u003Cli\u003ELink validation and broken link detection\u003C\/li\u003E\n\u003Cli\u003EComprehensive menu reporting\u003C\/li\u003E\n\u003Cli\u003ETree visualization\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EParagraphs Integration\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EParagraph type management and analysis\u003C\/li\u003E\n\u003Cli\u003ENesting depth analysis\u003C\/li\u003E\n\u003Cli\u003EOrphaned paragraph detection\u003C\/li\u003E\n\u003Cli\u003EUsage statistics and validation\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003ECKEditor \u0026amp; Text Formats\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003ECKEditor 5 plugin analysis and reporting\u003C\/li\u003E\n\u003Cli\u003EToolbar configuration inspection\u003C\/li\u003E\n\u003Cli\u003EText format validation\u003C\/li\u003E\n\u003Cli\u003EPlugin dependency trees\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EPerformance \u0026amp; Security\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EMemory usage analysis\u003C\/li\u003E\n\u003Cli\u003ESecurity role auditing\u003C\/li\u003E\n\u003Cli\u003EOWASP Top 10 compliance checking\u003C\/li\u003E\n\u003Cli\u003EWCAG 2.1 accessibility validation\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EDeveloper Tools\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EService container analysis and dependency mapping\u003C\/li\u003E\n\u003Cli\u003ENamespace conflict detection\u003C\/li\u003E\n\u003Cli\u003EJS\/CSS library management and validation\u003C\/li\u003E\n\u003Cli\u003ECode quality and best practice validation\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--post-installation-01\u0022\u003EPost-Installation\u003C\/h3\u003E\n\u003Cp\u003EAfter installation, Gadget works entirely through Drush commands - no configuration pages needed! Simply run:\u003C\/p\u003E\n\u003Cp\u003E\u003Ccode\u003Edrush gadget\u003C\/code\u003E\u003C\/p\u003E\n\u003Cp\u003EThis displays all available commands organized by category. Each command includes:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EColorful, organized output for better readability\u003C\/li\u003E\n\u003Cli\u003EInteractive selection menus where appropriate\u003C\/li\u003E\n\u003Cli\u003EComprehensive filtering and search options\u003C\/li\u003E\n\u003Cli\u003EDetailed help with examples\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EKey commands to get started:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:info\u003C\/code\u003E - Site overview and statistics\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:entity:list\u003C\/code\u003E - Browse all content\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:config:validate\u003C\/code\u003E - Check configuration health\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Edrush gadget:help\u003C\/code\u003E - Detailed help with examples\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAll commands support standard Drush options like \u003Ccode\u003E--format\u003C\/code\u003E, \u003Ccode\u003E--fields\u003C\/code\u003E, and output redirection.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--additional-requirements-01\u0022\u003EAdditional Requirements\u003C\/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003ERequired:\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EDrupal 11+\u003C\/li\u003E\n\u003Cli\u003EDrush 11+ (for command functionality)\u003C\/li\u003E\n\u003Cli\u003EPHP 8.1+\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EOptional but Recommended:\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EConfig Split module (for advanced config management features)\u003C\/li\u003E\n\u003Cli\u003EParagraphs module (for paragraph-specific commands)\u003C\/li\u003E\n\u003Cli\u003ECKEditor 5 (for editor analysis tools)\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--recommended-libraries-01\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E\n\u003Cp\u003EGadget works great alongside:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EDevel\u003C\/strong\u003E - Complementary development tools\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EConfig Split\u003C\/strong\u003E - Enhanced by Gadget\u0027s split management commands\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EAdmin Toolbar\u003C\/strong\u003E - UI complement to Gadget\u0027s CLI tools\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EParagraphs\u003C\/strong\u003E - Unlocks paragraph-specific analysis commands\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EWebform\u003C\/strong\u003E - Additional entity types for analysis\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--similar-projects-01\u0022\u003ESimilar projects\u003C\/h3\u003E\n\u003Cp\u003EWhile tools like Devel, Drush core commands, and Console provide development utilities, Gadget differentiates itself by:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EComprehensive Coverage\u003C\/strong\u003E: 80+ commands covering every Drupal subsystem\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EEnhanced Output\u003C\/strong\u003E: Colorful, organized displays with emojis and formatting\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EInteractive Features\u003C\/strong\u003E: Menu-driven selection and guided workflows\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EDeep Analysis\u003C\/strong\u003E: Goes beyond basic listing to provide insights and issue detection\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EUnified Interface\u003C\/strong\u003E: Consistent command structure and output formatting\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EProduction-Safe\u003C\/strong\u003E: Read-only analysis commands safe for live sites\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EGadget doesn\u0027t replace these tools - it enhances your toolkit with specialized, developer-focused commands that provide deeper insights into your Drupal site.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--support-01\u0022\u003ESupporting this Module\u003C\/h3\u003E\n\u003Cp\u003EGadget is actively developed and maintained. You can support development by:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EReporting issues and feature requests on the project page\u003C\/li\u003E\n\u003Cli\u003EContributing patches and improvements\u003C\/li\u003E\n\u003Cli\u003ESharing your use cases and feedback\u003C\/li\u003E\n\u003Cli\u003EStarring the project to show appreciation\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--community-documentation-01\u0022\u003ECommunity Documentation\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EBuilt-in Help\u003C\/strong\u003E: Run \u003Ccode\u003Edrush gadget:help\u003C\/code\u003E for comprehensive documentation with examples\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ECommand Reference\u003C\/strong\u003E: Each command includes detailed help via \u003Ccode\u003Edrush help gadget:command:name\u003C\/code\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EInteractive Discovery\u003C\/strong\u003E: Use \u003Ccode\u003Edrush gadget\u003C\/code\u003E to explore available commands by category\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003EPerfect for:\u003C\/strong\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EDrupal developers debugging complex sites\u003C\/li\u003E\n\u003Cli\u003ESite builders analyzing content structure\u003C\/li\u003E\n\u003Cli\u003EDevOps teams validating configurations\u003C\/li\u003E\n\u003Cli\u003EAgencies managing multiple Drupal projects\u003C\/li\u003E\n\u003Cli\u003EAnyone who prefers powerful CLI tools over clicking through admin interfaces\u003C\/li\u003E\n\u003C\/ul\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"gadget","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"6e6b0e9c-4e68-4043-8752-8c15121a8d8f","meta":{"drupal_internal__target_id":24244}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/uid?resourceVersion=id%3A21791917"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/relationships\/uid?resourceVersion=id%3A21791917"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/field_development_status?resourceVersion=id%3A21791917"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/relationships\/field_development_status?resourceVersion=id%3A21791917"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/field_maintenance_status?resourceVersion=id%3A21791917"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/relationships\/field_maintenance_status?resourceVersion=id%3A21791917"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"086cebcf-200f-4c34-886e-f9921919b292","meta":{"drupal_internal__target_id":189}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/field_module_categories?resourceVersion=id%3A21791917"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/relationships\/field_module_categories?resourceVersion=id%3A21791917"}}},"field_project_images":{"data":[],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/field_project_images?resourceVersion=id%3A21791917"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/91ca8a42-bf07-40c4-a004-6d98b18b16cf\/relationships\/field_project_images?resourceVersion=id%3A21791917"}}}}},{"type":"node--project_module","id":"0a66d43b-caf8-4c41-96ef-9fd4efd19719","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719?resourceVersion=id%3A21791916"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583973,"status":true,"title":"Admin Theming Tools","created":"2026-04-09T16:20:28+00:00","changed":"2026-04-09T17:29:44+00:00","moderation_state":null,"body":{"value":"  \u003Cp\u003EA suite of test modules for Drupal admin theme development. Each submodule exercises one UI component or form pattern \u0026mdash; buttons, dialogs, tables, form widgets, pagers, tabs, and so on \u0026mdash; across multiple themes so regressions can be spotted visually.\u003C\/p\u003E\r\n\r\n  \u003Cp\u003ENone of the test pages are theme-specific \u0026mdash; each renders in whatever theme is active, so the suite works equally well against Claro, Admin, Olivero, Stark, and any contrib or custom admin theme. The whole point is to surface cross-theme rendering differences.\u003C\/p\u003E\r\n\u003Cdiv class=\u0022note-warning\u0022\u003E\r\n  \u003Ch2\u003ENot for production\u003C\/h2\u003E\r\n  \u003Cp\u003EThis module is intended for local development and regression testing only. Several submodules intentionally open admin routes to anonymous users, ship fixture content types and test data, or disable render caching. Do not install on a public site.\u003C\/p\u003E\r\n\u003C\/div\u003E\r\n  \u003Ch2\u003EFeatures\u003C\/h2\u003E\r\n\r\n  \u003Cul\u003E\r\n    \u003Cli\u003E\u003Cstrong\u003EDashboard\u003C\/strong\u003E at \u003Ccode\u003E\/admin\/modules\/theming-tools\u003C\/code\u003E listing every test submodule with enable\/disable operations and bulk actions.\u003C\/li\u003E\r\n    \u003Cli\u003E\u003Cstrong\u003ENavigation drawer\u003C\/strong\u003E \u0026mdash; a \u0022Theming Tools\u0022 expandable group auto-injected into the admin menu. Every enabled test submodule\u0027s page appears here automatically, sorted alphabetically.\u003C\/li\u003E\r\n    \u003Cli\u003E\u003Cstrong\u003EAuto-discovery\u003C\/strong\u003E \u0026mdash; submodules tagged \u003Ccode\u003Etheming_test: true\u003C\/code\u003E are picked up by the dashboard and navigation drawer with zero configuration.\u003C\/li\u003E\r\n    \u003Cli\u003E\u003Cstrong\u003E3 test themes\u003C\/strong\u003E \u0026mdash; fixture themes for the Appearance admin page, including an intentionally incompatible theme for testing that code path.\u003C\/li\u003E\r\n  \u003C\/ul\u003E\r\n\u003Cdiv class=\u0022note-warning\u0022\u003E\r\n  \u003Ch2\u003ENot for production damnit!\u003C\/h2\u003E\r\n  \u003Cp\u003EThis module is intended for local development and regression testing only. Several submodules intentionally open admin routes to anonymous users, ship fixture content types and test data, or disable render caching. Do not install on a public site.\u003C\/p\u003E\r\n\u003C\/div\u003E\r\n  \u003Ch2\u003EIncluded submodules\u003C\/h2\u003E\r\n\r\n  \u003Ctable\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Eactionlink\u003C\/td\u003E\u003Ctd\u003EAction Link component\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Eautocomplete\u003C\/td\u003E\u003Ctd\u003EAutocomplete form widget\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Ebutton\u003C\/td\u003E\u003Ctd\u003EButtons and button links (primary, secondary, small variants)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Ecard\u003C\/td\u003E\u003Ctd\u003ECard component (appearance admin page)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Echeckboxradio\u003C\/td\u003E\u003Ctd\u003ECheckboxes and radios on a contact form\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Edetails\u003C\/td\u003E\u003Ctd\u003EDetails element (site information form)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Edevhelp\u003C\/td\u003E\u003Ctd\u003EDisables render caching and enables debug mode\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Edialog\u003C\/td\u003E\u003Ctd\u003ERegular, modal, off-canvas, and off-canvas-top dialogs\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Edropbutton\u003C\/td\u003E\u003Ctd\u003EDropbutton \/ Operations component\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Eexposed_form\u003C\/td\u003E\u003Ctd\u003EViews exposed form and bulk operations\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Efieldcardinality\u003C\/td\u003E\u003Ctd\u003EMulti-cardinality field widgets\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Efieldset\u003C\/td\u003E\u003Ctd\u003EFieldset component\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Eimagefile\u003C\/td\u003E\u003Ctd\u003EImage and managed file form widgets\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Elang_hebrew\u003C\/td\u003E\u003Ctd\u003EHebrew language + language switcher for RTL tests\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Emessage\u003C\/td\u003E\u003Ctd\u003EMessage component and Drupal.Message JS API\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Epager\u003C\/td\u003E\u003Ctd\u003EPagers (via Views)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Epassword\u003C\/td\u003E\u003Ctd\u003EPassword-confirm widget\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Epointertracker\u003C\/td\u003E\u003Ctd\u003ECrosshair overlay following mouse\/touch pointer\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Epresuf\u003C\/td\u003E\u003Ctd\u003EForm item prefixes and suffixes\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Eprogress\u003C\/td\u003E\u003Ctd\u003EProgress indicators (throbber, progress bar, fullscreen)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Eselect\u003C\/td\u003E\u003Ctd\u003ESingle- and multi-value select widgets\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Esidebar\u003C\/td\u003E\u003Ctd\u003EEntity meta sidebar\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etab\u003C\/td\u003E\u003Ctd\u003ELocal task tabs\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etable\u003C\/td\u003E\u003Ctd\u003ETable component (sortable, selectable, responsive)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etabledrag\u003C\/td\u003E\u003Ctd\u003EDraggable tables (nested hierarchy, mixed-height rows)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etestfilters\u003C\/td\u003E\u003Ctd\u003EText formats and CKEditor 5 editor config\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etextarea\u003C\/td\u003E\u003Ctd\u003EPlain and formatted textarea widgets\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etextfixtures\u003C\/td\u003E\u003Ctd\u003EColor, password, and search field types\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etextform\u003C\/td\u003E\u003Ctd\u003EText-like form items (textfield, telephone, email, url, datetime)\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Ethemeswitcher\u003C\/td\u003E\u003Ctd\u003EFooter form to switch active theme via cookie\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Etitle_shortcut\u003C\/td\u003E\u003Ctd\u003EPage titles alongside shortcut badges\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Ett_navigation\u003C\/td\u003E\u003Ctd\u003ECore Navigation block rendering\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Ett_node\u003C\/td\u003E\u003Ctd\u003EMinimal test content type used as a fixture\u003C\/td\u003E\u003C\/tr\u003E\r\n    \u003Ctr\u003E\u003Ctd\u003Evertical_tabs\u003C\/td\u003E\u003Ctd\u003EVertical Tabs component\u003C\/td\u003E\u003C\/tr\u003E\r\n  \u003C\/table\u003E\r\n\r\n  \u003Ch2\u003EInstallation\u003C\/h2\u003E\r\n\r\n  \u003Cpre\u003E\u003Ccode\u003Edrush en theming_tools\r\n  # then enable specific test submodules as needed:\r\n  drush en button dialog table tabledrag dropbutton textform textarea\r\n  \u003C\/code\u003E\u003C\/pre\u003E\r\n\r\n  \u003Cp\u003EOr enable everything at once through the dashboard at \u003Ccode\u003E\/admin\/modules\/theming-tools\u003C\/code\u003E.\u003C\/p\u003E\r\n\r\n  \u003Cp\u003ESome submodules depend on the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/contact\u0022\u003EContact\u003C\/a\u003E contrib module (moved out of core in Drupal 11). If it isn\u0027t installed, those submodules simply won\u0027t enable; everything else works without it.\u003C\/p\u003E\r\n\r\n  \u003Ch2\u003EDrupal version support\u003C\/h2\u003E\r\n\r\n  \u003Cp\u003ESupports Drupal 10.3, 11, and 12. Actively tested against the \u003Ccode\u003Emain\u003C\/code\u003E branch of Drupal core.\u003C\/p\u003E\r\n\r\n  \u003Cdiv class=\u0022note-warning\u0022\u003E\r\n  \u003Ch2\u003EBTW, this is not for production\u003C\/h2\u003E\r\n  \u003Cp\u003EThis module is intended for local development and regression testing only. Several submodules intentionally open admin routes to anonymous users, ship fixture content types and test data, or disable render caching. Do not install on a public site.\u003C\/p\u003E\r\n\u003C\/div\u003E\r\n\r\n\u003Cdiv class=\u0022note-version\u0022\u003E\r\n\u003Ch2\u003EHistory\u003C\/h2\u003E\r\n\r\n\u003Cp\u003EThis module was originally created by \u003Ca href=\u0022https:\/\/www.drupal.org\/u\/huzooka\u0022\u003EZoltan Horvath\u003C\/a\u003E as \u003Ca href=\u0022https:\/\/github.com\/zolhorvath\/cd_tools\u0022\u003Ecd_tools\u003C\/a\u003E to support development of the Claro admin theme. It has since been renamed and generalized into a theme-agnostic test harness for any Drupal admin theme.\u003C\/p\u003E\r\n\u003C\/div\u003E\r\n\r\n","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003EA suite of test modules for Drupal admin theme development. Each submodule exercises one UI component or form pattern \u2014 buttons, dialogs, tables, form widgets, pagers, tabs, and so on \u2014 across multiple themes so regressions can be spotted visually.\u003C\/p\u003E\n\u003Cp\u003ENone of the test pages are theme-specific \u2014 each renders in whatever theme is active, so the suite works equally well against Claro, Admin, Olivero, Stark, and any contrib or custom admin theme. The whole point is to surface cross-theme rendering differences.\u003C\/p\u003E\n\u003Cdiv class=\u0022note-warning\u0022\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022not-for-production\u0022\u003ENot for production\u003C\/h2\u003E\n\u003Cp\u003EThis module is intended for local development and regression testing only. Several submodules intentionally open admin routes to anonymous users, ship fixture content types and test data, or disable render caching. Do not install on a public site.\u003C\/p\u003E\n\u003C\/div\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022features\u0022\u003EFeatures\u003C\/h2\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EDashboard\u003C\/strong\u003E at \u003Ccode\u003E\/admin\/modules\/theming-tools\u003C\/code\u003E listing every test submodule with enable\/disable operations and bulk actions.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ENavigation drawer\u003C\/strong\u003E \u2014 a \u0022Theming Tools\u0022 expandable group auto-injected into the admin menu. Every enabled test submodule\u0027s page appears here automatically, sorted alphabetically.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EAuto-discovery\u003C\/strong\u003E \u2014 submodules tagged \u003Ccode\u003Etheming_test: true\u003C\/code\u003E are picked up by the dashboard and navigation drawer with zero configuration.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003E3 test themes\u003C\/strong\u003E \u2014 fixture themes for the Appearance admin page, including an intentionally incompatible theme for testing that code path.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cdiv class=\u0022note-warning\u0022\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022not-for-production-damnit\u0022\u003ENot for production damnit!\u003C\/h2\u003E\n\u003Cp\u003EThis module is intended for local development and regression testing only. Several submodules intentionally open admin routes to anonymous users, ship fixture content types and test data, or disable render caching. Do not install on a public site.\u003C\/p\u003E\n\u003C\/div\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022included-submodules\u0022\u003EIncluded submodules\u003C\/h2\u003E\n\u003Ctable\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eactionlink\u003C\/td\u003E\n\u003Ctd\u003EAction Link component\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eautocomplete\u003C\/td\u003E\n\u003Ctd\u003EAutocomplete form widget\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ebutton\u003C\/td\u003E\n\u003Ctd\u003EButtons and button links (primary, secondary, small variants)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecard\u003C\/td\u003E\n\u003Ctd\u003ECard component (appearance admin page)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Echeckboxradio\u003C\/td\u003E\n\u003Ctd\u003ECheckboxes and radios on a contact form\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Edetails\u003C\/td\u003E\n\u003Ctd\u003EDetails element (site information form)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Edevhelp\u003C\/td\u003E\n\u003Ctd\u003EDisables render caching and enables debug mode\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Edialog\u003C\/td\u003E\n\u003Ctd\u003ERegular, modal, off-canvas, and off-canvas-top dialogs\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Edropbutton\u003C\/td\u003E\n\u003Ctd\u003EDropbutton \/ Operations component\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eexposed_form\u003C\/td\u003E\n\u003Ctd\u003EViews exposed form and bulk operations\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Efieldcardinality\u003C\/td\u003E\n\u003Ctd\u003EMulti-cardinality field widgets\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Efieldset\u003C\/td\u003E\n\u003Ctd\u003EFieldset component\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eimagefile\u003C\/td\u003E\n\u003Ctd\u003EImage and managed file form widgets\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Elang_hebrew\u003C\/td\u003E\n\u003Ctd\u003EHebrew language + language switcher for RTL tests\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Emessage\u003C\/td\u003E\n\u003Ctd\u003EMessage component and Drupal.Message JS API\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Epager\u003C\/td\u003E\n\u003Ctd\u003EPagers (via Views)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Epassword\u003C\/td\u003E\n\u003Ctd\u003EPassword-confirm widget\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Epointertracker\u003C\/td\u003E\n\u003Ctd\u003ECrosshair overlay following mouse\/touch pointer\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Epresuf\u003C\/td\u003E\n\u003Ctd\u003EForm item prefixes and suffixes\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eprogress\u003C\/td\u003E\n\u003Ctd\u003EProgress indicators (throbber, progress bar, fullscreen)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eselect\u003C\/td\u003E\n\u003Ctd\u003ESingle- and multi-value select widgets\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Esidebar\u003C\/td\u003E\n\u003Ctd\u003EEntity meta sidebar\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etab\u003C\/td\u003E\n\u003Ctd\u003ELocal task tabs\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etable\u003C\/td\u003E\n\u003Ctd\u003ETable component (sortable, selectable, responsive)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etabledrag\u003C\/td\u003E\n\u003Ctd\u003EDraggable tables (nested hierarchy, mixed-height rows)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etestfilters\u003C\/td\u003E\n\u003Ctd\u003EText formats and CKEditor 5 editor config\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etextarea\u003C\/td\u003E\n\u003Ctd\u003EPlain and formatted textarea widgets\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etextfixtures\u003C\/td\u003E\n\u003Ctd\u003EColor, password, and search field types\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etextform\u003C\/td\u003E\n\u003Ctd\u003EText-like form items (textfield, telephone, email, url, datetime)\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ethemeswitcher\u003C\/td\u003E\n\u003Ctd\u003EFooter form to switch active theme via cookie\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Etitle_shortcut\u003C\/td\u003E\n\u003Ctd\u003EPage titles alongside shortcut badges\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ett_navigation\u003C\/td\u003E\n\u003Ctd\u003ECore Navigation block rendering\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ett_node\u003C\/td\u003E\n\u003Ctd\u003EMinimal test content type used as a fixture\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evertical_tabs\u003C\/td\u003E\n\u003Ctd\u003EVertical Tabs component\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003C\/table\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022installation\u0022\u003EInstallation\u003C\/h2\u003E\n\u003Cpre\u003E\u003Ccode\u003Edrush en theming_tools\n  # then enable specific test submodules as needed:\n  drush en button dialog table tabledrag dropbutton textform textarea\n  \u003C\/code\u003E\u003C\/pre\u003E\u003Cp\u003EOr enable everything at once through the dashboard at \u003Ccode\u003E\/admin\/modules\/theming-tools\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003ESome submodules depend on the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/contact\u0022 rel=\u0022nofollow\u0022\u003EContact\u003C\/a\u003E contrib module (moved out of core in Drupal 11). If it isn\u0027t installed, those submodules simply won\u0027t enable; everything else works without it.\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022drupal-version-support\u0022\u003EDrupal version support\u003C\/h2\u003E\n\u003Cp\u003ESupports Drupal 10.3, 11, and 12. Actively tested against the \u003Ccode\u003Emain\u003C\/code\u003E branch of Drupal core.\u003C\/p\u003E\n\u003Cdiv class=\u0022note-warning\u0022\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022btw-this-is-not-for-production\u0022\u003EBTW, this is not for production\u003C\/h2\u003E\n\u003Cp\u003EThis module is intended for local development and regression testing only. Several submodules intentionally open admin routes to anonymous users, ship fixture content types and test data, or disable render caching. Do not install on a public site.\u003C\/p\u003E\n\u003C\/div\u003E\n\u003Cdiv class=\u0022note-version\u0022\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022history\u0022\u003EHistory\u003C\/h2\u003E\n\u003Cp\u003EThis module was originally created by \u003Ca href=\u0022https:\/\/www.drupal.org\/u\/huzooka\u0022 rel=\u0022nofollow\u0022\u003EZoltan Horvath\u003C\/a\u003E as \u003Ca href=\u0022https:\/\/github.com\/zolhorvath\/cd_tools\u0022 rel=\u0022nofollow\u0022\u003Ecd_tools\u003C\/a\u003E to support development of the Claro admin theme. It has since been renamed and generalized into a theme-agnostic test harness for any Drupal admin theme.\u003C\/p\u003E\n\u003C\/div\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"theming_tools","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"c3547638-ecdf-4857-b728-c496f8bb07f8","meta":{"drupal_internal__target_id":118428}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/uid?resourceVersion=id%3A21791916"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/relationships\/uid?resourceVersion=id%3A21791916"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/field_development_status?resourceVersion=id%3A21791916"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/relationships\/field_development_status?resourceVersion=id%3A21791916"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/field_maintenance_status?resourceVersion=id%3A21791916"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/relationships\/field_maintenance_status?resourceVersion=id%3A21791916"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"086cebcf-200f-4c34-886e-f9921919b292","meta":{"drupal_internal__target_id":189}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/field_module_categories?resourceVersion=id%3A21791916"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/relationships\/field_module_categories?resourceVersion=id%3A21791916"}}},"field_project_images":{"data":[{"type":"file--file","id":"01d9dca7-da11-44b3-8f52-d907e114184c","meta":{"alt":"Screenshot of navigation menu open showing various links to theming tools","title":null,"width":1159,"height":785,"drupal_internal__target_id":1461094}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/field_project_images?resourceVersion=id%3A21791916"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/0a66d43b-caf8-4c41-96ef-9fd4efd19719\/relationships\/field_project_images?resourceVersion=id%3A21791916"}}}}},{"type":"node--project_module","id":"53654787-6a15-45ac-8a18-590d848df091","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091?resourceVersion=id%3A21791820"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583875,"status":true,"title":"Display Mode Switcher","created":"2026-04-09T09:38:36+00:00","changed":"2026-04-09T09:38:36+00:00","moderation_state":null,"body":{"value":"\u003Cp\u003E\r\n    \u003Cstrong\u003EDisplay Mode Switcher\u003C\/strong\u003E lets you show different field layouts to different audiences - no templates, no custom code, just configuration.\r\n  \u003C\/p\u003E\r\n  \u003Cp\u003E\r\n    The classic use case is a paywall: anonymous visitors see a teaser or locked version of content, while subscribers see the full article. But the module works for any scenario where different users (or different contexts) should see a different arrangement of fields.\r\n  \u003C\/p\u003E\r\n  \u003Cp\u003E\r\n    You define \u003Cstrong\u003Erules\u003C\/strong\u003E that specify: which entity and display mode you are starting from, which display mode to switch to, and what conditions must be true for the switch to happen. At render time the module evaluates your rules in order, picks the first match, and swaps the display mode transparently. If no rule matches, the original display mode is used unchanged.\r\n  \u003C\/p\u003E\r\n  \u003Cp\u003E\r\n    Drupal\u0027s render cache is fully respected: cache metadata from every evaluated condition is propagated to the rendered output automatically.\r\n  \u003C\/p\u003E\r\n\r\n  \u003Ch3 id=\u0022module-project--features\u0022\u003EFeatures\u003C\/h3\u003E\r\n  \u003Cul\u003E\r\n    \u003Cli\u003ESwitch any entity\u0027s view mode at render time based on configurable rules - no template overrides needed.\u003C\/li\u003E\r\n    \u003Cli\u003ERule-based evaluation with \u003Cstrong\u003Eweight-ordered priority\u003C\/strong\u003E: the first matching rule wins, making it easy to build subscriber\/anonymous\/admin hierarchies.\u003C\/li\u003E\r\n    \u003Cli\u003EShips with a \u003Cstrong\u003EUser has role\u003C\/strong\u003E condition out of the box. All standard Drupal core condition plugins (node type, language, request path, current theme) work automatically.\u003C\/li\u003E\r\n    \u003Cli\u003EAny contrib module that provides condition plugins is supported automatically - no extra wiring.\u003C\/li\u003E\r\n    \u003Cli\u003E\u003Cstrong\u003ECustom condition plugins\u003C\/strong\u003E can be added by any module via a simple PHP class and a config schema entry.\u003C\/li\u003E\r\n    \u003Cli\u003EConditions receive the entity being rendered directly, so field-level checks (e.g. \u0022is this node marked as paywalled?\u0022) require no Context API  setup.\u003C\/li\u003E\r\n    \u003Cli\u003ECache tags, cache contexts, and max-age from all evaluated conditions are merged into the render array automatically.\u003C\/li\u003E\r\n    \u003Cli\u003ERules are standard \u003Cstrong\u003Econfiguration entities\u003C\/strong\u003E: fully exportable, deployable via \u003Ccode\u003Edrush config:export\/import\u003C\/code\u003E, and  version-controllable.\u003C\/li\u003E\r\n    \u003Cli\u003EA single permission (\u003Ccode\u003Eadminister display mode switcher\u003C\/code\u003E) controls access to rule management.\u003C\/li\u003E\r\n  \u003C\/ul\u003E\r\n\r\n  \u003Ch3 id=\u0022module-project--post-installation\u0022\u003EPost-Installation\u003C\/h3\u003E\r\n  \u003Cp\u003EAfter enabling the module:\u003C\/p\u003E\r\n  \u003Col\u003E\r\n    \u003Cli\u003E\r\n      \u003Cstrong\u003ECreate the view mode you want to switch to.\u003C\/strong\u003E Go to \u003Cem\u003EStructure \u2192 Display modes \u2192 View modes\u003C\/em\u003E, add a new view mode for your\r\n  entity type (e.g. \u003Ccode\u003Epaywall\u003C\/code\u003E), then go to the entity type\u0027s \u003Cem\u003EManage display\u003C\/em\u003E page, enable the new view mode under \u003Cem\u003ECustom display\r\n  settings\u003C\/em\u003E, and configure which fields it shows.\r\n    \u003C\/li\u003E\r\n    \u003Cli\u003E\r\n      \u003Cstrong\u003ECreate a rule.\u003C\/strong\u003E Go to \u003Cem\u003EStructure \u2192 Display modes \u2192 View modes \u2192 Switcher rules\u003C\/em\u003E\r\n  (\u003Ccode\u003E\/admin\/structure\/display-modes\/view\/switcher\u003C\/code\u003E) and click \u003Cem\u003EAdd rule\u003C\/em\u003E. Choose the entity type and (optionally) bundle, set the source\r\n  display mode that triggers evaluation (e.g. \u003Ccode\u003Efull\u003C\/code\u003E), set the target display mode to switch to (e.g. \u003Ccode\u003Epaywall\u003C\/code\u003E), and add one or\r\n  more conditions. A rule with no conditions always matches \u2014 useful as a catch-all fallback at a high weight.\r\n    \u003C\/li\u003E\r\n    \u003Cli\u003E\r\n      \u003Cstrong\u003ETest.\u003C\/strong\u003E Render the entity in the source display mode as a user who meets the conditions and verify the correct display mode appears.\r\n  Then test as a user who does not meet the conditions.\r\n    \u003C\/li\u003E\r\n  \u003C\/ol\u003E\r\n  \u003Cp\u003ENo database updates are needed. All configuration lives in YAML files and can be managed with Config Management (\u003Ccode\u003Edrush config:export\u003C\/code\u003E).\u003C\/p\u003E\r\n\r\n  \u003Ch3 id=\u0022module-project--additional-requirements\u0022\u003EAdditional Requirements\u003C\/h3\u003E\r\n  \u003Cul\u003E\r\n    \u003Cli\u003EDrupal 11.3 or later\u003C\/li\u003E\r\n    \u003Cli\u003ENo additional module dependencies beyond Drupal core.\u003C\/li\u003E\r\n  \u003C\/ul\u003E\r\n\r\n  \u003Ch3 id=\u0022module-project--similar-projects\u0022\u003ESimilar projects\u003C\/h3\u003E\r\n  \u003Cul\u003E\r\n    \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/view_mode_page\u0022\u003EView Mode Page\u003C\/a\u003E - serves an entity under a custom URL using a specific view mode,\r\n  rather than switching modes conditionally at render time.\u003C\/li\u003E\r\n    \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/ds\u0022\u003EDisplay Suite\u003C\/a\u003E - powerful field layout builder that works well alongside this module; it does not provide rule-based mode switching.\u003C\/li\u003E\r\n    \u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/content_access\u0022\u003EContent Access\u003C\/a\u003E \/ \u003Ca \r\n  href=\u0022https:\/\/www.drupal.org\/project\/permissions_by_term\u0022\u003EPermissions by Term\u003C\/a\u003E - restrict access entirely rather than showing a degraded view to unauthorised users. Use Display Mode Switcher when you want a teaser or locked layout instead of an access denied page.\u003C\/li\u003E\r\n  \u003C\/ul\u003E","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003E\n    \u003Cstrong\u003EDisplay Mode Switcher\u003C\/strong\u003E lets you show different field layouts to different audiences - no templates, no custom code, just configuration.\n  \u003C\/p\u003E\n\u003Cp\u003E\n    The classic use case is a paywall: anonymous visitors see a teaser or locked version of content, while subscribers see the full article. But the module works for any scenario where different users (or different contexts) should see a different arrangement of fields.\n  \u003C\/p\u003E\n\u003Cp\u003E\n    You define \u003Cstrong\u003Erules\u003C\/strong\u003E that specify: which entity and display mode you are starting from, which display mode to switch to, and what conditions must be true for the switch to happen. At render time the module evaluates your rules in order, picks the first match, and swaps the display mode transparently. If no rule matches, the original display mode is used unchanged.\n  \u003C\/p\u003E\n\u003Cp\u003E\n    Drupal\u0027s render cache is fully respected: cache metadata from every evaluated condition is propagated to the rendered output automatically.\n  \u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--features-01\u0022\u003EFeatures\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003ESwitch any entity\u0027s view mode at render time based on configurable rules - no template overrides needed.\u003C\/li\u003E\n\u003Cli\u003ERule-based evaluation with \u003Cstrong\u003Eweight-ordered priority\u003C\/strong\u003E: the first matching rule wins, making it easy to build subscriber\/anonymous\/admin hierarchies.\u003C\/li\u003E\n\u003Cli\u003EShips with a \u003Cstrong\u003EUser has role\u003C\/strong\u003E condition out of the box. All standard Drupal core condition plugins (node type, language, request path, current theme) work automatically.\u003C\/li\u003E\n\u003Cli\u003EAny contrib module that provides condition plugins is supported automatically - no extra wiring.\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ECustom condition plugins\u003C\/strong\u003E can be added by any module via a simple PHP class and a config schema entry.\u003C\/li\u003E\n\u003Cli\u003EConditions receive the entity being rendered directly, so field-level checks (e.g. \u0022is this node marked as paywalled?\u0022) require no Context API  setup.\u003C\/li\u003E\n\u003Cli\u003ECache tags, cache contexts, and max-age from all evaluated conditions are merged into the render array automatically.\u003C\/li\u003E\n\u003Cli\u003ERules are standard \u003Cstrong\u003Econfiguration entities\u003C\/strong\u003E: fully exportable, deployable via \u003Ccode\u003Edrush config:export\/import\u003C\/code\u003E, and  version-controllable.\u003C\/li\u003E\n\u003Cli\u003EA single permission (\u003Ccode\u003Eadminister display mode switcher\u003C\/code\u003E) controls access to rule management.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--post-installation-01\u0022\u003EPost-Installation\u003C\/h3\u003E\n\u003Cp\u003EAfter enabling the module:\u003C\/p\u003E\n\u003Col\u003E\n\u003Cli\u003E\n      \u003Cstrong\u003ECreate the view mode you want to switch to.\u003C\/strong\u003E Go to \u003Cem\u003EStructure \u2192 Display modes \u2192 View modes\u003C\/em\u003E, add a new view mode for your\u003Cbr\u003E\n  entity type (e.g. \u003Ccode\u003Epaywall\u003C\/code\u003E), then go to the entity type\u0027s \u003Cem\u003EManage display\u003C\/em\u003E page, enable the new view mode under \u003Cem\u003ECustom display\u003Cbr\u003E\n  settings\u003C\/em\u003E, and configure which fields it shows.\n    \u003C\/li\u003E\n\u003Cli\u003E\n      \u003Cstrong\u003ECreate a rule.\u003C\/strong\u003E Go to \u003Cem\u003EStructure \u2192 Display modes \u2192 View modes \u2192 Switcher rules\u003C\/em\u003E\u003Cbr\u003E\n  (\u003Ccode\u003E\/admin\/structure\/display-modes\/view\/switcher\u003C\/code\u003E) and click \u003Cem\u003EAdd rule\u003C\/em\u003E. Choose the entity type and (optionally) bundle, set the source\u003Cbr\u003E\n  display mode that triggers evaluation (e.g. \u003Ccode\u003Efull\u003C\/code\u003E), set the target display mode to switch to (e.g. \u003Ccode\u003Epaywall\u003C\/code\u003E), and add one or\u003Cbr\u003E\n  more conditions. A rule with no conditions always matches \u2014 useful as a catch-all fallback at a high weight.\n    \u003C\/li\u003E\n\u003Cli\u003E\n      \u003Cstrong\u003ETest.\u003C\/strong\u003E Render the entity in the source display mode as a user who meets the conditions and verify the correct display mode appears.\u003Cbr\u003E\n  Then test as a user who does not meet the conditions.\n    \u003C\/li\u003E\n\u003C\/ol\u003E\n\u003Cp\u003ENo database updates are needed. All configuration lives in YAML files and can be managed with Config Management (\u003Ccode\u003Edrush config:export\u003C\/code\u003E).\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--additional-requirements-01\u0022\u003EAdditional Requirements\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003EDrupal 11.3 or later\u003C\/li\u003E\n\u003Cli\u003ENo additional module dependencies beyond Drupal core.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3 id=\u0022module-project--similar-projects-01\u0022\u003ESimilar projects\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/view_mode_page\u0022 rel=\u0022nofollow\u0022\u003EView Mode Page\u003C\/a\u003E - serves an entity under a custom URL using a specific view mode,\u003Cbr\u003E\n  rather than switching modes conditionally at render time.\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/ds\u0022 rel=\u0022nofollow\u0022\u003EDisplay Suite\u003C\/a\u003E - powerful field layout builder that works well alongside this module; it does not provide rule-based mode switching.\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/content_access\u0022 rel=\u0022nofollow\u0022\u003EContent Access\u003C\/a\u003E \/ \u003Ca rel=\u0022nofollow\u0022\u003E\n  href=\u0022\u003Ca href=\u0022https:\/\/www.drupal.org\/project\/permissions_by_term\u0022 rel=\u0022nofollow\u0022\u003Ehttps:\/\/www.drupal.org\/project\/permissions_by_term\u003C\/a\u003E\u0022\u0026gt;Permissions by Term\u003C\/a\u003E - restrict access entirely rather than showing a degraded view to unauthorised users. Use Display Mode Switcher when you want a teaser or locked layout instead of an access denied page.\u003C\/li\u003E\n\u003C\/ul\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"display_mode_switcher","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"d912db4b-2d93-4c7f-a1ce-75636a500aa4","meta":{"drupal_internal__target_id":1532844}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/uid?resourceVersion=id%3A21791820"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/relationships\/uid?resourceVersion=id%3A21791820"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/field_development_status?resourceVersion=id%3A21791820"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/relationships\/field_development_status?resourceVersion=id%3A21791820"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"cee844e2-68b5-489d-bafa-6a0ade2b6dfd","meta":{"drupal_internal__target_id":27273}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/field_maintenance_status?resourceVersion=id%3A21791820"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/relationships\/field_maintenance_status?resourceVersion=id%3A21791820"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"754c04cb-6da2-42ba-9032-d64307f68f45","meta":{"drupal_internal__target_id":188}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/field_module_categories?resourceVersion=id%3A21791820"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/relationships\/field_module_categories?resourceVersion=id%3A21791820"}}},"field_project_images":{"data":[],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/field_project_images?resourceVersion=id%3A21791820"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/53654787-6a15-45ac-8a18-590d848df091\/relationships\/field_project_images?resourceVersion=id%3A21791820"}}}}},{"type":"node--project_module","id":"9eb96260-6cbe-4d1f-b947-62aa5df9ac02","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02?resourceVersion=id%3A21791811"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583870,"status":true,"title":"Views area wrapper","created":"2026-04-09T09:20:51+00:00","changed":"2026-04-09T09:20:51+00:00","moderation_state":null,"body":{"value":"This simple module just wraps Views areas (header, footer, no results behavior) in a views_area Drupal template. \r\n\r\nEnabling it does not change the HTML output, but it adds various template suggestions which ease theming by enabling specific area targeting in template overrides, as it can be done for fields in core for example.","format":"1","processed":"\u003Cp\u003EThis simple module just wraps Views areas (header, footer, no results behavior) in a views_area Drupal template. \u003C\/p\u003E\n\u003Cp\u003EEnabling it does not change the HTML output, but it adds various template suggestions which ease theming by enabling specific area targeting in template overrides, as it can be done for fields in core for example.\u003C\/p\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"views_area_wrapper","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"e86679e2-10de-49b9-a48a-9b38f6469632","meta":{"drupal_internal__target_id":431210}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/uid?resourceVersion=id%3A21791811"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/relationships\/uid?resourceVersion=id%3A21791811"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"219c1cf2-dd7f-474b-9dd5-a26643fbc699","meta":{"drupal_internal__target_id":27276}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/field_development_status?resourceVersion=id%3A21791811"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/relationships\/field_development_status?resourceVersion=id%3A21791811"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"cee844e2-68b5-489d-bafa-6a0ade2b6dfd","meta":{"drupal_internal__target_id":27273}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/field_maintenance_status?resourceVersion=id%3A21791811"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/relationships\/field_maintenance_status?resourceVersion=id%3A21791811"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"754c04cb-6da2-42ba-9032-d64307f68f45","meta":{"drupal_internal__target_id":188}},{"type":"taxonomy_term--module_categories","id":"086cebcf-200f-4c34-886e-f9921919b292","meta":{"drupal_internal__target_id":189}},{"type":"taxonomy_term--module_categories","id":"dcb48e9f-6afa-4842-8ef6-44b90b083fcc","meta":{"drupal_internal__target_id":200}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/field_module_categories?resourceVersion=id%3A21791811"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/relationships\/field_module_categories?resourceVersion=id%3A21791811"}}},"field_project_images":{"data":[],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/field_project_images?resourceVersion=id%3A21791811"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9eb96260-6cbe-4d1f-b947-62aa5df9ac02\/relationships\/field_project_images?resourceVersion=id%3A21791811"}}}}},{"type":"node--project_module","id":"9a81b520-e865-4622-9b27-4ef2f8718669","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669?resourceVersion=id%3A21791810"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583862,"status":true,"title":"Language Switcher Dialog","created":"2026-04-09T09:08:12+00:00","changed":"2026-04-09T13:38:26+00:00","moderation_state":null,"body":{"value":"\u003Cp\u003EA modern language switcher for Drupal that replaces the default language block with a \u003Cstrong\u003Etrigger button + modal dialog\u003C\/strong\u003E pattern. Built on the native HTML \u003Ccode\u003E\u003Cdialog\u003E\u003C\/code\u003E element and Drupal core\u0027s HTMX integration. No jQuery UI, no custom focus-trap libraries, no JavaScript frameworks.\u003C\/p\u003E\r\n\u003Ch2\u003EHow it works\u003C\/h2\u003E\r\n\u003Cp\u003EThe module places a block with a compact trigger button showing the current language. Clicking it opens a modal dialog that loads language switch links via HTMX. The dialog content is lazy-loaded as an HTML fragment: no JSON, no client-side rendering.\u003C\/p\u003E\r\n\u003Ch2\u003EKey features\u003C\/h2\u003E\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003ENative \u003Ccode\u003E\u003Cdialog\u003E\u003C\/code\u003E\u003C\/strong\u003E with \u003Ccode\u003EshowModal()\u003C\/code\u003E: built-in focus trapping, Escape key dismissal, and background inertness without custom JavaScript\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EHTMX-powered\u003C\/strong\u003E: uses Drupal 11.3\u0027s \u003Ccode\u003Ecore\/drupal.htmx\u003C\/code\u003E library for server-rendered HTML fragment loading\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EPluggable dialog content\u003C\/strong\u003E: a Drupal plugin system lets you swap out how language links are rendered, or create your own\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003ENo CSS by default\u003C\/strong\u003E: bring your own theme styles. An optional \u0022classic dialog\u0022 CSS library is included for quick prototyping\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EAccessible\u003C\/strong\u003E: Designed for \u003Cstrong\u003EWCAG 2.2 AA compliance\u003C\/strong\u003E out of the box. Proper focus management, ARIA attributes, \u003Ccode\u003Ehreflang\u003C\/code\u003E\/\u003Ccode\u003Elang\u003C\/code\u003E on links, CSS \u003Ccode\u003Etext-transform\u003C\/code\u003E for uppercase, \u003Ccode\u003Eprefers-reduced-motion\u003C\/code\u003E and \u003Ccode\u003Eforced-colors\u003C\/code\u003E support\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\u003Ch2\u003EIncluded submodules\u003C\/h2\u003E\r\n\u003Ch3\u003ELanguage Switcher Dialog: Countries\u003C\/h3\u003E\r\n\u003Cp\u003EMaps languages to countries and world regions. Adds country code, base language code, and region fields to each language configuration entity.\u003C\/p\u003E\r\n\u003Cp\u003EShips two dialog content provider plugins:\u003C\/p\u003E\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EEnhanced links\u003C\/strong\u003E: a flat list of language links enriched with country names and optional flag icons\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EGrouped by region\u003C\/strong\u003E: languages organized under region headings (Europe, Asia, etc.)\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\u003Cp\u003EAlso adds country-aware trigger button formats (e.g. \u0022BE - NL\u0022, \u0022Belgium - Dutch\u0022) and extends the trigger with optional flag icons.\u003C\/p\u003E\r\n\u003Cp\u003ERequires the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/country\u0022\u003ECountry\u003C\/a\u003E module. Optionally integrates with \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/flags\u0022\u003EFlags\u003C\/a\u003E for country flag icons.\u003C\/p\u003E\r\n\u003Ch3\u003ELanguage Switcher Dialog: GeoIP\u003C\/h3\u003E\r\n\u003Cp\u003EShows a one-time language suggestion popup for first-time visitors based on their IP-detected country. The popup is loaded via HTMX, uses a server-side cookie check to avoid repeat prompts, and includes configurable bot detection to skip search engine crawlers.\u003C\/p\u003E\r\n\u003Cp\u003ERequires the Countries submodule and \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/smart_ip\u0022\u003ESmart IP\u003C\/a\u003E.\u003C\/p\u003E\r\n\u003Ch2\u003ERequirements\u003C\/h2\u003E\r\n\u003Cul\u003E\r\n  \u003Cli\u003EDrupal 11.3+ (for core HTMX support)\u003C\/li\u003E\r\n  \u003Cli\u003EPHP 8.3+\u003C\/li\u003E\r\n  \u003Cli\u003ECore Language module with two or more languages configured\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\u003Ch2\u003EExtending\u003C\/h2\u003E\r\n\u003Cp\u003EThe module is designed to be extended:\u003C\/p\u003E\r\n\u003Cul\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EDialog content provider plugins\u003C\/strong\u003E: drop a plugin class in \u003Ccode\u003EPlugin\/DialogContentProvider\/\u003C\/code\u003E and it\u0027s auto-discovered in the settings form\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003EAlter hooks\u003C\/strong\u003E: customize trigger button formats, world regions, GeoIP bot patterns, and plugin definitions\u003C\/li\u003E\r\n  \u003Cli\u003E\u003Cstrong\u003ETemplate overrides\u003C\/strong\u003E: all templates follow standard Drupal theme suggestion patterns\u003C\/li\u003E\r\n\u003C\/ul\u003E\r\n\u003Cp\u003ESee \u003Ccode\u003Elanguage_switcher_dialog.api.php\u003C\/code\u003E for documented hook signatures.\u003C\/p\u003E\r\n\r\n\u003Cdiv class=\u0022warning\u0022\u003E\r\n\u003Ch4\u003E\ud83e\udd16 Assisted Development\u003C\/h4\u003E\r\n\u003Cp\u003EThis module is maintained with the help of AI assistants for code generation, review, testing, and documentation. All code is carefully reviewed by the maintainers  to ensure that quality and security standards are met.\u003C\/p\u003E\r\n\u003C\/div\u003E","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003EA modern language switcher for Drupal that replaces the default language block with a \u003Cstrong\u003Etrigger button + modal dialog\u003C\/strong\u003E pattern. Built on the native HTML \u003Ccode\u003E\u003C\/code\u003E element and Drupal core\u0027s HTMX integration. No jQuery UI, no custom focus-trap libraries, no JavaScript frameworks.\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022how-it-works\u0022\u003EHow it works\u003C\/h2\u003E\n\u003Cp\u003EThe module places a block with a compact trigger button showing the current language. Clicking it opens a modal dialog that loads language switch links via HTMX. The dialog content is lazy-loaded as an HTML fragment: no JSON, no client-side rendering.\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022key-features\u0022\u003EKey features\u003C\/h2\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003ENative \u003Ccode\u003E\u003C\/code\u003E\u003C\/strong\u003E with \u003Ccode\u003EshowModal()\u003C\/code\u003E: built-in focus trapping, Escape key dismissal, and background inertness without custom JavaScript\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EHTMX-powered\u003C\/strong\u003E: uses Drupal 11.3\u0027s \u003Ccode\u003Ecore\/drupal.htmx\u003C\/code\u003E library for server-rendered HTML fragment loading\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EPluggable dialog content\u003C\/strong\u003E: a Drupal plugin system lets you swap out how language links are rendered, or create your own\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ENo CSS by default\u003C\/strong\u003E: bring your own theme styles. An optional \u0022classic dialog\u0022 CSS library is included for quick prototyping\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EAccessible\u003C\/strong\u003E: Designed for \u003Cstrong\u003EWCAG 2.2 AA compliance\u003C\/strong\u003E out of the box. Proper focus management, ARIA attributes, \u003Ccode\u003Ehreflang\u003C\/code\u003E\/\u003Ccode\u003Elang\u003C\/code\u003E on links, CSS \u003Ccode\u003Etext-transform\u003C\/code\u003E for uppercase, \u003Ccode\u003Eprefers-reduced-motion\u003C\/code\u003E and \u003Ccode\u003Eforced-colors\u003C\/code\u003E support\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022included-submodules\u0022\u003EIncluded submodules\u003C\/h2\u003E\n\u003Ch3 id=\u0022language-switcher-dialog-countries\u0022\u003ELanguage Switcher Dialog: Countries\u003C\/h3\u003E\n\u003Cp\u003EMaps languages to countries and world regions. Adds country code, base language code, and region fields to each language configuration entity.\u003C\/p\u003E\n\u003Cp\u003EShips two dialog content provider plugins:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EEnhanced links\u003C\/strong\u003E: a flat list of language links enriched with country names and optional flag icons\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EGrouped by region\u003C\/strong\u003E: languages organized under region headings (Europe, Asia, etc.)\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAlso adds country-aware trigger button formats (e.g. \u0022BE - NL\u0022, \u0022Belgium - Dutch\u0022) and extends the trigger with optional flag icons.\u003C\/p\u003E\n\u003Cp\u003ERequires the \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/country\u0022 rel=\u0022nofollow\u0022\u003ECountry\u003C\/a\u003E module. Optionally integrates with \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/flags\u0022 rel=\u0022nofollow\u0022\u003EFlags\u003C\/a\u003E for country flag icons.\u003C\/p\u003E\n\u003Ch3 id=\u0022language-switcher-dialog-geoip\u0022\u003ELanguage Switcher Dialog: GeoIP\u003C\/h3\u003E\n\u003Cp\u003EShows a one-time language suggestion popup for first-time visitors based on their IP-detected country. The popup is loaded via HTMX, uses a server-side cookie check to avoid repeat prompts, and includes configurable bot detection to skip search engine crawlers.\u003C\/p\u003E\n\u003Cp\u003ERequires the Countries submodule and \u003Ca href=\u0022https:\/\/www.drupal.org\/project\/smart_ip\u0022 rel=\u0022nofollow\u0022\u003ESmart IP\u003C\/a\u003E.\u003C\/p\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022requirements\u0022\u003ERequirements\u003C\/h2\u003E\n\u003Cul\u003E\n\u003Cli\u003EDrupal 11.3+ (for core HTMX support)\u003C\/li\u003E\n\u003Cli\u003EPHP 8.3+\u003C\/li\u003E\n\u003Cli\u003ECore Language module with two or more languages configured\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\n\n\u003Ch2 id=\u0022extending\u0022\u003EExtending\u003C\/h2\u003E\n\u003Cp\u003EThe module is designed to be extended:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Cstrong\u003EDialog content provider plugins\u003C\/strong\u003E: drop a plugin class in \u003Ccode\u003EPlugin\/DialogContentProvider\/\u003C\/code\u003E and it\u0027s auto-discovered in the settings form\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EAlter hooks\u003C\/strong\u003E: customize trigger button formats, world regions, GeoIP bot patterns, and plugin definitions\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003ETemplate overrides\u003C\/strong\u003E: all templates follow standard Drupal theme suggestion patterns\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003ESee \u003Ccode\u003Elanguage_switcher_dialog.api.php\u003C\/code\u003E for documented hook signatures.\u003C\/p\u003E\n\u003Cdiv\u003E\n\u003Ch4 id=\u0022assisted-development\u0022\u003E\ud83e\udd16 Assisted Development\u003C\/h4\u003E\n\u003Cp\u003EThis module is maintained with the help of AI assistants for code generation, review, testing, and documentation. All code is carefully reviewed by the maintainers  to ensure that quality and security standards are met.\u003C\/p\u003E\n\u003C\/div\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"language_switcher_dialog","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"cf195a19-00b6-4e02-aef7-5fe21d63b2df","meta":{"drupal_internal__target_id":35369}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/uid?resourceVersion=id%3A21791810"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/relationships\/uid?resourceVersion=id%3A21791810"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/field_development_status?resourceVersion=id%3A21791810"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/relationships\/field_development_status?resourceVersion=id%3A21791810"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/field_maintenance_status?resourceVersion=id%3A21791810"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/relationships\/field_maintenance_status?resourceVersion=id%3A21791810"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"3cf38e0a-d4b1-426d-9b8e-008e7a41cf8d","meta":{"drupal_internal__target_id":194}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/field_module_categories?resourceVersion=id%3A21791810"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/relationships\/field_module_categories?resourceVersion=id%3A21791810"}}},"field_project_images":{"data":[{"type":"file--file","id":"ecf9ba23-645a-44dc-9e8a-855e3b673278","meta":{"alt":"Language switcher dialog screenshot","title":null,"width":981,"height":776,"drupal_internal__target_id":1461041}},{"type":"file--file","id":"08005475-a8f4-462d-af74-350560b1d4a1","meta":{"alt":"Language switcher dialog GeoIP feature screenshot","title":null,"width":null,"height":null,"drupal_internal__target_id":1461052}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/field_project_images?resourceVersion=id%3A21791810"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/9a81b520-e865-4622-9b27-4ef2f8718669\/relationships\/field_project_images?resourceVersion=id%3A21791810"}}}}},{"type":"node--project_module","id":"70cc7cb3-2120-4ebd-a33b-54d447306e63","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63?resourceVersion=id%3A21791798"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583846,"status":true,"title":"Media on Demand","created":"2026-04-09T08:06:38+00:00","changed":"2026-04-09T08:06:38+00:00","moderation_state":null,"body":{"value":"This module is designed to assist with migration of media, particularly when migrating HTML-like content with references to media.\r\n\r\nThe basic premise is being able to turn something like this:\r\n\r\n\u003Ccode\u003E\u003Cimg src=\u0022puppy.jpg alt=\u0022...\u0022\u003E\u003C\/code\u003E\r\n\r\ninto this:\r\n\r\n\u003Ccode\u003E\u003Cdrupal-media uuid=\u00224bff6314-3bb8-4a4c-8049-20afdac121ef\u0022\u003E\u003C\/code\u003E\r\n\r\nThe mechanics of copying files, creating media entities and avoiding duplicates all happens behind the scenes.\r\n","format":"1","processed":"\u003Cp\u003EThis module is designed to assist with migration of media, particularly when migrating HTML-like content with references to media.\u003C\/p\u003E\n\u003Cp\u003EThe basic premise is being able to turn something like this:\u003C\/p\u003E\n\u003Cp\u003E\u003Ccode\u003E\u003Cimg src=\u0022\/core\/misc\/icons\/e32700\/error.svg\u0022 alt=\u0022Image removed.\u0022 title=\u0022This image has been removed. For security reasons, only images from the local domain are allowed.\u0022 height=\u002216\u0022 width=\u002216\u0022 class=\u0022filter-image-invalid\u0022\u003E\u003C\/code\u003E\u003C\/p\u003E\n\u003Cp\u003Einto this:\u003C\/p\u003E\n\u003Cp\u003E\u003Ccode\u003E\u003C\/code\u003E\u003C\/p\u003E\n\u003Cdrupal-media\u003E\n\nThe mechanics of copying files, creating media entities and avoiding duplicates all happens behind the scenes.\n\u003C\/drupal-media\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"media_on_demand","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"e52d9f9c-a96a-4167-b49a-69967157e171","meta":{"drupal_internal__target_id":375884}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/uid?resourceVersion=id%3A21791798"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/relationships\/uid?resourceVersion=id%3A21791798"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/field_development_status?resourceVersion=id%3A21791798"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/relationships\/field_development_status?resourceVersion=id%3A21791798"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/field_maintenance_status?resourceVersion=id%3A21791798"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/relationships\/field_maintenance_status?resourceVersion=id%3A21791798"}}},"field_module_categories":{"data":[{"type":"taxonomy_term--module_categories","id":"086cebcf-200f-4c34-886e-f9921919b292","meta":{"drupal_internal__target_id":189}}],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/field_module_categories?resourceVersion=id%3A21791798"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/relationships\/field_module_categories?resourceVersion=id%3A21791798"}}},"field_project_images":{"data":[],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/field_project_images?resourceVersion=id%3A21791798"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/70cc7cb3-2120-4ebd-a33b-54d447306e63\/relationships\/field_project_images?resourceVersion=id%3A21791798"}}}}},{"type":"node--project_module","id":"a551a0e5-af94-4e51-bb82-cda41c096f30","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30?resourceVersion=id%3A21791776"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__nid":3583837,"status":true,"title":"Agent Experience Interface","created":"2026-04-09T07:32:33+00:00","changed":"2026-04-09T07:35:20+00:00","moderation_state":null,"body":{"value":"Here, write an introduction that summarizes the purpose and function of this project with a focus on users brand new to Drupal. Answer the question: What solution does this module provide? The first 200 characters of this will be shown when browsing projects. Alternatively, you can click \u201cEdit summary\u201d above and enter the exact summary you want (it should be 200 characters or less).\r\n\r\n\u003Ch3 id=\u0022module-project--features\u0022\u003EFeatures\u003C\/h3\u003E\r\nHere, answer the following questions: What is the basic functionality? What unique features does enabling this project add? When and why would someone use this module? What use cases are there?\r\n\r\n\u003Ch3 id=\u0022module-project--post-installation\u0022\u003EPost-Installation\u003C\/h3\u003E\r\nHow does this module actually work once I install it? Should I go to a config page? Should I look for a new content type? Should I go and manage my text formats? Provide an overview of the configuration process and any other special considerations for the module.\r\n\r\n\u003Ch3 id=\u0022module-project--additional-requirements\u0022\u003EAdditional Requirements\u003C\/h3\u003E\r\nDoes this project need anything beyond Drupal core? Include any dependent modules, libraries, APIs, etc., that are required for this project to work.\r\n\r\n\u003Ch3 id=\u0022module-project--recommended-libraries\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E\r\nAre there any projects that enhance or improve the functionality of this project?\r\n\r\n\u003Ch3 id=\u0022module-project--similar-projects\u0022\u003ESimilar projects\u003C\/h3\u003E\r\nIf there are modules providing similar functionality, please describe what differentiates them.\r\n\r\n\u003Ch3 id=\u0022module-project--support\u0022\u003ESupporting this Module\u003C\/h3\u003E\r\nIf you have a Patreon, OpenCollective, etc. you can put links here to describe how people can support development. \r\n\r\n\u003Ch3 id=\u0022module-project--community-documentation\u0022\u003ECommunity Documentation\u003C\/h3\u003E\r\nA great place to add links to YouTube walkthroughs, external documentation, or a demo site (use DrupalPod!).\r\n\r\nYou may continue to put additional information below here, if there are other things you think people need to know about your module!","format":"1","processed":"\u003Cdiv class=\u0022toc-filter\u0022\u003E\u003Cp\u003EHere, write an introduction that summarizes the purpose and function of this project with a focus on users brand new to Drupal. Answer the question: What solution does this module provide? The first 200 characters of this will be shown when browsing projects. Alternatively, you can click \u201cEdit summary\u201d above and enter the exact summary you want (it should be 200 characters or less).\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--features-01\u0022\u003EFeatures\u003C\/h3\u003E\n\u003Cp\u003EHere, answer the following questions: What is the basic functionality? What unique features does enabling this project add? When and why would someone use this module? What use cases are there?\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--post-installation-01\u0022\u003EPost-Installation\u003C\/h3\u003E\n\u003Cp\u003EHow does this module actually work once I install it? Should I go to a config page? Should I look for a new content type? Should I go and manage my text formats? Provide an overview of the configuration process and any other special considerations for the module.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--additional-requirements-01\u0022\u003EAdditional Requirements\u003C\/h3\u003E\n\u003Cp\u003EDoes this project need anything beyond Drupal core? Include any dependent modules, libraries, APIs, etc., that are required for this project to work.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--recommended-libraries-01\u0022\u003ERecommended modules\/libraries\u003C\/h3\u003E\n\u003Cp\u003EAre there any projects that enhance or improve the functionality of this project?\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--similar-projects-01\u0022\u003ESimilar projects\u003C\/h3\u003E\n\u003Cp\u003EIf there are modules providing similar functionality, please describe what differentiates them.\u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--support-01\u0022\u003ESupporting this Module\u003C\/h3\u003E\n\u003Cp\u003EIf you have a Patreon, OpenCollective, etc. you can put links here to describe how people can support development. \u003C\/p\u003E\n\u003Ch3 id=\u0022module-project--community-documentation-01\u0022\u003ECommunity Documentation\u003C\/h3\u003E\n\u003Cp\u003EA great place to add links to YouTube walkthroughs, external documentation, or a demo site (use DrupalPod!).\u003C\/p\u003E\n\u003Cp\u003EYou may continue to put additional information below here, if there are other things you think people need to know about your module!\u003C\/p\u003E\u003Ca href=\u0022#top\u0022 class=\u0022back-to-top\u0022\u003EBack to top\u003C\/a\u003E\u003C\/div\u003E","summary":""},"field_active_installs":null,"field_active_installs_total":null,"field_composer_namespace":null,"field_core_semver_maximum":null,"field_core_semver_minimum":null,"field_issue_summary_template":null,"field_logo_url":null,"field_project_has_releases":true,"field_project_machine_name":"axi","field_security_advisory_coverage":"not-covered"},"relationships":{"uid":{"data":{"type":"user--user","id":"d225fac6-5c5b-42fe-8cd5-80d272f1aec0","meta":{"drupal_internal__target_id":3506581}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/uid?resourceVersion=id%3A21791776"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/relationships\/uid?resourceVersion=id%3A21791776"}}},"field_development_status":{"data":{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","meta":{"drupal_internal__target_id":27274}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/field_development_status?resourceVersion=id%3A21791776"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/relationships\/field_development_status?resourceVersion=id%3A21791776"}}},"field_maintenance_status":{"data":{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","meta":{"drupal_internal__target_id":27271}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/field_maintenance_status?resourceVersion=id%3A21791776"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/relationships\/field_maintenance_status?resourceVersion=id%3A21791776"}}},"field_module_categories":{"data":[],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/field_module_categories?resourceVersion=id%3A21791776"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/relationships\/field_module_categories?resourceVersion=id%3A21791776"}}},"field_project_images":{"data":[],"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/field_project_images?resourceVersion=id%3A21791776"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/node\/project_module\/a551a0e5-af94-4e51-bb82-cda41c096f30\/relationships\/field_project_images?resourceVersion=id%3A21791776"}}}}}],"included":[{"type":"taxonomy_term--module_categories","id":"24830916-5c07-4446-89de-960915f87bf6","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/24830916-5c07-4446-89de-960915f87bf6?resourceVersion=id%3A199"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/24830916-5c07-4446-89de-960915f87bf6?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Access control","drupal_internal__tid":199,"status":true,"description":{"value":"Grant or restrict access to content, assets, or site functionality, or extend the authentication\/login process.","format":"1","processed":"\u003Cp\u003EGrant or restrict access to content, assets, or site functionality, or extend the authentication\/login process.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"0cd80c8e-5c20-43a8-aa3e-ec701007d443","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/0cd80c8e-5c20-43a8-aa3e-ec701007d443?resourceVersion=id%3A195"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/0cd80c8e-5c20-43a8-aa3e-ec701007d443?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"E-commerce","drupal_internal__tid":195,"status":true,"description":{"value":"Assist with aspects of running an online store, such as product management and display, shopping carts, inventory management, fulfillment, payments, taxes, and shipping.","format":"1","processed":"\u003Cp\u003EAssist with aspects of running an online store, such as product management and display, shopping carts, inventory management, fulfillment, payments, taxes, and shipping.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"3322058a-a158-4806-ac5b-9bcabc95edac","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/3322058a-a158-4806-ac5b-9bcabc95edac?resourceVersion=id%3A185"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/3322058a-a158-4806-ac5b-9bcabc95edac?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Integrations","drupal_internal__tid":185,"status":true,"description":{"value":"Use a third-party CSS or JS Framework, a self-hosted service like a CRM, or a third-party service with the site.","format":"1","processed":"\u003Cp\u003EUse a third-party CSS or JS Framework, a self-hosted service like a CRM, or a third-party service with the site.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"8117d8b0-f171-414d-b384-0bafa81bef9f","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/8117d8b0-f171-414d-b384-0bafa81bef9f?resourceVersion=id%3A193"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/8117d8b0-f171-414d-b384-0bafa81bef9f?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Security","drupal_internal__tid":193,"status":true,"description":{"value":"Help protect the website from attackers or bad actors, by identifying, preventing, or mitigating security vulnerabilities.","format":"1","processed":"\u003Cp\u003EHelp protect the website from attackers or bad actors, by identifying, preventing, or mitigating security vulnerabilities.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"86237004-3801-40cf-96b5-fe7d60efccb5","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/86237004-3801-40cf-96b5-fe7d60efccb5?resourceVersion=id%3A187"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/86237004-3801-40cf-96b5-fe7d60efccb5?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Content editing experience","drupal_internal__tid":187,"status":true,"description":{"value":"Enhance the editorial interface and improve the processes and workflows around creating, editing or removing content.","format":"1","processed":"\u003Cp\u003EEnhance the editorial interface and improve the processes and workflows around creating, editing or removing content.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"cfef5e6a-b77b-4a2b-b669-e87b1266f3ac","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/cfef5e6a-b77b-4a2b-b669-e87b1266f3ac?resourceVersion=id%3A191"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/cfef5e6a-b77b-4a2b-b669-e87b1266f3ac?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Import and export","drupal_internal__tid":191,"status":true,"description":{"value":"Help transfer content and data into or out of the site, by migration, backup, or exposing data to external systems.","format":"1","processed":"\u003Cp\u003EHelp transfer content and data into or out of the site, by migration, backup, or exposing data to external systems.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"abf23828-f269-4d39-8589-b731209eb154","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/abf23828-f269-4d39-8589-b731209eb154?resourceVersion=id%3A186"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/abf23828-f269-4d39-8589-b731209eb154?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Administration tools","drupal_internal__tid":186,"status":true,"description":{"value":"Empower site builders and administrators with no-code tools to setup, enhance, configure, or maintain the site.","format":"1","processed":"\u003Cp\u003EEmpower site builders and administrators with no-code tools to setup, enhance, configure, or maintain the site.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"086cebcf-200f-4c34-886e-f9921919b292","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/086cebcf-200f-4c34-886e-f9921919b292?resourceVersion=id%3A189"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/086cebcf-200f-4c34-886e-f9921919b292?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Developer tools","drupal_internal__tid":189,"status":true,"description":{"value":"Empower developers with tools that assist with developing and debugging the frontend or backend of the site.","format":"1","processed":"\u003Cp\u003EEmpower developers with tools that assist with developing and debugging the frontend or backend of the site.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"754c04cb-6da2-42ba-9032-d64307f68f45","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/754c04cb-6da2-42ba-9032-d64307f68f45?resourceVersion=id%3A188"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/754c04cb-6da2-42ba-9032-d64307f68f45?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Content display","drupal_internal__tid":188,"status":true,"description":{"value":"Configure the layout and format of content and data presented to site visitors.","format":"1","processed":"\u003Cp\u003EConfigure the layout and format of content and data presented to site visitors.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"dcb48e9f-6afa-4842-8ef6-44b90b083fcc","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/dcb48e9f-6afa-4842-8ef6-44b90b083fcc?resourceVersion=id%3A200"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/dcb48e9f-6afa-4842-8ef6-44b90b083fcc?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Site structure","drupal_internal__tid":200,"status":true,"description":{"value":"Extend the structure of the site by way of content models, data storage, field types, and navigation, so it is more understandable to users.","format":"1","processed":"\u003Cp\u003EExtend the structure of the site by way of content models, data storage, field types, and navigation, so it is more understandable to users.\u003C\/p\u003E"}}},{"type":"taxonomy_term--module_categories","id":"3cf38e0a-d4b1-426d-9b8e-008e7a41cf8d","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/3cf38e0a-d4b1-426d-9b8e-008e7a41cf8d?resourceVersion=id%3A194"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/module_categories\/3cf38e0a-d4b1-426d-9b8e-008e7a41cf8d?resourceVersion=rel%3Aworking-copy"}},"attributes":{"name":"Multilingual","drupal_internal__tid":194,"status":true,"description":{"value":"Provide tools for translation and display of text in multiple languages and support for regionalization\/localization for dates, numbers, currency, measurement, or other local contexts.","format":"1","processed":"\u003Cp\u003EProvide tools for translation and display of text in multiple languages and support for regionalization\/localization for dates, numbers, currency, measurement, or other local contexts.\u003C\/p\u003E"}}},{"type":"taxonomy_term--maintenance_status","id":"089406ad-304d-4737-80d1-2f08527ae49e","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/maintenance_status\/089406ad-304d-4737-80d1-2f08527ae49e?resourceVersion=id%3A27271"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/maintenance_status\/089406ad-304d-4737-80d1-2f08527ae49e?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__tid":27271,"status":true,"name":"Actively maintained","description":{"value":"Maintainers strive to actively monitor issues and respond in a timely manner.","format":"1","processed":"\u003Cp\u003EMaintainers strive to actively monitor issues and respond in a timely manner.\u003C\/p\u003E"}}},{"type":"taxonomy_term--maintenance_status","id":"cee844e2-68b5-489d-bafa-6a0ade2b6dfd","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/maintenance_status\/cee844e2-68b5-489d-bafa-6a0ade2b6dfd?resourceVersion=id%3A27273"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/maintenance_status\/cee844e2-68b5-489d-bafa-6a0ade2b6dfd?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__tid":27273,"status":true,"name":"Minimally maintained","description":{"value":"Maintainers monitor issues, but fast responses are not guaranteed.","format":"1","processed":"\u003Cp\u003EMaintainers monitor issues, but fast responses are not guaranteed.\u003C\/p\u003E"}}},{"type":"taxonomy_term--development_status","id":"e767288c-9800-4fb4-aeb8-8c311533838a","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/development_status\/e767288c-9800-4fb4-aeb8-8c311533838a?resourceVersion=id%3A27274"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/development_status\/e767288c-9800-4fb4-aeb8-8c311533838a?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__tid":27274,"status":true,"name":"Under active development","description":{"value":"This project is under active development.","format":"1","processed":"\u003Cp\u003EThis project is under active development.\u003C\/p\u003E"}}},{"type":"taxonomy_term--development_status","id":"219c1cf2-dd7f-474b-9dd5-a26643fbc699","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/development_status\/219c1cf2-dd7f-474b-9dd5-a26643fbc699?resourceVersion=id%3A27276"},"working-copy":{"href":"https:\/\/new.drupal.org\/jsonapi\/taxonomy_term\/development_status\/219c1cf2-dd7f-474b-9dd5-a26643fbc699?resourceVersion=rel%3Aworking-copy"}},"attributes":{"drupal_internal__tid":27276,"status":true,"name":"Maintenance fixes only","description":{"value":"Considered feature-complete by its maintainers.","format":"1","processed":"\u003Cp\u003EConsidered feature-complete by its maintainers.\u003C\/p\u003E"}}},{"type":"user--user","id":"1d1ccd47-550f-4b20-a1ed-909c6a7e67b5","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/1d1ccd47-550f-4b20-a1ed-909c6a7e67b5"}},"attributes":{"display_name":"jason.ullstam","drupal_internal__uid":2728387,"name":"jason.ullstam","field_country":"US","field_first_name":"Jason","field_git_username":"jason.ullstam","field_last_name":"Ullstam"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"17bf802b-cee7-4b73-94f3-67ec6c4299f0","meta":{"alt":null,"title":null,"width":350,"height":350,"drupal_internal__target_id":741578}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/1d1ccd47-550f-4b20-a1ed-909c6a7e67b5\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/1d1ccd47-550f-4b20-a1ed-909c6a7e67b5\/relationships\/user_picture"}}}}},{"type":"user--user","id":"432f3d0c-a2cc-4483-95a6-5cfdc553f0a9","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/432f3d0c-a2cc-4483-95a6-5cfdc553f0a9"}},"attributes":{"display_name":"kwtsms","drupal_internal__uid":3867520,"name":"kwtsms","field_country":null,"field_first_name":"Mohammed","field_git_username":"kwtsms","field_last_name":"Alhassoun"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"0cbf94b0-cb0d-4aa8-9b15-8f386c900d6f","meta":{"alt":null,"title":null,"width":null,"height":null,"drupal_internal__target_id":1461141}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/432f3d0c-a2cc-4483-95a6-5cfdc553f0a9\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/432f3d0c-a2cc-4483-95a6-5cfdc553f0a9\/relationships\/user_picture"}}}}},{"type":"user--user","id":"a8b50ba6-d27b-42b0-9684-61cbd6a16e05","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/a8b50ba6-d27b-42b0-9684-61cbd6a16e05"}},"attributes":{"display_name":"ajetiv1","drupal_internal__uid":3834672,"name":"ajetiv1","field_country":"US","field_first_name":"Valon","field_git_username":"ajetiv1","field_last_name":"Ajeti"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"197af2f1-f024-4808-bcb8-32d7e143c6a2","meta":{"alt":null,"title":null,"width":400,"height":400,"drupal_internal__target_id":1461053}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/a8b50ba6-d27b-42b0-9684-61cbd6a16e05\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/a8b50ba6-d27b-42b0-9684-61cbd6a16e05\/relationships\/user_picture"}}}}},{"type":"user--user","id":"8158dd3b-5959-4302-ab39-a6c10602608d","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/8158dd3b-5959-4302-ab39-a6c10602608d"}},"attributes":{"display_name":"coderdan","drupal_internal__uid":490684,"name":"coderdan","field_country":"US","field_first_name":"Daniel","field_git_username":"dsasser","field_last_name":null},"relationships":{"user_picture":{"data":{"type":"file--file","id":"711923e2-b262-4815-8380-d9cbe9433673","meta":{"alt":null,"title":null,"width":147,"height":147,"drupal_internal__target_id":218891}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/8158dd3b-5959-4302-ab39-a6c10602608d\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/8158dd3b-5959-4302-ab39-a6c10602608d\/relationships\/user_picture"}}}}},{"type":"user--user","id":"ac31d9c9-9a4f-400f-893b-a8b4e4fb1de0","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/ac31d9c9-9a4f-400f-893b-a8b4e4fb1de0"}},"attributes":{"display_name":"jrockowitz","drupal_internal__uid":371407,"name":"jrockowitz","field_country":"US","field_first_name":"Jacob","field_git_username":"jrockowitz","field_last_name":"Rockowitz"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"d920e38b-8128-4cee-9656-08f3495925a9","meta":{"alt":null,"title":null,"width":140,"height":140,"drupal_internal__target_id":114812}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/ac31d9c9-9a4f-400f-893b-a8b4e4fb1de0\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/ac31d9c9-9a4f-400f-893b-a8b4e4fb1de0\/relationships\/user_picture"}}}}},{"type":"user--user","id":"6e6b0e9c-4e68-4043-8752-8c15121a8d8f","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/6e6b0e9c-4e68-4043-8752-8c15121a8d8f"}},"attributes":{"display_name":"ncianca","drupal_internal__uid":24244,"name":"ncianca","field_country":"US","field_first_name":"Nick","field_git_username":"ncianca","field_last_name":"Cianca"},"relationships":{"user_picture":{"data":null,"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/6e6b0e9c-4e68-4043-8752-8c15121a8d8f\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/6e6b0e9c-4e68-4043-8752-8c15121a8d8f\/relationships\/user_picture"}}}}},{"type":"user--user","id":"c3547638-ecdf-4857-b728-c496f8bb07f8","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/c3547638-ecdf-4857-b728-c496f8bb07f8"}},"attributes":{"display_name":"mherchel","drupal_internal__uid":118428,"name":"mherchel","field_country":"US","field_first_name":"Mike","field_git_username":"mherchel","field_last_name":"Herchel"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"046bf3bc-f24f-4d0f-adfb-4949585fa8ae","meta":{"alt":null,"title":null,"width":1024,"height":994,"drupal_internal__target_id":52333}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/c3547638-ecdf-4857-b728-c496f8bb07f8\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/c3547638-ecdf-4857-b728-c496f8bb07f8\/relationships\/user_picture"}}}}},{"type":"user--user","id":"d912db4b-2d93-4c7f-a1ce-75636a500aa4","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/d912db4b-2d93-4c7f-a1ce-75636a500aa4"}},"attributes":{"display_name":"zaporylie","drupal_internal__uid":1532844,"name":"zaporylie","field_country":"NO","field_first_name":"Jakub","field_git_username":"zaporylie","field_last_name":"Piasecki"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"3e03fe6d-7aec-4c4d-ad9a-9efd8fc4f7e7","meta":{"alt":null,"title":null,"width":1024,"height":1024,"drupal_internal__target_id":193292}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/d912db4b-2d93-4c7f-a1ce-75636a500aa4\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/d912db4b-2d93-4c7f-a1ce-75636a500aa4\/relationships\/user_picture"}}}}},{"type":"user--user","id":"e86679e2-10de-49b9-a48a-9b38f6469632","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/e86679e2-10de-49b9-a48a-9b38f6469632"}},"attributes":{"display_name":"ga\u00eblg","drupal_internal__uid":431210,"name":"ga\u00eblg","field_country":"FR","field_first_name":"Ga\u00ebl","field_git_username":"gaelg","field_last_name":"Gosset"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"c6637878-4429-42d1-920d-2eb000c6a72c","meta":{"alt":null,"title":null,"width":73,"height":73,"drupal_internal__target_id":65740}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/e86679e2-10de-49b9-a48a-9b38f6469632\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/e86679e2-10de-49b9-a48a-9b38f6469632\/relationships\/user_picture"}}}}},{"type":"user--user","id":"cf195a19-00b6-4e02-aef7-5fe21d63b2df","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/cf195a19-00b6-4e02-aef7-5fe21d63b2df"}},"attributes":{"display_name":"svendecabooter","drupal_internal__uid":35369,"name":"svendecabooter","field_country":"BE","field_first_name":"Sven","field_git_username":"svendecabooter","field_last_name":"Decabooter"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"ab283f99-a72b-4134-ad33-44aa41ed8613","meta":{"alt":null,"title":null,"width":936,"height":1011,"drupal_internal__target_id":9099}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/cf195a19-00b6-4e02-aef7-5fe21d63b2df\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/cf195a19-00b6-4e02-aef7-5fe21d63b2df\/relationships\/user_picture"}}}}},{"type":"user--user","id":"e52d9f9c-a96a-4167-b49a-69967157e171","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/e52d9f9c-a96a-4167-b49a-69967157e171"}},"attributes":{"display_name":"erik.erskine","drupal_internal__uid":375884,"name":"erik.erskine","field_country":"SE","field_first_name":"Erik","field_git_username":"erik.erskine","field_last_name":"Erskine"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"724aa091-bf3d-49e0-8a80-a98e5dda62d2","meta":{"alt":null,"title":null,"width":731,"height":1024,"drupal_internal__target_id":119038}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/e52d9f9c-a96a-4167-b49a-69967157e171\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/e52d9f9c-a96a-4167-b49a-69967157e171\/relationships\/user_picture"}}}}},{"type":"user--user","id":"d225fac6-5c5b-42fe-8cd5-80d272f1aec0","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/d225fac6-5c5b-42fe-8cd5-80d272f1aec0"}},"attributes":{"display_name":"gagosha","drupal_internal__uid":3506581,"name":"gagosha","field_country":"GE","field_first_name":"Giorgi","field_git_username":"gagosha","field_last_name":"Gagoshidze"},"relationships":{"user_picture":{"data":{"type":"file--file","id":"fd44af7a-5b06-457f-ba85-38f01e64c49b","meta":{"alt":null,"title":null,"width":1024,"height":668,"drupal_internal__target_id":112636}},"links":{"related":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/d225fac6-5c5b-42fe-8cd5-80d272f1aec0\/user_picture"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/user\/user\/d225fac6-5c5b-42fe-8cd5-80d272f1aec0\/relationships\/user_picture"}}}}},{"type":"file--file","id":"5e96b2d0-b667-4be6-bc65-403fa4b24fc0","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/5e96b2d0-b667-4be6-bc65-403fa4b24fc0"}},"attributes":{"uri":{"value":"public:\/\/project-images\/Screenshot 2026-04-09 at 5.17.46\u202fPM.png","url":"\/assets\/project-images\/Screenshot%202026-04-09%20at%205.17.46%E2%80%AFPM.png"}}},{"type":"file--file","id":"b744b363-0952-4e90-bd44-63132a47ba0e","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/b744b363-0952-4e90-bd44-63132a47ba0e"}},"attributes":{"uri":{"value":"public:\/\/project-images\/Screenshot 2026-04-09 at 5.18.21\u202fPM.png","url":"\/assets\/project-images\/Screenshot%202026-04-09%20at%205.18.21%E2%80%AFPM.png"}}},{"type":"file--file","id":"f4170e4d-baa3-4141-9965-e0f499a797e2","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/f4170e4d-baa3-4141-9965-e0f499a797e2"}},"attributes":{"uri":{"value":"public:\/\/project-images\/01-dashboard.png","url":"\/assets\/project-images\/01-dashboard.png"}}},{"type":"file--file","id":"b17f4fd8-1cf5-46c0-9c76-9021b66eb96c","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/b17f4fd8-1cf5-46c0-9c76-9021b66eb96c"}},"attributes":{"uri":{"value":"public:\/\/project-images\/02-settings.png","url":"\/assets\/project-images\/02-settings.png"}}},{"type":"file--file","id":"41c97a38-fa40-497b-bdb1-7ec003d0a06f","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/41c97a38-fa40-497b-bdb1-7ec003d0a06f"}},"attributes":{"uri":{"value":"public:\/\/project-images\/03-gateway.png","url":"\/assets\/project-images\/03-gateway.png"}}},{"type":"file--file","id":"37aa9770-eb7b-42d5-847e-980b233ee31c","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/37aa9770-eb7b-42d5-847e-980b233ee31c"}},"attributes":{"uri":{"value":"public:\/\/project-images\/04-templates.png","url":"\/assets\/project-images\/04-templates.png"}}},{"type":"file--file","id":"1c230f9a-5369-49eb-9ef0-57ad8cffe261","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/1c230f9a-5369-49eb-9ef0-57ad8cffe261"}},"attributes":{"uri":{"value":"public:\/\/project-images\/06-logs.png","url":"\/assets\/project-images\/06-logs.png"}}},{"type":"file--file","id":"f84a712e-fea5-414f-bf43-31515514c5a1","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/f84a712e-fea5-414f-bf43-31515514c5a1"}},"attributes":{"uri":{"value":"public:\/\/project-images\/migrate_forward_draft_project_icon.png","url":"\/assets\/project-images\/migrate_forward_draft_project_icon.png"}}},{"type":"file--file","id":"3962b1ef-d51d-4c6a-bd8b-25308b2442b1","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/3962b1ef-d51d-4c6a-bd8b-25308b2442b1"}},"attributes":{"uri":{"value":"public:\/\/project-images\/plugin_report.png","url":"\/assets\/project-images\/plugin_report.png"}}},{"type":"file--file","id":"01d9dca7-da11-44b3-8f52-d907e114184c","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/01d9dca7-da11-44b3-8f52-d907e114184c"}},"attributes":{"uri":{"value":"public:\/\/project-images\/theming-tools.jpg","url":"\/assets\/project-images\/theming-tools.jpg"}}},{"type":"file--file","id":"ecf9ba23-645a-44dc-9e8a-855e3b673278","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/ecf9ba23-645a-44dc-9e8a-855e3b673278"}},"attributes":{"uri":{"value":"public:\/\/project-images\/language_switcher_dialog.png","url":"\/assets\/project-images\/language_switcher_dialog.png"}}},{"type":"file--file","id":"08005475-a8f4-462d-af74-350560b1d4a1","links":{"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/file\/file\/08005475-a8f4-462d-af74-350560b1d4a1"}},"attributes":{"uri":{"value":"public:\/\/project-images\/language_switcher_dialog_geoip.png","url":"\/assets\/project-images\/language_switcher_dialog_geoip.png"}}}],"meta":{"count":38056},"links":{"last":{"href":"https:\/\/new.drupal.org\/jsonapi\/index\/project_modules?filter%5Bstatus%5D=1\u0026filter%5Btype%5D=project_module\u0026filter%5Bproject_type%5D=full\u0026filter%5Bn_security_coverage%5D%5Bvalue%5D%5B0%5D=revoked\u0026filter%5Bn_security_coverage%5D%5Boperator%5D=NOT%20IN\u0026filter%5Bn_security_coverage%5D%5Bpath%5D=security_coverage\u0026page%5Boffset%5D=38052\u0026page%5Blimit%5D=12\u0026include=field_module_categories%2Cfield_maintenance_status%2Cfield_development_status%2Cuid%2Cfield_project_images\u0026sort=-created"},"next":{"href":"https:\/\/new.drupal.org\/jsonapi\/index\/project_modules?filter%5Bstatus%5D=1\u0026filter%5Btype%5D=project_module\u0026filter%5Bproject_type%5D=full\u0026filter%5Bn_security_coverage%5D%5Bvalue%5D%5B0%5D=revoked\u0026filter%5Bn_security_coverage%5D%5Boperator%5D=NOT%20IN\u0026filter%5Bn_security_coverage%5D%5Bpath%5D=security_coverage\u0026page%5Boffset%5D=12\u0026page%5Blimit%5D=12\u0026include=field_module_categories%2Cfield_maintenance_status%2Cfield_development_status%2Cuid%2Cfield_project_images\u0026sort=-created"},"self":{"href":"https:\/\/new.drupal.org\/jsonapi\/index\/project_modules?filter%5Bstatus%5D=1\u0026filter%5Btype%5D=project_module\u0026filter%5Bproject_type%5D=full\u0026filter%5Bn_security_coverage%5D%5Bvalue%5D%5B0%5D=revoked\u0026filter%5Bn_security_coverage%5D%5Boperator%5D=NOT%20IN\u0026filter%5Bn_security_coverage%5D%5Bpath%5D=security_coverage\u0026include=field_module_categories%2Cfield_maintenance_status%2Cfield_development_status%2Cuid%2Cfield_project_images\u0026page%5Blimit%5D=12\u0026page%5Boffset%5D=0\u0026sort=-created"}}}