Primary tabs
Useful Drupal modules
Click on the module name for notes, comments, patches.
Recommendations (for and against) are my personal opinion only and may be out of date. Feel free to email with corrections/suggestions.
Why doesn't the table mention Drupal 9 or 10?
1. Nowadays, I try and use Drupal as little as possible. Specifically I do not recommend it for a new website. I'd also strongly caution you against choosing Drupal if you're at the beginning of your career and trying to learn web development (front / back / full stack) or just want to manage/maintain a website. More details why by email on request.
2. By February 2022 I'd updated all the sites I look after to Drupal 9 (experience: mixed). As of March 2023, a year later, none of them were fully ready for Drupal 10 (waiting on support for various modules). By 13 Nov 2023 (a week or two after D9 lost support) I had updated a couple of them.
Q: What's the Drupal 9 to 10 upgrade experience like? A: it's what I'd describe as "just bearable", slightly better than D8 to D9, though with plenty of things to still trip you up. There is still deprecated code that needs fixing in D10 modules, and policy changes mean odd things will break (be prepared to turn off Aggregate CSS/JS files if your themes stop working, and note that Drush launcher doesn't work with Drush 12...)
Admittedly the upgrade_status module is the best solution they could have come up with for tracking compatibility. Also watch out for a nasty session headers bug with redirect_after_login.
What about sites still running Drupal 7? In short I still recommend leaving them on Drupal 7 or moving to another platform entirely. My prediction was that Drupal will extend D7 support year after year (note that drupal.org itself is still running D7). It's now been confirmed as 5 Jan 2025. There will have to be some sort of third-party long term support, because of the sheer volume of sites that are not being upgraded.
Your decision is really what specifically you think you will gain from Drupal 8/9/10 - often the answer will be not enough, and one of the main hassles - apart from converting each content type one at a time, and setting up a new theme, will be recreating all your views by hand, as views can't be automatically upgraded.
(134 modules in list)Name | D8 | Personally Tested Sort descending | Last Updated |
---|---|---|---|
Feeds (feeds) | ✔ | ✖ | |
"Essential" As of Sep 2018, up to alpha3 in D8 (but not personally tested). Lets you import CSV/RSS etc. files and various other formats and map them to nodes/user/taxonomy terms, either one-off or periodically. |
|||
Alexa (alexa) | ✔ | ✖ | |
Integrates with Amazon Echo. Allows Drupal to respond to Alexa skills requests. See Dries' blog with video demo. |
|||
Field collection (field_collection) | ✔ | ✖ | |
Allows you to group a set of fields together. In active development for D8 but still a lot of open bugs at time of writing - project page says it will likely be replaced by Paragraphs. |
|||
Refreshless (refreshless) | ✔ | ✖ | |
Only loads the parts of page that change when navigating between pages. Unclear if still being maintained (no updates since Sep 2016) - part of the issue is it requires a core patch. |
|||
Trash (trash) | ✔ | ✖ | |
Adds a trash bin for all content, so you may later restore (or permanently delete) it. Depends on Content Moderation module. Alpha in D8. |
|||
CKEditor Custom Config (ckeditor_config) | ✔ | ✖ | |
I've not actually used this but I adapted it's code to enforce a configuration setting (I wanted to remove the HTML dom elements that are shown in the status bar). The module allows you to supply your configuration using the UI. |
|||
Node Export (node_export) | ✖ | ✖ | |
Tto actually export node content. An 8.x version has begun development:
|
|||
Twig Extensions (twig_extensions) | ✔ | ✖ | |
Text filters, array and date manipulation. (haven't tried this yet) |
|||
Restrict Login or Role Access by IP Address (restrict_by_ip) | ✖ | ✖ | |
Can specify single IP address or ranges. Two modes: restrict login, so they can only login from certain IPs, and restrict role, so they can login from anywhere but only access a role's permissions from the defined IPs. There's a D8 dev branch, last updated June 2016. |
|||
Entity Access Audit (entity_access_audit) | ✔ | ✖ | |
This is a way of visualising - via grids of ticks and crosses - which roles have access to different operations on different entities. |
|||
Group (group) | ✔ | ✖ | |
Alternative to the Organic Groups module. Allows you to create groups - e.g. classes, subscriptions, multiple communities. Drupal module of the week post. Blog post. It is by all accounts solidly written, but I found the initial UI confusing (in a "so what do I do now?" way) - you probably need to watch the YouTube video to understand it. |
|||
Features (features) | ✔ | ✖ | |
Not recommended Update: most people are now moving away from features. There is a Configuration Management initiative under discussion in Drupal 8. Package up selected configuration for "features" (e.g. a blog or a photo gallery etc.) for reuse on other sites. Not the same as the new D8 Config sync, which is for exchanging configs between different environments of the same site and requires a cloned DB sharing the same UUIDs. |
|||
Simple OAuth (simple_oauth) | ✔ | ✖ | |
An implementation of OAuth 2.0 Authorization Framework RFC - based on a PHP League package. |
|||
AddToAny Share Buttons (addtoany) | ✔ | ✖ | |
Nice, clean, SVG sharing buttons. Project page says it's specifically optimised for Drupal. |
|||
Autofocus (focus) | ✖ | ✖ | |
Autofocuses the first field of form (forms can be specified). No sign of a D8 port. |
|||
Image Lazyloader (lazyloader) | ✔ | ✖ | |
Images are hidden until they scroll into view. Can specify distance before loading is triggered, also placeholder image, loading GIF and any pages to be excluded. There's been some Drupal 8 development but unclear how complete it is. |
|||
Autosave (autosave) | ✖ | ✖ | |
Saves snapshot of content type form using AJAX. Content types and save frequency can be configured. No sign of a D8 port yet. |
|||
Automatic Nodetitles (auto_nodetitle) | ✖ | ✖ | |
You can hide a node's title field (for reference, every node has to have a title) and generate it automatically, similar to pathauto. No-one's porting this to D8 yet. |
|||
Datetime Range (datetime_range) | ✔ | ✖ | |
"Essential" Now in core, but you need to enable it. Adds an 'all-day' option. |
|||
Twig Tweak (twig_tweak) | ✔ | ✖ | |
Adds Twig syntax to insert views, view results, regions, entities (e.g. nodes, blocks, webforms), menus, images, image styles, tokens, breadcrumbs, messages, contextual links and more. |
|||
Mollom (mollom) | ✔ | ✖ | |
Deprecated Not recommended DO NOT USE - security issue and Acquia will no longer support or maintain it. Spam filtering SaaS from Acquia. Free for up to 50 "ham" messages a day. Scans message then provides a captcha if appropriate, scores each message for reputation, spam etc. I never tried this module and anecdotally I've seen mixed reports / people suggesting it's not all that good. |
|||
Coder (coder) | ✔ | ✖ | |
Checks your code against Drupal coding standards. No need to install this - isn't actually a module, it's a set of phpcs rules installed as standard in /vendor/drupal/coder/coder_sniffer |
|||
Block Visibility Groups (block_visibility_groups) | ✔ | ✖ | |
Rather than change visibility for individual blocks, you can group them together and assign complex visibility settings to all of them. Module page promotes it as a simpler alternative to Panels. |
|||
Flood Control (flood_control) | ✖ | ✖ | |
Protect against brute-force login attacks. Unclear what's happening with porting of this. |
|||
HMS Field (hms_field) | ✔ | ✔ | |
Hours/minutes/seconds field type (formats: h:mm, h:mm:ss, m:ss, h, m or s). Drupal 8 in beta. |
|||
Two Factor Authentication (tfa) | ✔ | ✔ | |
"Essential" install tfa and ga_login (TFA is just a framework, it doesn't come with it's own login plugins.) Use this patch I wrote - it adds display of validation skip times and an admin reset button for users who are got locked out. My installation instructions: Next you need to generate an encryption profile. Set key provider to File rather than Configuration, this means the key won't end up in your version control. Tick the 'strip trailing line breaks' box to avoid the "The selected key size does not match the actual size of the key." error Key path should be relative to Drupal so the config will work on multiple sites Remember to save the key somewhere in your password manager, or your ansible variables, in case you lose the files later. In the TFA settings (/admin/config/people/tfa) you probably want to increase the number of times a user can skip validation. Note that TFA has a separate 'Tfa user login' block (replacing the ordinary 'User login') |
|||
AJAX Comments (ajax_comments) | ✔ | ✔ | |
Not recommended Not very actively maintained and it can be quite buggy. Needs this patch: Reply button can be pressed multiple times, resulting in multiple comment forms I abandoned it for a project because the admin XHR response when you submit comments sends back comments you've already filtered out (I had written code to restrict visibility of certain comments). Also had a problem where the initial comment form was left in place rather than being replaced, so you ended up with duplicates. |
|||
Automatic User Names (auto_username) | ✔ | ✔ | |
"Essential" Removes the 'Username' field from registration form. Use in conjunction with a module that allows users to login with their email address. Patches:
|
|||
Layout builder (layout_builder) | ✔ | ✔ | |
Benefits:
Nov 2018: core, experimental in 8.6.x Installation:
By turning on Layout Builder, you switch from the standard Manage Display view (field, label, format/widget settings) and the layout builder GUI. Resources: Compatibility:
|
|||
Login email or username (login_emailusername) | ✔ | ✔ | |
"Essential" Self-explanatory. |
|||
Views Aggregator Plus (views_aggregator) | ✖ | ✔ | |
Provides extra options for aggregating data in tables - e.g. grouping sets of rows together and summing the values of particular fields. Has a hook - hook_views_aggregation_functions_info() - which lets you add your own options to the table aggregation settings - e.g. supposing you have a limit for something (number of tickets, nights of accommodation) and want to decrement it - you can write a method to sum the matching rows and then do a calculation on the total. Also supports 'add column function' - adds a grand total (or other summary field) at the very bottom of the table. Caution - this module breaks hook_views_pre_render() - you can write your own pre_render method to remove or shuffle entire rows, but any chances to values will be overwritten (discovered this by looking through the source and looking for the use of that hook). The workaround is to try and do what you need to by using hook_views_aggregation_functions_info() instead. |
|||
Configuration Read-only (config_readonly) | ✔ | ✔ | |
Lock all configuration changes via the admin UI - e.g. if you need to lockdown a production environment. config_readonly now has a whitelist, added via an array in settings.php. |
|||
Password policy (password_policy) | ✔ | ✔ | |
Not recommended There are still quite a few bugs open. I dropped this for a project, partly because it adds a load of clutter with the 'resets' and reset dates. |
|||
Automatic Entity Label (auto_entitylabel) | ✔ | ✔ | |
"Essential" Hide entity labels (i.e. titles) or auto-generate them. (Works for anything - nodes, comments, taxonomies). |
|||
Field Formatter Condition (fico) | ✔ | ✔ | |
(based on ffc which hasn't been ported to D8). Allows you to configure field display based on value. Adds a 'Conditions' pane to the cog in Manager Display of all entities (so content types but also comment types, e.g. if you have comments with multiple fields) Requires Display Suite (ds) Note: if you wanted to hide say a checkbox when it's value is false - you can do in it core with Manage Display - turn the label off then set (via cog wheel) the output format to Custom, and you can enter a value for true and leave false blank - exactly the same widget for boolean values you use when setting the output of a field in a view. |
|||
Webform Views Integration (webform_views) | ✔ | ✔ | |
"Essential" This module lets you add fields from submissions to view, and sort/filter the view on them, in the same way you would standard fields from the Field API. It's still alpha and not as polished/robust as the webform module itself - but it's certainly OK to use in production provided you test things first - check every combination of exposed filters works, and double check you aren't seeing duplicate rows (right now I've locked it to a recent commit on the dev-5.x branch, which doesn't need any patches). |
|||
Menu position (menu_position) | ✔ | ✔ | |
"Essential" Assign various pages (by content type, URL, role etc.) to certain menu entries - so the 'active' status of the menu is set correctly (i.e. they appear within the sections you want). - patch: Add enabled checkbox to edit form + enable new rules by default
|
|||
Conditional Fields (conditional_fields) | ✔ | ✔ | |
Adds a 'Manage dependencies' tab to the admin page for content types. This lets you set a 'target field' whose visibility is set according to a 'control field' and whether the latter is full/empty/checked/unchecked/has a specific value. Another useful feature is you can prefill/pre-tick etc. the target field (including with a custom text value, for example). To detect quickly if it's in use anywhere (I needed to do this before being sure I could uninstall the module on a site), export your site config and grep the /config/sync directory for 'conditional_fields' - it's stored in the 'third_party_settings' key in core.entity_form_display.node.[content type].default.yml |
|||
Telephone (telephone) | ✔ | ✔ | |
Telephone number field type. This is in core, but you need to enable it. |
|||
Field Permissions (field_permissions) | ✔ | ✔ | |
"Essential" Control editing/visibility of individual fields by role. As well as custom settings ('create own', 'edit own', 'view own', 'edit any' and 'view any' - all per role), there's a Private setting which gives access to the author and administrator only. These are automatically applied to views. Finding the setting: Look for Field visibility and permissions – on the Edit tab, NOT Field Settings. In /admin/people/permissions there's also a Access other users private fields permission. |
|||
Bamboo Twig (bamboo_twig) | ✔ | ✔ | |
Way to embed lots of objects in twig. note you have to selectively enable various sub modules for each of the commands. Seems pretty actively developed and well documented. |
|||
ClamAV (clamav) | ✔ | ✔ | |
"Essential" Virus check files uploaded by users. In Drupal - when it can't connect you get an error on the Status Report. There's a "verbose" option in the config settings (which logs files that "passed" the virus check as well as failed) You need to tick 'Enable ClamAV integration' before it will actually scan any files. Test it's working by creating a small file with the short Eicar test signature string Notes: ClamAV does use a fair bit of memory (because it keeps a copy of all the virus signatures) Patch: Requires core patch to avoid possible data loss (race condition) - use my rerolled patch (#35) |
|||
Menu Token (menu_token) | ✔ | ✔ | |
Add tokens, such as a user ID, to text or URL paths of menu items. Be wary of this issue: Current-user:uid not correct |
|||
CKEditor Wordcount (ckwordcount) | ✔ | ✔ | |
Adds word/character/paragraph count to the CKEditor status bar (can optionally enforce a word/character limit) Configured via Text formats and Editors (/admin/config/content/formats). Requires the ckeditor wordcount library - example composer.json for that (put this in your 'repositories' section): "ckeditor.wordcount": { "type": "package", "package": { "name": "ckeditor/wordcount", "version": "1.17.4", "type": "drupal-library", "extra": { "installer-name": "wordcount" }, "dist": { "url": "https://download.ckeditor.com/wordcount/releases/wordcount_1.17.4.zip", "type": "zip" }, "require": { "composer/installers": "~1.0" } } }, and then require: "ckeditor/wordcount": "1.17.4", Patch needed: https://www.drupal.org/files/issues/2018-12-06/ckwordcount_plugin_path_2850845-9.patch (to ensure modules gives browser correct path of plugin.js - if your ckeditor input disappears, check console.log and it's probably that) The notification module is a dependency. |
|||
Save edit (save_edit) | ✔ | ✔ | |
"Essential" Add a save and edit button
|
|||
AudioField (audiofield) | ✔ | ✔ | |
"Essential" This is a formatter, available on node display or in views. It turns a uploaded file or an external URL into an HTML5 audio player. Also supports various other JS player libraries which you can download. You can turn lazy-loading of the file on or off. Note: there is a default label added below the player, which is either the URL field description or actual address, if the former is missing. Override the audioplayer.html.twig template to remove this. |
|||
TagCloud (tagclouds) | ✔ | ✔ | |
Provides a block with a tag cloud of chosen taxonomy term. Works but a bit buggy, e.g. UI taxonomy setting reverts to 'tags'. Requires clearing the cache to update (including changing any settings). Choice of numbers after each tag to indicate quality, or 'wordcloud' style with varying sizes (will need you to modify your CSS to add some spacing between words). |
|||
Advanced Page Expiration (ape) | ✔ | ✔ | |
Not recommended I would avoid this. The idea is you enter URL paths with wildcards and override the cache expiration. I was unable to get it to work properly for pages (settings on config under Development > Performance) Also, re: caching images, those are files being served directly by Apache or Nginx, not via the Drupal front-controller, so caching settings need to be configured there. |
|||
Views Secondary Row (views_secondary_row) | ✔ | ✔ | |
"Essential" For Views that use Table format. Adds a row underneath each record - you change the format from 'table' to the 'secondary row' option, you get an extra select dropdown in the table *settings*, and you can also specify colspan. This does mean the label will be missing by default (you won't have a column header any more) - so you need to edit the field and tick rewrite output, and then specify your desired label, followed by the field value in Twig. |
|||
Pathologic (pathologic) | ✖ | ✔ | |
There's a D8 version but I've only tested D7. It's a filter that fixes incorrect paths in your content - e.g. if you have content with an old domain or IP address specified, you can redirect it. |