Jan 06 2020
Jan 06

"There's an app for that."

We hear this often because it's true. In today's hyper-connected world, offering mobile apps for your business or services have become an expectation. According to Statista, the total number of mobile apps on Apple and Google's app stores are 1.8M and 2.47M respectively. It's now the norm to build apps that support both platforms. But native apps have always been an issue for businesses due to the costly development cycle. Then comes cross-platform technology, which enables developers to build and maintain a single code base for applications that can be published across multiple platforms.   

At Evolving Web, we specialize in web development using Drupal and recently extended our offerings to include mobile solutions. We developed mobile applications using React Native that could be seamlessly integrated to Drupal 8 using modules such as JSON:API or SimpleOAuth, and also implemented third party services such as Firebase or Amplify to enhance the mobile experience with features like push notification or real-time data synchronization.   

We have been actively researching and experimenting with cross-platform technologies and have learned that while they can save a lot of development time and costs, they also present new challenges.

Here's a quick overview of the pros and cons of cross-platform technology:


  • Write once, run anywhere: developers don't need to write Swift for iOS or Java/Kotlin for Android. The whole business logic remains in one single piece of code.
  • Easy code management: a single code base is easier to maintain.
  • Shorter development cycle: write once, deploy to both stores. 


  • Unoptimized app performance: the need to support multiple platforms can diminish performance. 
  • Not-so-native feel: Balancing platform-specific experiences can be difficult due to differences in user experiences for iOS and Android.

In this article, we'll explore our experiences with React Native and Flutter, two mobile application frameworks that will continue to dominate in 2020.

The Top Two Mobile Frameworks

In 2019, React Native took the lead of being the most used cross-platform mobile framework, followed by Flutter, Cordova, Ionic and Xamarin. Flutter has also been a rising star in the last year.  

React Native

Created by Facebook in 2015, React Native is undoubtedly the most adored cross-platform mobile development framework with 83.4k stars on Github so far. The framework allows you to build applications using Javascript or Typescript, and brought in the concept of the bridge that helps you generate and manipulate native mobile UI components from a background Javascript thread. Unlike other frameworks such as PhoneGap, Cordova, and Ionic—which rely on webview to render UI components—React Native allows us to create and manipulate real UIView instances like we would have done with native mobile development.  

Moreover, you can also write modules in native languages such as Objective C, Swift or Java, which allows you to interact with OS APIs if you want to build more sophisticated applications. This opens up more possibilities regarding what you can build with React Native.   

Facebook and Instagram are two top-of-the-chart applications built in React Native, not to mention other names such as Tesla and Bloomberg. In May 2019, Microsoft announced a new performance oriented open source project for React Native developers who want to target Windows, another example of how much the framework is extending their capabilities. 


  • Convenience: benefit from time and cost efficiencies. 
  • Faster refresh: get near-instant feedback for changes on React components.
  • It's a sibling with ReactJS so the web components are reusable. 
  • Awesome performance: thanks to its technical capabilities and big, supportive community.


  • Not completely intuitive: you may need expertise from native developers for platform-specific modules.   

With a vibrant developer community and increasing recognition from tech businesses, React Native will thrive and continue to evolve in 2020.

Apps Built With React Native

Apps built by React Native - Facebook, Tesla, Bloomberg

  • Facebook
  • Tesla
  • Bloomberg  


Flutter is a modern development kit from Google used to build mobile apps for Android, iOS and Google Fuchsia—an operating system that can run on embedded systems in smartphones, tablets, and personal computers.

Google announced Flutter's first stable release in 2018. Despite being quite young on the market, Flutter has quickly gathered a large community and is the fastest-growing skill among software engineers. One of the reasons Flutter has risen so quickly is because of its performance. With the UI refreshing at 60fps—mostly using GPU—each and every pixel on the screen is painted on SkiaCanvas, allowing developers to create sophisticated, smooth and highly customizable UIs.   

In order to build apps with Flutter, developers need to use Dart, a programming language also developed by Google. There are many fantastic features of Dart that make it crucial to Flutter's success, one of which is that Dart is one of the few languages that does compiling in both AOT and JIT. Just-in-time (JIT) compilers run during the execution of the program, compiling on the fly, which provides much faster development cycles as developers see updates right away, though it has slow startup times. On the other hand, ahead-of-time (AOT) compiles high-level programming languages into native machine code so that the resulting file can execute natively and really fast. Flutter's use of Dart benefits from the hot reload thanks to the JIT compiler and the quick execution and startup times due to the AOT compiler.   


  • Hot reload: you can see the results of your changes almost instantly.
  • Speed: fast execution and startup times.
  • High-performing native experience: the UI refreshes up to 60 fps animations.
  • Direct access to native code: you can import libraries and use native APIs.
  • Fantastic testing and performance profiling support. 


  • Relatively young: not as much support as other frameworks. 
  • Less features: less available plug-ins.  

Apps Built With Flutter

Flutter Apps - Google Ads, Alibaba, Top Goals

  • Google Ads
  • Alibaba 
  • Top Goals


If you're a developer with a JS background, React Native's big community will speed up the learning process and is a quick way to familiarize yourself with mobile development.   

If you don't mind learning a new language and want to experiment with a new technology that's performance focused, Flutter is the way to go.  

In 2020, we will continue to bring more beyond-Drupal solutions to our clients and can't wait to maximize the capabilities of React Native and Flutter for future projects. Tune in for future blog articles where we teach you how to integrate these solutions with Drupal!

If you want to learn more about Evolving Web and our culture, feel free to visit our careers page

Jan 06 2020
Jan 06

It is known that page load time is one of the important aspects of search engine result position. Site speed is what stands between the website and the potential user.

Caching therefore plays an essential role in optimizing websites to deliver high-performance. Not only does it help support faster load times than otherwise possible, but it also helps in reducing latency. The information can be stockpiled at every level right from the original server to intermediate proxies to the browser.

Drupal encompasses numerous tools for caching content that can work for your site exceptionally and it’s important to know what they are and what they do. This blog will elucidate the caching mechanism in Drupal 8.

Drupal 8 Caching Modules

By default, Drupal 8 comes with 2 modules for implementing caching-

  • Internal Page Caching:
The Internal Page Caching module when enabled, stores the complete page information even if the user visiting the site hasn’t logged in. Future anonymous visitors will then observe that the same content is loaded extremely fast since the page wasn’t put together from scratch. This module is useful for websites with a lot of unregistered users
  • Internal Dynamic Page Cache:

The Internal Dynamic Page Cache module is designed to cache small sections of each page for all users whether they are logged in or not. Whenever the page content is requested by the same or different user, the module can pull in those individual parts to speed up the building of the page on the fly.

Understanding Caching At Different Layers

Caching in Drupal takes place at three separate levels: application, component, and page. Given below is the detailed description of each-

  • Application-level Caching

Application-level caching is in-built in Drupal. However, you won’t see it in action until you scrutinize Drupal’s internal code. It is active by default and won’t even show older, cached pages.

The application-level caching in Drupal ensures that the cached pages are separately stored from the site content (which goes into the database). You can’t set this up, except for guiding Drupal where to save cached pages explicitly. 

Drupal stores its external and internal data structures efficiently to enhance repeated users’ access when performing application-level caching. This isn’t the information that a site visitor sees in itself but forms a critical factor in constructing any page. The only level of refinements that can be made at this level is improving where this cached information is stored, like using Memcached instead of the database.

  • Component-level Caching

Component-level caching works on front-end components such as blocks, panels, and views. For example, you might own a website having dynamic content but a single block remains constant. In fact, you may have the same block widely scattered across dozens of pages. Caching it can deliver improved performances significantly.

Though component-level caching is generally disabled by default, however, you can make it active with some simple configuration changes. You can initiate with identifying blocks, panels, and views on your site that remains the same across to later cache them strenuously. You will notice a strong speedup for authenticated users.

  • Page-level Caching

As the name suggests, this page-level caching caches, stores, and delivers the entire page to the user. One of the most effective types of caching,  it shoes static HTML pages to users to improve site performance almost immeasurably.

Page-level caching gives you enough space to customize where you can use any number of caching servers, including Varnish, or CDNs like CloudFlare to deliver cached pages from servers close to the users’ location. 

CDNs help you in bringing your site closer to your users. However, it only works for anonymous users by default. Fortunately, this drives huge traffic to any website.

A typical Drupal application comprises of all the layers mentioned above. However, to better understand the flow and learn how to debug a caching issue, a flowchart is given to illustrate how content is cached at different layers-

Flowchart of how caching works in Drupal 8Learn more about caching from here-

[embedded content]

Cacheability Metadata in Drupal 8. What is it?

Cacheability metadata is used to describe the thing which is rendered with respect to its dynamism. Сaching properties could be applied to any object and one can easily change the default cache settings of these three properties-

  1. Cache Tags  
  2. Cache Contexts  
  3. Cache Max-Age
  • Cache Tags: 

Tags are used to nullify cache entries when something on the site undergoes modification. (nullifying or invalidating means that the cache entry won’t get used, and will be reconstructed the next time that piece of content is rendered). Drupal comprises multiple cache tags to explicate all sorts of different scenarios from individual nodes and blocks, to site configuration settings, and menus. 

For example, the cache tag ‘node:5’ gets invalidated any time the Drupal content node with ID 5 gets modified.

So, whenever content gets cached which depends on something related to node 5,  the cache entry keeps track of that tag; then, saving the node causes that cache entry to get invalidated. This implies that any time you save something in Drupal, a relevant tag gets invalidated.

The tag for the same will look like this-

Syntax : “node:5” 

node_list: List cache tags for node entities

  • Cache Contexts: 

Contexts are quite different from tags. Cache contexts are stored alongside cache entries and are designed to let content vary depending on what circumstances or situation it is showcased in.

For instance, you have a site with users of several different roles, and one block on the site is meant to show content differently depending on what roles the user seeing it has. This can’t be implemented through cache tags alone. However, it won’t be a good idea to leave the block completely uncached, instead, it can have the “user permissions” context applied to it. This way, the block can be cached multiple times- specifically one time for each combination of roles that the users see the block have. This way, an administrator can see something different from an editor who will see something different from a user who has both roles.

Commands shown in for caching tags

  • Cache Max-age:

Cache max-age is the last step to handle cache invalidation. You have to simply set the time on how long the content should be cached for. This can vary from 0 seconds (to not cache content at all) to as long as you want. 

Presuming that all of the tags and contexts being used are working as intended, this can be put to indefinite (default state in Drupal) since those can cover most scenarios where cached content might need to be created.

Given this, there is still no mechanism that notifies your Drupal site about the change in content, and therefore, no-cache tags can be invalidated and no context is helpful (as the content doesn’t vary by the situations in which it is displayed).

However, if you set a max-age of 3600 on the page, then it will cache its content for up to one hour before automatically invalidating, at which point the next person who views the page would get a brand-new updated version (fresh with new content from the remote service) which would then get cached for another hour. This way, you can leverage all the benefits of caching without causing your site to stop updating itself with content from the remote service. 

Summing Up-

Caching lets you retrieve data instantly without having to request it from the source. Given that, it makes up a significant part of website speed optimization. If you want to ease surfing experience for your users on the site, then enable the cache for the same. Drupal 8 has enhanced its caching capabilities considerably.

Jan 06 2020
Jan 06

The templating engine of Drupal 8 has seen a massive turnaround. Unlike Drupal 7, there’s Twig in Drupal 8 instead of PHPTemplate. Twig is basically a templating language for PHP i.e a tool used to output variables inside HTML. Fabien Potencier, the creator of the Symfony framework, gave life to Twig. Contrary to Drupal 7, you cannot call the regular PHP functions in your templates in Drupal 8. The way forward, in Drupal 8, is to create filters and functions.

Icon resembling human wearing blue shirt standing in front of a white board explaining Twig Extension in Symfony and Drupal

Twig extension gives more flexibility to process nearly anything inside the twig. Twig can be extended in many ways such as tags, filters, operators, global variables, and functions.

One of the major plus points of creating a twig extension in Drupal 8 is in the view.

Drupal 8 views can often be more challenging in the case where you want to perform operations on the value or need to process the content in the field. When you need to write code often, try to reuse it rather than writing it from scratch every time.

You must use a filter when you want to transform the data you want to display. Imagine you have a title that you always want to be capitalized. For example, twig has the capitalize filter that allows you to transform any text into its equivalent in uppercase.

I came across Twig Extension during one of my E-commerce projects where I had to print dynamic currency name. Drupal Commerce allows only 3 characters long currency code and they have also implemented their own Twig Extension to convert Price object into equivalent price format. So to handle this case where I have to show currency name with more number of characters, I had implemented my own Twig Extension. Similarly, there are several other cases where these Twig Extension can be very handful.

Let’s see an example where we will create a filter that will allow us to count the number of words in the article. The process of creating filters and functions is exactly the same as normal Twig. Also, you can use word count to display the reading time of the article or any other use case as per the requirement.

The main difference between regular Twig and Drupal 8 Twig is that, in Drupal 8, you must create a service definition of the class you are creating and the class must also belong to a namespace, otherwise it will not be registered as a Twig filter in the Drupal environment.

This example assumes you have a module called:


This will be the basic definition of the inn service.

    class: Drupal\twig_word_count_extension\TwigExtension\TwigWordCountExtension
      - { name: twig.extension }

The key tags are also absolutely necessary and that is what Drupal tells you what this class is supposed to do (that is, register it as an extension of Twig).

And now the source code that should be placed in the path defined in the class service definition key.


namespace Drupal\twig_word_count_extension\TwigExtension;

use Twig_Extension;
use Twig_SimpleFilter;

class TwigWordCountExtension extends \Twig_Extension  {
   * This is the same name we used on the services.yml file
  public function getName() {
    return 'twig_word_count_extension.twig_extension';

  // Basic definition of the filter. You can have multiple filters of course.
  public function getFilters() {
    return [
      new Twig_SimpleFilter('word_count', [$this, 'wordCountFilter']),
  // The actual implementation of the filter.
  public function wordCountFilter($context) {
    if(is_string($context)) {
      $context = str_word_count($context);
    return $context;

Clear your caches and now, if everything goes according to plan, you can use the filter in your templates.

{{ "shuffle me!" | word_count }} {# Return 2. #}

Note: If these twig extensions don’t have other service dependencies (i.e. if you don't inject services in them), the performance is not affected. However, if these extensions have lots of complex dependencies, for example, say those making database connections or perform heavy operations, the performance loss can be significant.

To avail help from our experts for your Drupal projects, you can check out our suite of services. You can also talk to us at [email protected].

Jan 03 2020
Jan 03

For years, Drupal site builders have endured a less than great experience with any media they wanted to use.  It was difficult to manage and reuse images; let alone video, audio, and other media.  A number of excellent contributed modules tried to bridge that gap in Drupal 7; however Drupal 8 committed to having a media manager in core.  

As of December 2019, that wait is over with the Media module now officially out of "experimental" and fully integrated into Drupal core.

Probably the most exciting change for site builders in Drupal 8 is that almost everything is an entity, and media is no exception.  That introduces one big issue for images - an image style is not so ealily added to your image as it was in Drupal 7.  Learn how to create and apply image styles for media following this tutorial.  It's not difficult, but it does require some planning, because it's now a four-step process.

Step One:  Set up Image Styles

Go to Configuration > Media > Image styles and define styles as needed. For this article, we will use "Gallery", but the steps can be repeated for additional styles as needed.  For simplicity and consistency, it's not a bad idea to use the image style names in the next step as well.

image styles

Step Two: Set up Media View Modes

Go to Structure > Display modes > View modes and navigate to the “Media” section. Add media view modes.

While it's not necessary to name the view modes the same as the image styles, it can help keep everything better organized, especially when there are many more styles than are being covered in this tutorial.

media styles

Step Three: Manage Media Display

Once you’ve created all your media view modes, go to Structure > Media types > Image > Manage Display and enable "Gallery".  Continue to enable all custom displays created in Step One.

custom display settings

Now that these are enabled, go to the "Gallery" display, find the image field and make sure its format is “Image.” Click the gear icon and set the image style.
Repeat this step for remaining displays.

manage display media

Step 4: Manage Entity Display

Now we'll see it in action.  I’m going to review how to setup fields in a content type, but this process can be used on any entity that allows for fields to be defined.

Go to the Manage Display tab of your content type, “Article” in my case. For the Default display, set the “Rendered entity” View Mode to “Gallery.” Now every article node when displayed with this mode will use that style to render the image field.

manage display content

Repeat this step for any other entity displays that have been created, and that's it.

Be sure to watch this video from our class on the Drupal 8 Media Module.

[embedded content]

See the full class here: https://www.ostraining.com/class/learn-drupal-8-media-module/

About the author

Rod holds two masters degrees and has been training people how to do "things" for over 25 years. Originally from Australia, he grew up in Canada and now resides just outside Cincinnati, Ohio.
Jan 03 2020
Jan 03

That’s nice, now why are you telling me this?

In you role as a project- or site owner you might not be aware of the implications the “End of Life” announcement has if your site is running on Drupal 7 right now. There are two things you should be aware of:

1. Active development of Drupal 7 stops on the EOL date.

This does certainly not mean that your site will come to a grinding halt on that day, but it does mean that Drupal’s strong points will start to fade going forward. The Drupal Association will no longer provide security releases for Drupal 7, no further development on the core framework will be done and development on the Drupal 7 version of most contributed modules will stop.

Security, flexibility and scalability are often reasons why Drupal was chosen for a project and this clearly has an impact. I knowingly say ”impact” because the robustness of the Drupal project prevents a full stop of support even after the EOL date. A number of partners will be selected to provide paid security support for several years and there will always be members of the community who are prepared to do some work on unsupported contributed modules.

2. Upgrading means migrating.

Upgrading your site from Drupal 7 to Drupal 8 means that you have to also migrate all content that is present in your site. The theme that is used to display the content on the site will also have to be re-developed. This only holds true for this specific upgrade and not for later upgrades from Drupal 8 to Drupal 9 for instance, more on that later... The massive structural changes of the inner workings of Drupal are the cause of this, highly inconvenient but certainly necessary to keep Drupal the modern framework we all need it to be.

Performing a migration and re-developing the theme mean that this needs to be discussed and planned well in advance. Depending on the size of your site the time needed may vary, but to wait until the EOL date arrives is obviously not a good idea.

I see, so what should I do?

The sensible thing to do is to start thinking about what steps are necessary to perform an upgrade to Drupal 8. Drupal 8 was released in November 2015, so it has been in production use for over 4 years now. It is a very stable and mature piece of software with a wide adoption worldwide.

As mentioned earlier, “under-the-hood” Drupal 8 changed significantly compared to Drupal 7. Upgrading therefore provides a chance to perform structural and visual changes to your site that you have in mind anyway. It doesn’t make sense to make big changes to your Drupal 7 site when you know that it’s official life will come to an end in 2021. If you now start to plan for incorporating these changes into the Drupal 8 version of the site, you still have plenty of time to thoroughly discuss these changes and efficiently spend your budget when the time comes to actually perform the upgrade.

The same goes for migrating your content. The upgrade provides an opportunity to think about what content you want to keep and how you can put it to it’s best use!

Drupal 9 will be released in 2020, do I have to do all this again? Should I postpone?

Drupal 9 will be released on June 3rd 2020. Since that is less than half a year away, it might seem better to wait a bit and move from Drupal 7 to Drupal 9 directly. That’s where the big “under-the-hood” structural changes in Drupal 8 come in, upgrading from Drupal 8 to later versions will be extremely easy and not require a full migration! This makes the move from Drupal 7 to 8 an exception, once you are on Drupal 8 upgrading can more or less be done with the click of a button!

So migrating to Drupal 8 first makes a lot of sense because you can start incorporating changes into your site directly, without having to wait for a move away from Drupal 7. This way you benefit from being on the new version of Drupal right away and are future proof from that moment on.

Ok let’s do this, how do we perform the migration?

There are 3 parts relevant to the migration from Drupal 7 to Drupal 8: upgrading code, rebuilding the theme and migrating content. To perform a successful migration we first need to understand where you want to go, so we first discuss what the Drupal 8 site will look like before we do anything else. We have extensive project management experience in house that will lead to a clearly defined product to deliver.

Once we know where we are going, it is time to look at the Drupal 7 site we are coming from. For projects we have not built ourselves this usually means we perform an assessment that tells us how the site is built and what we can expect from its content. The assessment’s outcome tells us how much work the migration will entail and forms the basis for an estimated budget and time needed to complete the project.

Do you want us to help you migrate your site? Then contact us here to plan an introductionary meeting and get started right away!

Jan 03 2020
Jan 03

That’s nice, now why are you telling me this?

In you role as a project- or site owner you might not be aware of the implications the “End of Life” announcement has if your site is running on Drupal 7 right now. There are two things you should be aware of:

1. Active development of Drupal 7 stops on the EOL date.

This does certainly not mean that your site will come to a grinding halt on that day, but it does mean that Drupal’s strong points will start to fade going forward. The Drupal Association will no longer provide security releases for Drupal 7, no further development on the core framework will be done and development on the Drupal 7 version of most contributed modules will stop.

Security, flexibility and scalability are often reasons why Drupal was chosen for a project and this clearly has an impact. I knowingly say ”impact” because the robustness of the Drupal project prevents a full stop of support even after the EOL date. A number of partners will be selected to provide paid security support for several years and there will always be members of the community who are prepared to do some work on unsupported contributed modules.

2. Upgrading means migrating.

Upgrading your site from Drupal 7 to Drupal 8 means that you have to also migrate all content that is present in your site. The theme that is used to display the content on the site will also have to be re-developed. This only holds true for this specific upgrade and not for later upgrades from Drupal 8 to Drupal 9 for instance, more on that later... The massive structural changes of the inner workings of Drupal are the cause of this, highly inconvenient but certainly necessary to keep Drupal the modern framework we all need it to be.

Performing a migration and re-developing the theme mean that this needs to be discussed and planned well in advance. Depending on the size of your site the time needed may vary, but to wait until the EOL date arrives is obviously not a good idea.

I see, so what should I do?

The sensible thing to do is to start thinking about what steps are necessary to perform an upgrade to Drupal 8. Drupal 8 was released in November 2015, so it has been in production use for over 4 years now. It is a very stable and mature piece of software with a wide adoption worldwide.

As mentioned earlier, “under-the-hood” Drupal 8 changed significantly compared to Drupal 7. Upgrading therefore provides a chance to perform structural and visual changes to your site that you have in mind anyway. It doesn’t make sense to make big changes to your Drupal 7 site when you know that it’s official life will come to an end in 2021. If you now start to plan for incorporating these changes into the Drupal 8 version of the site, you still have plenty of time to thoroughly discuss these changes and efficiently spend your budget when the time comes to actually perform the upgrade.

The same goes for migrating your content. The upgrade provides an opportunity to think about what content you want to keep and how you can put it to it’s best use!

Drupal 9 will be released in 2020, do I have to do all this again? Should I postpone?

Drupal 9 will be released on June 3rd 2020. Since that is less than half a year away, it might seem better to wait a bit and move from Drupal 7 to Drupal 9 directly. That’s where the big “under-the-hood” structural changes in Drupal 8 come in, upgrading from Drupal 8 to later versions will be extremely easy and not require a full migration! This makes the move from Drupal 7 to 8 an exception, once you are on Drupal 8 upgrading can more or less be done with the click of a button!

So migrating to Drupal 8 first makes a lot of sense because you can start incorporating changes into your site directly, without having to wait for a move away from Drupal 7. This way you benefit from being on the new version of Drupal right away and are future proof from that moment on.

Ok let’s do this, how do we perform the migration?

There are 3 parts relevant to the migration from Drupal 7 to Drupal 8: upgrading code, rebuilding the theme and migrating content. To perform a successful migration we first need to understand where you want to go, so we first discuss what the Drupal 8 site will look like before we do anything else. We have extensive project management experience in house that will lead to a clearly defined product to deliver.

Once we know where we are going, it is time to look at the Drupal 7 site we are coming from. For projects we have not built ourselves this usually means we perform an assessment that tells us how the site is built and what we can expect from its content. The assessment’s outcome tells us how much work the migration will entail and forms the basis for an estimated budget and time needed to complete the project.

Do you want us to help you migrate your site? Then contact us here to plan an introductionary meeting and get started right away!

Jan 03 2020
Jan 03

If you look up the word ‘terraform’ in the Oxford English Dictionary, the meaning that you find may make you reminisce about some of the science fiction movies or TV series you have watched or heard of. And you may start wondering if something like ‘terraforming’ is actually possible. Transformation of another planet to make it Earth-like, which is what terraform means, would seem like a glorious idea. As there’s always a ‘but’ associated with any brilliant thought that we have, this terraforming of Mars or any other planet is not possible with the current technologies, says NASA.

Terraform process of a planet shown through an open sky filled with white curves to resemble shooting stars

Anyway, on Earth, terraforming is possible. (Although this is in no way referring to the tackling of climate change, it would be nice to see some strong measures being taken). Earth, our home, is witnessing a wave of digitisation all around in this 21st century. Amongst different digital innovations that are happening, one of the open-source tools, which is incidentally, and rightfully, named Terraform, is here to metamorphose the web arena. And Drupal web application infrastructure can reap the benefits of Terraform to a great extent.

Infrastructure As Code with Terraform

Logo of Terraform with Capital T formed by violet parallelograms and Hashi Terraform written below it

To better understand Terraform, let’s start with an example where you are hosting a Drupal site on AWS. Managing the infrastructure here is a crucial aspect. You will be required to create an Amazon Elastic Compute Cloud (EC2) instance with your Drupal code to serve traffic. But that’s not all. There are more things to be taken care of. You are required to look after the identity and access management (IAM), subnets, auto-scaling groups, virtual private cloud, security groups, target groups, load balancers, Elastic load balancing and many more. Infrastructure as Code (IaC) is your solution to manage infrastructure resources effectively.

IaC automates the provisioning of infrastructure and allows your digital firm to build, deploy and scale cloud applications rapidly, cost-effectively and with minimum risks. It utilises top-of-the-line descriptive coding language for automating the process of provisioning of IT infrastructure. This reduces the need for developers to manually provision and manage servers, operating systems, database connections, storage and several other infrastructure elements. To apply IaC, leveraging Terraform is your best bet.

What is Terraform anyway? It’s a configuration orchestration tool that can work with private cloud, public cloud or on-premise system and has the provision for secure and convenient design, governance and improvement for infrastructure as code. As a cross-platform, extensible tool, Terraform codifies APIs into declarative configuration files. These can, then, be shared amongst team members, treated as code, edited, analysed and versioned.

“Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently.” - Terraform.io

Terraform enables you to define infrastructure in config/code and lets you rebuild/change and track alterations to infrastructure easily. Terraform’s speed and operations are impeccable. Its plan command ensures that you make alterations to the infrastructure predictably and safely. That is, you will know what Terraform will do before you make any changes which leaves zero possibilities of any sort of surprises later on. By building a graph of all your resources and parallelizing the building and modification of any non-dependent resources, it gives insights into dependencies in the infrastructure. And, intricate changesets can be applied to the infrastructure with the help of minimal human interaction. Being open-source, it also has a lively community for you to easily engage with them and start using it.

Table with rows and columns showing comparisons between Terraform, Ansible, Chef, Puppet and SaltStackComparison of Terraform with similar tools | Source: IBM

IBM states that, in general, Ansible, Puppet, SaltStack and Chef are considered to be the configuration management tools where the software is installed and managed on existing server instances. Terraform, on the other hand, is considered to be an orchestrator which provides server instances itself thereby leaving the job of configuring those servers to other tools.

Bar graph with horizontal, blue coloured bars to show statistics on market share of Terraform, Ansible, Chef, Puppet, and Salt

Even though Ansible leads the adoption charts, it’s the Terraform that has witnessed a surge in users in recent times. According to a 2019 State of the Cloud survey, conducted by RightScale, Terraform displayed the strongest growth. It expanded from 20% in 2018 to 31% in 2019.

Implementing serverless architecture with Terraform and Drupal

A session at Decoupled Days 2019 showed how Terraform can be used in the Drupal web application infrastructure. It demonstrated how to architect a serverless solution for serving the frontend with data that is fetched via an API from Drupal. The serverless frontend application was hosted with multiple cloud providers available via a CDN (Content Delivery Network). Such an application could be provisioned several times in multiple regions of more than one cloud providers with the help of Terraform. Writing wrapper scripts for Terraform streamlined the process of deploying infrastructure.

Drupal’s multisite capabilities, where multiple separate websites from a single codebase could be run, made the hosting requirements for the backend simple. The Frontend part wasn’t easy as it required to run multiple instances to emulate the number of web properties. All the websites were built on a common stack and the infrastructure resources could be easily shared where needed.

Drupal’s multisite capabilities, where multiple separate websites from a single codebase could be run, made the hosting requirements for the backend simple.

In this decoupled Drupal setup, the infrastructure for static web assets (comprising HTML, CSS, JavaScript, fonts and others) required Amazon S3 or similar storage and a CDN distribution with origin set to the S3 bucket. The frontend code was done using Angular.

With the presence of different environments and the need for an endpoint to access the API, hardcoding the URL during the build time was necessary. IP whitelist was used for Drupal server for high-level security. All the content was retrieved from a proxy. The proxy could be placed behind a CDN thereby improving performance and availability.

With several websites and environments, infrastructure automation was needed. Terraform made it all possible. It enabled the process of writing similar scripts for AWS and Aliyun, for instance. Terraform modules were run once to prepare the environment and create IDs of all the resources. The IDs were set in a configuration file which was accessible to all the Jenkins runs. This made sure that the front end code could be deployed from the CI (Continuous Integration) builds. Terraform also helped in administering the state of all the infrastructure.


System administrators and DevOps engineers strive to do more with less. Defining infrastructure in code and automating its deployment brings about operational efficacy and lower administrative overhead. Terraform is all set to be your go-to toolset for infrastructure automation. And, it can be a great asset in Drupal web application infrastructure.

Using Terraform can be fun. For starters, you can take Terraform for a spin and simply play with it to better understand its efficiency for your digital business.

Offering fantastic digital experience has always been the objective of OpenSense Labs. Talk to our experts at [email protected] and understand more about Terraform’s capability in transforming the landscape of your web application infrastructure.

Jan 03 2020
Jan 03

Ok, the problem is clear:

  • Your composer based Drupal site put code base to the /web folder
  • You are using a shared hosting which maps your primary domain to /public_html, and you can't change that

Now your users will have to browse your site as http://example.com/web . And it is not cool.

So how to serve your site from the subfolder /public_html/web but removing the /web suffix so it becomes transparent to users?

Here are the steps, as I learned from this thread on Drupal.org

1. Open your settings.php file and add the following code:

if ( isset($GLOBALS['request']) && '/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME') ) {
    $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');

2. Create a .htaccess file on the /public_html folder with:

<IfModule mod_rewrite.c>
RewriteEngine on
# Redirect to the subdirectory because that's where Drupal is installed
RewriteRule (.*) web/$1 [L]

3. Update .htaccess under /public_html/web folder

Uncomment the line RewriteBase and set it to:

RewriteBase /web

4. Clear the cache and run update.php

Your site should work by browsing http://example.com now (without the /web suffix). Your menu items may still have the /web part, but it will be gone after some hard refresh.

5. (Bonus) If you want to redirect http/https and wwww/non-www:

On the .htaccess file under /public_html/web, please add those lines between the <IfModule mod_rewrite.c> tag:

This is to redirect non-https + www to https + non-www:

  RewriteCond %{HTTPS} off [OR]
  RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
  RewriteRule (.*) https://example.com/$1 [L,R=301]

And this is to redirect non-https + non-www to https + www"

  RewriteCond %{HTTPS} off [OR]
  RewriteCond %{HTTP_HOST} !^www\. [NC]
  RewriteCond %{HTTP_HOST} ^(.*)$  [NC]
  RewriteRule (.*) https://www.%1/$1 [R=301,L]

You can see those examples on Htaccess guide.

Jan 02 2020
Jan 02

So my blog's been offline for a while now. I think there was a security issue sometime around 8.2.2 because I just upgraded the public version of the site from 8.2.1 directly to 8.8.1. I actually did an upgrade to 8.8.0 alpha-something that I used to bootstrap the upgrade to 8.8.1, but public-facing the site made a pretty big jump. Some of this is due to laziness on my part, but a pretty significant portion of my disappearance has been due to a new (to this blog) position within Acquia. I've been at Acquia for nearly 6 years now (in April of 2020), and for almost the last 2 years, I've been helping Acquia re-develop the ContentHub product.

ContentHub is a really interesting problem space. I tend to get sucked into these very nuanced, support-everything-imaginable situations with Drupal module and core development, and ContentHub is no different in that respect. Ultimately, it's intended to be a syndication engine, taking content from one site and materializing it on another. However, the nuance of doing this between Drupal sites is quite detailed. In order to solve this, we approach content syndication in a 5 step process, with 2 steps happening on the originator, 2 steps happening on the receiver, and 1 step happening within our service.

  1. Dependency Calculation (Originator)
    Any given piece of data within Drupal might depend on dozens of other pieces of data. The common "article node" that Drupal 8's standard profile ships with depends on around 40 other entities at the very least. These include the node type, field storage and config, author, tags, image(s) and any supporting entity bundle/field/view mode/form mode data each of those entities requires. Even simple entities are quite complicated in terms of what data they require in order to operate. We can't really "depend" on any of these things existing on the receiving end of our syndication pipeline, so we have to package it all up and send it en mass and let the receiver figure out the details.

  2. Data Serialization (Originator)
    Ideally, this is a "solved" problem in Drupal 8. The 8.x-1.x version of ContentHub tried to use the serialization engine that ships with Drupal core in order to do much of this work, but this approached tended to come up short when dealing with multilingual data. This may have been a flaw exclusive to ContentHub 8.x-1.x, but ultimately, when looking at this problem space, it seemed easier to have each field declare how it was to be serialized, deal with all language level data on a per field basis, and have a fallback mechanism for unrecognized field types for "best guess" solutions.

  3. Communication (Originator->Service->Receiver)
    Once we've found all our dependencies and serialized them, we send that data to an Acquia specific service whose job it is to filter data by customer-defined criteria, and send the appropriate data to any receiving sites the customer might have on a per-filter basis.

  4. Data Collection (Receiver)
    Since only filtered data is sent to a receiver, it may not actually get all the data required to install a given piece of content, it just gets the content itself. Each piece of data is constructed with a reference to all its dependencies so that a complete list of requirements can be built before attempting to import anything.

  5. Data Import/Site Configuration/Dependency Handling (Receiver)
    Ok, this is a bunch of stuff to have all in one step, but when you have a giant list of completely different types of data with different module & configuration dependencies, you have to be flexible. In this step we start by identifying all the required modules for an entire import. Once that's complete, we check to see if those modules exist on our receiver and bail out if they don't. If they DO exist, we enable them and start parsing through the incoming data. This is tricky too though because we can't create a new node without first creating the node type and adding all the fields to it. If one of those fields references taxonomy terms from a particular vocabulary, we have to make sure that vocabulary exists... etc, etc. To this end, we loop our data set progressively creating the dependencies based upon what we have locally available and what's required to support our incoming data. Eventually, we'll process the entire incoming data stream finishing with the original entity that was requested for syndication.

Having outlined this basic flow, I want to contrast this with Migrate for a moment. Both Drupal 8 & 7 migrations happen on a per-entity-type basis. All the incoming node types are created before any nodes will be created. All the users will be created before nodes. All the terms, etc before most nodes (based on what dependencies any migration might have). This is really sensible since we tend to use Migrate for an entire site's worth of data at a time. ContentHub doesn't have this luxury since as little as 1 item might go to a site for syndication, or as much as many thousands. Whatever the case, ContentHub has to be capable of identifying how to handle any incoming entity type, creating that entity type, and moving on to some other based upon how the dependencies are stacked in a given Drupal setup.

This approach is really powerful because it ends up acting very similarly to the Features module. Since ContentHub can syndicate any sort of entity (so long as it supports uuid... don't get me started) it can package up things like content types, views, etc and send them to another site, complete with automated module dependency calculation. The team's common demo example has been installing Umami as an originator of content, and then using Standard or Minimal as a receiver, and then watching all the Umami configurations and content stream in to fill out a blank site. Acquia's demo team has actually been using it for setting up demo content in a limited capacity, and I'd love to help push that further by figuring out how to use our data format to uninstall data from a site (by reverse dependency encumbered-ness).

Ultimately, I'm really pleased with the efforts of the last almost 2 years of time. I think ContentHub 2.x is a really cool tool that a lot of people could use to varying degrees to do different compelling things. We included a couple of drush commands with it so that people could play with it without subscribing to our service. They can import/export data from manifest files, and are really useful for demoing the product and also doing development in a completely controlled manner. If you get a chance to play with ContentHub 2.x I'd be very interested to hear from you, or if you want to ask questions, please let me know!

Jan 02 2020
Jan 02

Major League Hacking’s Local Hack Day - Build is a global day-long hack day, which brings ideas to life with a worldwide community.

The Local Hack Day Build was scheduled from the 1st-7th December 2019 in different cities across the globe. A 12 hours hackathon known as BUILD was carried at more than 200+ locations during this period. Facebook and MLH were the event sponsors! 

QED42’s Pune office hosted approximately 65+ bright and curious minds for the Local Hack Day - Build on the 7th December 2019! This included a considerable amount of college graduates.

MLH Local Hack Day 2019

I had the opportunity to engage with Facebook Developer Circle Pune. To my surprise, students possessed knowledge about technologies like Docker, Git, and presented innovative ideas. Within a span of 12 hours, groups had created both desktop and mobile applications, which was commendable.

Let me walk you through the Local Hack Day at QED42. 

| Introduction

We kickstarted the event started with the MLH Local Hack Day introduction by Sangeeta Gupta (Facebook Developer Circle Pune Lead). Post this, Sayak Sarkar conducted a brief session on Git and Github. 

MLH Local Hack Day 2019

Some groups came up with innovative ideas, while others received ideas from the organizers. And finally, the event began! 

| Event Kick-Off

Groups of curious and innovative minds started working on their prototypes. In the middle of the prototype creation process, the organizers had arranged scrumptious lunch for everybody. Post lunch the groups resumed work on their respective prototypes.

MLH Local Hack Day 2019

| Interaction with FDC, Hyderabad

We also had the opportunity to interact with our sister community Facebook Developer Circle from Hyderabad. They were also hosting the MLH Hack Day!  Sharing updates and stories with them was an absolute pleasure. We played a fun game between Pune and Hyderabad folks, where each team has to mention a programming language name until other team runs out of known language names.

MLH Local hack day Facebook Developer Circle Hyderabad

Among several innovative ideas and demos, here are a few of my favourites:

  1. An application that enables children with down syndrome identify wet and dry waste by looking at the images. The app guides and communicates via text to speech functionality, whether or not the choice made by the individual is right. This helps improve the performance of special children. Link: https://github.com/Amarn7/Learn. Team Members:

    1. Amar Nagargoje

    2. Atharva Barve

    3. Tejas Bhadane

    4. Nirav Madariya

  2. An Online Judge System which also is one of the world's first Self Learning Ladder - based judge system, along with developing their own indigenous IDE. To make this project more of a Capstone Project, the team developed a Web interface and an Android App interface too. Link: https://github.com/pratikdaigavane/Son-Of-Anton. Team Members:

    1. Ayush Shah

    2. Kunal Raut

    3. Prathamesh Shiralkar

    4. Pratik Daigavane

    5. Saarth Deshpande

    6. Tejas Joshi

    7. Utkarsh Atre

  3. Built an internet bot to buy and sell digital gold on Paytm Gold at the best possible buying and selling prices. Enabling users to earn money without doing anything. Link: https://github.com/PranshuTople/GoldDigger. Team Members: 

    1. Pranshu Tople

    2. Pallavi Saha

    3. Shubham Nandi

    4. Rishabh Agarwal

  4. Women Safety App where the map will be segregated on the basis of the danger zones in the city based on the threat level. The areas will be colour-coded as grey, yellow, and red. The mobile will be connected with the GPS for live tracking if a person goes into the threat zone a prompt will be sent to the emergency contacts. If the person stays too long in the danger zone without any activity, the alert will be sent to the police department. Areas are segregated by the threat level determined by crowdsourcing the information about any particular area. Link: https://github.com/Knightfire1998/DotDashDot3.git. Team Members:

    1. Reshikesh Umakant Dhanrale

    2. Akshit Abhay Keoliya

    3. Shweta Singh

  5. Learning to use Azure Cloud Cognitive services and GitHub integration. Mood Detector - Captures your face and detects the mood like Happy or Sad. Link: https://github.com/AJV009/mooddetector/Hacker name: Alphons Jaimon

  6. Millions of saplings are planted every year, and millions die too. Because they are not taken care of. This is a humble attempt to track all such saplings around a volunteer's vicinity keeping the external factors like weather into account. Link: https://github.com/Devendrabhat/angry-buddha. Team Members:

    1. Aniruddha Kibey

    2. Devendra Bhat

    3. Shagun Kaushik

    4. Shreyas Kalmegh

You may also read about the other projects here: https://github.com/devcpune/solid-doodle/

MLH Local Hack Day 2019

Here are a few more highlights from the Local Hack day: 

  1. FDC Pune members launched the official Facebook Developer Circle: Pune organisation on GitHub and made the first solid-doodle repo. Currently, it has 102 commits and 23 contributors in the repo. Link: https://github.com/devcpune/solid-doodle/

  2. We discussed the DevC Training courses and how they can prove to be extremely beneficial for the community.

MLH Local Hack Day 2019

At the end of the local hack day, we collected the participant’s feedback in a rather innovative way! Participants drew emoji’s on colourful sticky notes to express their feedback about the event. 

MLH Local Hack Day 2019

We had a wonderful time collaborating with participants from different domains. Hacking, brainstorming, and innovating collectively at the Local Hack Day - Build! 

Jan 02 2020
Jan 02

A magnificent year has gone by! 2019 saw Drupal evolving by leaps and bounds. As the year comes to an end, here is a look at some of the significant moments from the Drupal world that happened during this time.

2019 written in orange amidst a black backdrop

18 years old: Drupal is no longer a kid!

It was on 15th January 2001 when the world saw Drupal burst onto the scene. Drupal 1.0.0 was released on this date. Since then, with the support from thousands of open source enthusiasts and contributors, it is today one of the market leaders in the CMS segment. Drupal turned 18 in 2019 and Drupal Community revelled in its success with much mirth.

Screengrab of a Drupal 2019 tweet with a name and image on top left and text below itDrupal Community members were surely excited

New Drupal releases

As per Drupal’s 6-month release cycle, the Drupal fraternity witnessed two new Drupal versions being released in 2019 - Drupal 8.7.0 and Drupal 8.8.0.

Drupal 8.7 was one step closer to a better future. It came packed with much-needed features, particularly the stable JSON:API core module and the stable Layout Builder module. With JSON:API support being included as a core feature, displaying your Drupal content in decoupled websites, mobile applications and others would be a downhill task.

[embedded content]

After being introduced as an experimental module in Drupal 8.5, the announcement of a stable and production-ready version of the Layout Builder module in Drupal 8.7 was huge news. Its provision for state-of-the-art content management solution with features like drag and drop management for content blocks and the quicker process of creating layout templates for content is a massive improvement.

[embedded content]

Drupal 8.8, that released on 4 December 2019, is the last normal feature release of Drupal 8. It came with a stable version of the Media Library module that was previously added as a beta experimental module in the core. Media Library streamlines the reuse of images, documents, videos and other assets across the website.

[embedded content]

Claro, a new experimental administration theme, was also introduced in Drupal 8.8. Its intuitive features like touch-friendly administration pages and more accessible colour combination and contrasts will definitely enthral website handlers.

[embedded content]

Drupal 8.8 also introduced a new experimental Help Topics module for further enhancement of in-Drupal help.

The Composer Initiative yielded great results as Drupal 8.8 became the first release that included native Composer support.

From the vantage point of businesses

With Drupal 9 set to be released in June 2020, the Drupal business leaders, as stated by Drupal Business Survey 2019, were eagerly looking forward to it. The survey revealed that the thought leaders from the Drupal circle had a lot of anticipations from Drupal 9.

Pie chart with different variations of blue colour in different regions to show Drupal Business Survey 2019(a)Pie chart with different blue coloured separations to show Drupal Business Survey 2019(b)

Source: Drupal.org

Majorly, these were the key results from the survey that showed what Drupal business leaders are excited about:

  • Streamlined upgrade path from Drupal 8 to Drupal 9
  • Ease of update. No large jumps on functionality changes when moving from one version to another
  • Better interface and improved user experience for developers as well as administrators, content editors and end-users.
  • The possibility of Drupal development becoming more simpler and a go-to option for not only the enterprises but also small and mid-size projects.
  • Drupal getting more powerful as an API-first CMS.

The survey did show that there are apprehensions about the migration from Drupal 7 to Drupal 8 or even from Drupal 7 to Drupal 9. It is perceived as a business-critical decision and the one that may be very intricate.

A clear picture: Drupal 9 upgrade

Infographics consisting of blue strip at centre and arrows on the left to show Drupal 2019 releases and future release pipeline

By the end of 2018 and in the entire 2019, Drupal Community began to see the clarity with the state of Drupal 7, Drupal 8 and Drupal 9. In DrupalCon Seattle 2019, the Driesnote presentation clarified that Drupal 7 will be fully supported by the community till November 2021 in addition to receiving security patches. From thereon, until at least November 2024, vendor support will continue.

It further stated that the Drupal 7 to Drupal 8 upgrade can be an uphill task for large sites in particular but nevertheless, once done, its advantages outranks the challenges.

Driesnote presentation in DrupalCon Amsterdam 2019 showed that the progress on Drupal 8’s Automated Updates Initiative has been spectacular last year.

[embedded content]

Symfony 3, which Drupal 8 is highly dependent upon, has an End-Of-Life date towards the end of 2021. That means Drupal 8 will be End-Of-Life by November 2021. Essentially, by the time Drupal 8 reaches End-Of-Life, every Drupal site should have upgraded to Drupal 9. Driesnote in DrupalCon Amsterdam also stated that the upgrade from Drupal 8 to Drupal 9 will be extremely easy. Consistently checking for and removing the use of deprecated code would make the migration from Drupal 8 to Drupal 9 a very simple one.

Rather than working on Drupal 9 in a separate codebase, it is being built in Drupal 8. Therefore, the new features and functionalities are being added as backwards-compatible code and experimental features. As the code attains stability, old functionalities will be deprecated.

Drupal project pipeline

Drupal adoption rate saw a palpable growth last year.

Graphical representation showing different lines forming regions to specify usage statistics of Drupal


Table with rows and columns showing usage statistics of DrupalSource: Drupal.org

When it comes to the experience that the business leaders had selling Drupal projects, according to Drupal Business Survey 2019, it has been fantastic. While the Drupal project pipeline has grown or remained at the same level, the average deal size has proliferated. Future of the Drupal project line is predicted to remain steady.

Pie chart with different blue coloured regions showing Drupal 2019 project pipelineSource: Drupal.org

When asked about the type of projects that the respondents completed in 2018 and the industries in which they implemented Drupal projects for providing ambitious digital experience, ‘Education’ turned out to be the most popular industry. Industries like ‘Travel and Tourism’, ‘Sports’, ‘Telecommunications’, and ‘Logistics and Support’ also witnessed an increase in the implementation of Drupal projects.


On examining Drupal.org’s contribution data in a 2018-2019 report, it was found that the number of contributors and contributions have increased to a great extent. There was an 8% rise in the number of Drupal.org projects that received contributions when compared to 2017-2018 period. More than half of the contributions were done on contributed modules. Interestingly, the big jump in non-product credits was discernible. This includes activities like organising different Drupal conferences, promoting Drupal, and community working groups.

Bar graph consisting of green and blue horizontal bars to represent Drupal contributionSource: Dries Buytaert's Blog

There was a noticeable increase in the number of contributions that the Drupal.org’s credit system received. The top 30 contributors (the top 0.4%) accounted for 19% of credits. (Our very own Drupal architect Gaurav Kapoor was amongst them.)

It was also found that most of the contributions were sponsored. Even though sponsored contributions remained on the higher side when compared to volunteer contributions, the latter is significant to Drupal’s growth and success as an open-source CMS.

Bar graph with green and blue horizontal bars to show Drupal contributionSource: Dries Buytaert's Blog

Drupal Business Survey 2019 shows that 111 out of 118 businesses contributed to Drupal. The survey delineated that the businesses have been contributing in multiple ways that ensure good health of Drupal. Whether it’s the contribution to modules, themes and distributions, or improvement of Drupal’s documentation, or sponsoring and organising events, businesses have been helping Drupal grow in their own ways. Some of the businesses, unable to contribute, cited lack of time and resources as the reason.

Bar graph comprising of blue horizontal bars to show statistics on Drupal contributionDifferent ways to contribute to Drupal | Source: Drupal.org

Decoupled approach

Since the time when Dries Buytaert, founder and project lead of Drupal, talked about RESTful Drupal and later about the future of Decoupled Drupal, this approach has evolved into something more exciting and attained new heights.

The two ways of decoupling Drupal include progressive decoupling and fully decoupling. But, as 2018 neared its end and 2019 began to unfurl, the fully decoupled approach branched into two methods. It was due to ever-increasing convolutions of JavaScript development that, in addition to existing fully decoupled application, it also took the form of a fully decoupled static site. The popularity of JAMstack and its reputation of rendering high performance, top-notch security and fewer complexities during the development gave wings to approach of building fully decoupled static sites.

Most importantly, API-first Initiative made great progress and strengthened Drupal’s capabilities as headless or decoupled solution. Not only has Drupal core started offering out-of-the-box JSON:API implementation with JSON:API module landing in core since the launch of Drupal 8.7, but several new improvements to JSON:API support in the contributed space were seen. (For instance, an interactive query builder called JSON:API Explorer.)

[embedded content]

Diversity and inclusion

Although Drupal’s contributors were found to have become more diverse in Drupal.org’s contribution data studied between 2018-2019, more effort needs to be put in to fill the gaps.

For instance, in this report, some interesting facts emerged when gender diversity and geographical diversity of Drupal.org contributors were studied. Even though the contributions made by persons who do not identify as male increased by one percent in 2018-2019 period, the gender imbalance in Drupal is still a worry. Non-male contributors accounted for only 8%.

Three bar graphs consisting of vertical bars of blue and green colours showing statistics on Drupal diversity and inclusionSource: Dries Buytaert's Blog

When it comes to geographical diversity, Europe and North America continued to dominate the contributions space. While the United States topped among the countries, India remained the second-largest contributor. Overall, the contributions from Asia were on the decline (particularly India in spite of it being the second-largest contributor).

Drupal Community understands the need to foster diversity and inclusion. Several efforts have been taken in 2019 to show its strong will to diversify its community and be more inclusive.

Drupal Association, like in 2018, changed its logo to show its support for LGBTQ+ community for the whole month of June (Pride Month).

Drupal logo, resembling a droplet, in Rainbow colour on left and 'Drupal Association' written on left

Listening to a more diverse group of people can be an inspiration to new contributors from all gender identities, races, religious groups, geographies, ethnicities and more. There were significant efforts made to help more people from underrepresented groups speak at Drupal conferences and workshops. For instance, Drupal Diversity and Inclusion group hosted a speaker diversity training workshop in September.

In their resolve to diversify the leadership group, Drupal Association decided to elevate a diverse group of leaders. The nominations for community elected board position were open for all.

Climate change

It was also the year when a teenager took the world by storm. An unlikely teenager somehow got the world’s attention. Greta Thunberg inspired millions of people to join the global climate strike in September which turned out to be the largest climate demonstration in human history.

On top of green background, 'Digital climate strike' written on left and a text supporting it on right

Drupal.org, along with thousands of websites across the globe, posted a banner message declaring that it has opted for a global digital climate strike.

End thoughts

2019 proved to be remarkable for Drupal. It reached new avenues. It kept getting bigger. It realised where it lacked and showed strong resolve to improve.

Drupal 8 isn’t done yet. It’s gonna be here for a while and will continue to offer enriching digital experiences all over the world. But, eventually, Drupal 9 will take over. It’s going to be released in a few months from now and Drupal Community is very excited to welcome it. A lot of interesting things are lined up for Drupal in 2020 and it will be amazing to see them all happening.

Happy New Year to all the Drupalists! Grow Drupal, grow with Drupal.

Jan 02 2020
Jan 02

Recent travel to Rwanda has brought me to build a POC (Proof-of-Concept) with a familiar stack, only in a very different structure.

To better understand why the POC was built that way, I should give you the backstory.

The Backstory

In 2016, I was invited to present about Drupal & Elm in DrupalCamp Tokyo. I always like to bring this fact up in any kind of conversation - but this time there’s even a reason beyond my usual bragging rights: The flight is terribly long from Israel to Tokyo. Twenty-four hours door-to-door kind of long.

As it so happened, a short time before my flight, Adam, Gizra US Director had virtually dropped a PDF on my table. I was preparing myself for yet another long RFP (Request for proposal) with an impossible spec, and an even less possible timeline. I was surprised to see that was not the case. That PDF was forty-something pages, with a wireframe per page and some notes, showing the flow of a rather interesting app.

Wireframe from the spec

Three years later I still refer to those pages as the best spec we’ve ever received. The people behind those wireframes were Dr. Wendy Leonard and her Ihangane team. They were planning an electronic medical record for an HIV prevention program in Rwanda.

I was really impressed. Sure, the wireframes were rougher than usual, but they did exactly what they were supposed to. The team was smart enough to not rush into development and in fact, they even printed out the spec pages, went to the field, sat with nurses, and let them click on the screens. The printed screens. They clicked on paper!

Anyway, did I ever mention I was invited to Tokyo in 2016?

That long 24 hours flight. I’ve finished my book (“Ancillary Justice”), watched a movie (“Wreck-It Ralph”, as for some reason I love watching cartoons on planes), and there were still many hours before my arrival. So I took my laptop out, spun up a Drupal backend and an Elm frontend - and the first POC for Ihangane’s app called “E-Heza” was born in the sky.

The Good Ol’ Days

And so began the development. A decoupled architecture, where we had a RESTful server in the backend and Elm in the front. Like any project we had: different challenges, deadlines, deadlines we missed, scope creep, managing the project, managing the client, managing expectations, delivering, hot fixing, being proud of what we’ve accomplished, having a technical debt. Rinse and repeat.

While we were developing, the Ihangane team was hard at work implementing our work in the field. In fact, they were able to get it going in a dozen health centers in Rwanda. And while it worked for the most part, there was one challenge we knew was lurking, and waiting - Offline.

Have you ever worked with non profits, or NGOs, and they tell you they have a need for a site, and some of its users are in developing countries where infrastructure isn’t always good, internet is slow, and so we must take care of a light theme and shave every single byte possible, but then in the design they insist on hero banners with huge images, and every possible JS transition?

Well, we have. But that was not such a case. This time it was for real - all health centers had internet, but it was not rare for them to have the connections dropped for days on end. And so, we decided it was time to implement a proper offline support. The reason I say “proper” Is that we actually had offline support from the get go, but it was a very crude one. Only after the nurses checked all the patients, and a “session” was done, did the nurses manually start a sync process. But that wasn’t very nice, and we decided to go with “opportunistic syncing” - where data was pushed and pulled whenever an internet connection was available.

Offline & Service Workers

I’m going to side step, and go technical here: Getting offline support was admittedly a bit easier than I had feared. It is surely the most complicated part of the system, but we were able to keep it confined to the edges of the front-end application.

Elm, in all its greatness, already taught us to think about interacting with JS the same way we would with a remote server. So, instead of having Elm contact directly the remote server, we’ve placed a service worker as a middleware.

That meant that Elm keeps using HTTP requests, the same way it always did, but now we intercept those requests, and the service worker decides - are we online, then call the server and sync the data; Or are we offline, and we should use the data from IndexDB. To make the wiring of the offline part to Elm even less disruptive, we’ve structured our responses from the service worker to be similar to the ones we used to get from the server. In other words, the change was minimal, and it looks beautiful.

But still, as one can imagine, adding this layer brings a new set of challenges. Our app isn’t a news reader, where the worst case scenario is you cannot read your news. No, our app is all around creating new content, and the worst-case scenario for us is losing patient data.

The Rwanda Visit

Back to the main narrative. I was invited to attend a workshop that Ihangane had organized in Rwanda (you know, like that one time I was invited to Tokyo in 2016). It was a two-day workshop where different stakeholders came, and had discussions not only around Ihangane’s solutions but also in general - how to improve the health care in Rwanda.

Some parts were boring - the usual amount of suits talking about things they don’t necessarily know much about. But there was one topic that I found especially interesting: The Government of Rwanda is spearheading a “Health Cloud” effort. This project is a huge undertaking. To give just one example of the many challenges involved - currently in Rwanda when a baby is born, they don’t always get a national ID. In other words, there’s no unique identifier for every person - so the challenges are somewhat larger than just which best methods to use to create this platform.

But what really caught my attention, is how dedicated they were to make sure no vendor locking will happen under their supervising eye. I really appreciated it. I can only imagine how many private, for-profit organizations are trying to get their foot in the door in those emerging markets. I’m not saying all for-profit organizations are evil, I’m just not naive.

Rural Rwanda

I love saying “Rural Rwanda.” With my Israeli accent, it’s a real tongue twister for me. I also loved having a one day visit in the outskirts of Kigali, visiting nurses in Muhondo health center and see our system in action.

Spent a whole day in rural Rwanda, watching - in action - an @elmlang web-app with a #Drupal backend we've built for @ihanganeproject.

No marketing landing pages, no sale funnels, no targeted ads. Just a web-app that helps provide a better health care to mothers and their babies pic.twitter.com/PnLqV0vpSQ

— Amitai Burstein (@amitaibu) November 14, 2019

Make sure your speakers are on. That’s what I call true “stress testing” - when you have a room with about a hundred mothers and their (cute, yet screaming) babies, every extra second the app takes, is another second people are waiting.

What a great day it was for us - watching with our own eyes, seeing the good parts of the app, finding a couple of bugs, but mainly spotting workflows that could be improved, and benefit the team operating it, as well as the patients. When you see these women that have walked for hours with their babies on their backs to reach the health center, “try to refresh the page” or “let’s wait a couple minutes for the system to fully sync” is becoming less acceptable. I was very proud to see how we were able to be part of a thing that really does good to much less fortunate people.

Letting it All Sink In

  • We have mothers with HIV or high risk for HIV.
  • We have their babies, that need to be examined, and be checked for different signs of malnutrition.
  • We have no internet connection in some areas.
  • We need to support Android devices, as the measurements taken in the field are being registered in those devices.
  • We have this “Health Cloud” idea, that we want to help think about. We don’t want to follow a typical enterprise kind of thinking, but rather use our own more radical one.

At the same time of my visit to Rwanda I have started my affair with Plain text accounting with hledger. I think this quote sums it up nicely:

Accounting data is valuable; we want to know that it will be accessible for ever - even without software. We want to know when it changes, and revision-control it. We want to search and manipulate it efficiently.

It took my brain about a month to switch the word “Accounting” with “Medical”, as in:

Medical data is valuable; we want to know that it will be accessible for ever …

Then another thing happened. Did I ever tell you about my invitation to DrupalCamp Tokyo in 2016? Well, while I was in Rwanda I was invited to DrupalCamp Tokyo 2019.

Once again I was in a plane, finished my book (“The Sudden Appearance of Hope”), watched a movie (“Aladdin”, because cartoons are for kids!), and still had many hours ahead of me. Up in the sky, and for the sake of a good story I’d like to believe it was in the exact same spot the first POC was conceived, a new one started to form.

Same Ingredients, Different Mix

What if we didn’t have a DB, and stored medical records in plain text, the same as we’ve been doing with our accounting data?

What if Git, faithful and efficient Git, was taking care of syncing and working offline?

What if we’ve used Termux - to have a terminal on Android devices, and thus open the door to running a server locally on each device?

I felt those questions required me to answer them. The result is in this repo and the most important part about it, is the data. All the information we have is stored in YAML files. For example, here’s how we define the information of a mother, and the relation to her children:

id: 000f8e43-d638-49fa-8c9a-3429bb819f21
first_name: Aurelia
last_name: Sherlyn
    - ad1bce42-69c7-4d55-82e1-129fb4b91e87
    - b16df0be-ad66-4901-b7a1-2aa720c9968e
    - 0c9a59e4-dd51-40d6-8978-157fc9b65909

That’s it really. Thank you for reading, bye bye.

No, seriously, there’s some more on how we have some software to help view and manipulate the data (which is what you are probably interested in), but I think that having the data in a human readable format (as opposed to be inside DB tables) is the biggest thing in this POC.

Think about how you build a feature in a traditional website:

  1. The client has a feature idea.
  2. You sketch out some wireframes, the client approves them, and they will be out of the loop until section (6).
  3. You do a technical design.
  4. You add a table in your DB.
  5. You write some front end code.
  6. You deploy to TEST - and there the client sees the outcome for the first time.

But with plain text medical records, the “client” can write for themselves how the result of measurements should look. Any kind of conversation would be around that piece of data. Even if there’s no software on top of it, you know what the measurements are just by reading it.

version: 1
group_meeting: 2020-01-30-morning
# We have a single config file in the root, that has the measurements' units.
height: 125
weight: 12
# Mid-Upper Arm Circumference, known as MUAC.
muac: 30

For me, that’s the biggest win. In fact, maybe that’s the “no vendor lock-in” solution for Health Cloud, we can start building on top!

The Disposable Software

I wanted to build the local server in Haskell, but it seemed that to get it running on Termux it was more complicated than a simple pkg install php. So I decided to go with Symfony, and it was indeed a good decision. Setting everything up worked nicely, with a lot of copy & paste from the docs that are great. I’d say that only the Normalizer package (the equivalent of encoders/ decoders in Elm and Haskell) wasn’t fun to work with. Maybe because I’m so used to the guarantees of Elm and Haskell, working with a non-typed language felt less reliable.

Since PHP has its own web server, all we have to do is spin up the web server, and then use the browser to connect to that local server. The server is not meant for production, but in our case we have only a single client, so it actually works great. We can view data, we can add or change data, and we can even upload images directly from the device.

Adding measurements via Browser

Looking at the Git diff, we’d see the commit that resulted with submitting the form.

version: 1
group_meeting: 2020-01-30-morning
- height: 125
+ height: 130
weight: 12

I also wanted to show how the fact that we have the app in PHP doesn’t mean we are tightly coupled with it. We only care about the data, and that one is language agnostic. So I came up with a tiny Haskell utility, that you can give it a path to the data in another folder, and it will create 100 fake mothers and children, so we could test the app with more data.

Furthermore, since we’ve changed the structure of the stack, and we no longer need to think about a server as an entry point to get or manipulate data, the next thing I did was to create a console command to show a listing of mothers participating in a single group meeting. Below we can see the fake date we’ve created with the Haskell utility.

A list of mothers shown in the terminal

Final Thoughts

I think the biggest accomplishment here is stepping outside of the usual stack structure, and recognizing the unique situation that we are facing. This structure isn’t going to be right for a majority of the cases, but I’d argue that there are a good portion of problems that could be sovled with such a stack. Obviously it’s not a panacea, and it brings different problems; on the other hand, I find it solves some existing ones quite nicely.

In terms of syncing and access control - that’s baked deep inside Git, not to mention that having it as distributed, version controlled, and (sorry for the buzzword) “blockchain”-ed has many merits. In terms of security of running a local PHP server - since it’s running locally, and it’s not open to the outside world, it’s nothing more than a nicer interface to editing files. But obviously, by using Symfony and applying best practices - we make sure we write secure code.

I don’t know what’s next for this POC, as it’s not only for me to decide. But I do hope we’d get a chance to move forward some more with it, to reach a point where we can test it out in the field. If one day a nurse in a tiny room with many crying babies will tell me it improves her day to day work - that would be well worth it.

Jan 01 2020
Jan 01

The Problem

Replacing files uploaded to your Drupal site can be very frustrating. In most cases, when an editor wants to replace a document, they want to keep the exact same filename and filepath and just overwrite the contents of the file. This is important in cases where the file is linked to elsewhere throughout the website or on other websites outside of the editors control. If you use the media module to manage documents on your site, you'll quickly discover that it's not possible to upload a replacement file for a document and keep the same filename.

Why is this? The core file field allows you to remove and upload a replacement file. But when you upload a replacement file with the same filename, Drupal appends a number to the end of it, like _0, _1, etc. This is because the old file is not actually removed from the filesystem immediately. Drupal will mark it as a temporary file and it will be removed during a cron run sometime in the future (* see exception to this below). Drupal won't overwrite that file with the new one, so it appends a number to the end to make it unique. Drupal also does this to support revisions properly. If the file field is attached to an entity that has revisions enabled, then Drupal keeps that old file around because previous revisions may require it.

* Actually, as of Drupal 8.4, old unused files are never deleted unless you have a specific config override set that enables this cleanup.

Existing Contrib Solutions

There is a 4 year old Drupal core issue where the community has tried to resolve this problem. Probably the most popular solution has been to use the Media Entity Download module. It works by creating a special route for each media entity that will directly return the file associated with that entity as a download. So if you had a document media entity with ID 59, editors can create links to /media/59/download and Drupal will serve the file directly from that path. This solves the problem because it hides the actual file system path from visitors. It doesn't matter what that path is or how many numbers Drupal has appended to the end of replacement files, the visitor never sees it and you'll never have broken links.

The main problem I have with Media Entity Download is that it gets Drupal involved in serving up the files which are normally not handled by Drupal at all. After all, the files are just sitting there in the public filesystem. The web server (apache, nginx) typically serves them to visitors and leaves Drupal out of it. With this module, every time a file is requested, Drupal is bootstrapped and a PHP process is tied up until the download completes to the visitor. This is a bit scary if you get a large surge of traffic with many users requesting large downloads.

The New Solution

I just completed work on the Media Entity File Replace module to provide another solution to this problem. This module is intended for site builders that are using the Media module to manage documents on their site. It works by adding a replacement file widget to the media edit form for media types that use a file source (Image, Document, etc). You can control which specific media types it's enabled for by visiting the form display configuration and showing/hiding it. When replacement files are selected and the form is saved, the file is first uploaded to temporary storage and then copied over the existing file. The filepath and filename are kept in tact. Just the contents of the file and the metadata describing the file are updated - which is what editors want most of the time.

Edit form for a document media entity showing the &quot;replace file&quot; form widget

Note that the module still supports the previous behavior of NOT overwriting the original file. Editors just need to uncheck the "Keep original filename" checkbox and the replacement file will be uploaded and the media entity updated to reference it.

This module should fill a functionality gap in document management in Drupal - I hope others find it useful!

Dec 31 2019
Dec 31

In 2018, The Open Source Initiative celebrated its 20th Anniversary, a milestone and a huge success for the global non-profit dedicated to raising awareness and adoption of open source software. Since its inception, the open source movement has gained tremendous momentum in corporate computing. In the recent years, open source has entered the government sphere as well.

One such popular open-source platform is Drupal. Developed by Dries Buytaert in 2001, Drupal became a sensation when it was used to build a network for the Democratic primary campaign of Howard Dean in 2003. Since then, Drupal has come a long way and now more than 100 countries use Drupal for their government websites.

Steve Nichols, CTO of Georgia Technology Authority, which runs more than 65 state government websites, recently talked about how shifting to a Drupal platform helped him manage the government websites in a better way. Earlier, these government websites were running on two different versions of proprietary software - Vignette 6 and Vignette 7. But as the functionalities increased, it became very cumbersome and expensive. Soon they started looking out for other options, and all the evident choices pointed to open source CMS, and the most obvious and the strongest among all the contenders was Drupal.

When they dug a little deeper, they found out that many key federal government sites were being powered by Drupal, and that is when they decided upon to narrow down on the Drupal CMS.

So why exactly do these government websites opt for a Drupal CMS among the plethora of options? Why is the most obvious choice Drupal? Let us know a bit more about what makes Drupal so special!

Drupal's Market Share

In the present world, with more than 150 federal government sites running on Drupal platform, it is kind of obvious that the Drupal CMS has an enormous market share when it comes to the government websites and the public sector in general.

Nasa Website build with drupal cms

The list contains big guns like NASA, Department of Health, Department of Education, Transportation, Defense and Homeland Security. When Drupal platform is being preferred by some of these big government sites, it is not surprising to see that many other private and media companies are inclining towards Drupal CMS for their own websites.

Drupal's Adaptability Features

A few years back, the energy department's website, energy.gov got into a lot of trouble. The website faced low traffic, high bounce rate, and to make it worse, the entire website was built on the basis of an internal office structure which made it quite impossible to navigate. It needed immediate attention, and that is when the organization decided to migrate their website to Drupal.

One of the greatest strengths of the Drupal CMS is its ability to integrate with any other solutions and services. Even a proprietary CMS such as Sharepoint, is likely to coexist with Drupal and other open source platforms. The modular system that a Drupal CMS works on, allows it to adjust easily based on the type of deployments.


While the typical stereotypes about open-source platforms is that they are quite vulnerable to threats, Drupal has a track-record of being one of the most secure open-source CMS. Well-equipped to handle cyberthreats, the Drupal community does a great job to work together and ensure that they eliminate any threats before they affect the users.

Drupal consists of several security modules, making it one of the most reliable platforms amongst several others. Some of these modules include, Login Security, Password Policy, Captcha, Security Kit etc.

Multisites - An Easy Task

Governments tend to have multiple websites, in multiple languages in order to handle various sections of their administration. Irrespective of whether the government has just a couple of websites or few hundreds, the task of building each one of them individually and maintaining them is going to be a tough job.

Drupal CMS makes it easier with its multisite feature, allowing the developers to copy the site's code base and create as many new websites as required. Thus, by leveraging the features and functionalities of an already existing website, the need to build every single site from scratch, is eliminated.

Additionally, Drupal also offers out of the box Content and Entity Translator modules which help content authors to translate pages, individual fields, elements and more. Thus, multiple sites in multiple languages is an easy feat with Drupal CMS.

Say Hello To DeGov

DeGov is the first of its kind Drupal 8 open source distribution that focuses on the needs of government organizations only! DeGov offers a comprehensive set of customized functionalities which are commonly used only for those applications that are necessary for government websites.

With the ability to release federal and state portals, internet sites for ministries, authorities, municipalities and more, DeGov distribution allows web pages and group-specific portals to be created easily, without any hassle.
Learn more about DeGov here.

Dec 31 2019
Dec 31

As APIGEE end of support for Drupal 7 in May 2020 is combined with Drupal 7 end of life in Nov 2021, developer portal are not left with many choices - migrate to Drupal 8 or continue with Apigee’s integrated portals. 

For a custom Drupal 7 developer portal, migrating to Drupal 8 comes as a natural choice. In this blog we will understand why it is so important and what should be on your checklist while migrating to Drupal 8.

Benefits of Migrating Your Developer Portal to Drupal 8 

With continued effort of the Drupal community for its long-term sustainability and more effortless adoption, complete re-architecturing of Drupal 8 has made it different from the previous migrations. There are many ways why Drupal 7 can put your developer portal at risk

Drupal 8 with its performance-enhancing features and modules can turn your developer portal into a speedy and high performing one. Let’s look at what makes Drupal 8 the best version to be on:

  • Drupal 8’s adoption of Symfony framework has made it all the more better. Symfony’s robust, flexible and high-performance framework allows for easy scalability of a website.
  • BigPipe Caching lets you segregate your page into different sections which gets rendered as they become available, enhancing website’s performance and speed.

Source: specbee

  • Drupal 8 is PHP7 ready, which is twice as fast as PHP 5.6. It is capable of enhancing the performance of your developer portal to about 110%, with reduced memory usage.
  • Talking about Drupal 8 themes, they are responsive, making your developer portal look great on almost any device. 
  • Drupal 8 is equipped with CKEditor, which lets you preview your entered content quickly as well as an in-place editor that lets you edit blocks, content, menus, etc. right on the same page.
  • SEO will not be a concern anymore. Drupal 8’s built-in powerful SEO modules, like SEO Checklist, PathAuto, Redirect, and MetaTag can help boost your developer portal’s SEO. 
  • Not to forget about Drupal 8’s out-of-the-box multilingual support, which can help boost language-based views of your developer portal.

Planning Your Migration - Your To Do Checklist

It is important to follow the best approach for the migration process. Having spent too much time on building the right content for your developer portal, you would not want to drop your stats without a proper plan. Content migration becomes a significant decision for your business. 

When you think of developer portal migration to Drupal 8, you need to look into enhancements to the front-end features such as smartDocs API reference documentation, theme editor enhancements, default portal theme and content enhancements, quick start and how developer accounts are managed using the developer identity service.

To ease the process of migration, maximum time should be spent on planning. If properly administered, this will further bring down the number of hours spent on the actual migration. Though content migration is a tedious task, however, strategizing it well in advance will make the developers smoothly execute the process.

One would need one of these two steps to migrate their developer portal to Drupal 8:


  1. For minimal custom implementations on Drupal 7 portal, have Apigee Developer Portal Kickstart ready to migrate Drupal 7’s configuration and content.
  2. Follow custom migration approach for heavy customizations of Drupal 7 portal. For this, Apigee Edge module can help in connecting Drupal 8 Portal to Apigee and use Drupal 8 Migration API to migrate the Drupal 7 implementations to Drupal 8 Portal.


Now, let’s take a look at the pointers to consider before migration:


  • Take Backup

It is always a good practice to take a backup of your entire website before starting with the migration process. This can be done with the help of Backup and Migrate module to create a database dump to save all your Drupal database tables into a single file download, to be later used for restoring at a later stage. 

Enabling Backup and Migrate Module

  1. Navigate to Administer > Modules
  2. Select Backup and Migrate in the Other block
  3. Scroll to the bottom of the page and click Save Configuration

Configuring Backup and Migrate Module

  1. Navigate to Administer > Configuration > System > Backup and Migrate
  2. Download a backup of the default (Drupal) database by clicking Backup now. 

It is recommended to download a backup prior to updating or installing modules.

Backup to Server

Create a private directory to store backups on the server by following the below 3 steps:

  1. Navigate to Administer > Configuration > Media > File System
  2. In the Private file system path field enter sites/default/files/private
  3. Click Save configuration


  • Quick Roundup of Functionality and Content Check

Having a quick yet thorough check of the website for the entire set of features and functionalities of your developer portal will give you an idea of moving on from irrelevant ones. Do check if you want to drop off with any content or content types post analyzing them. This is the time when the need for new content types arises.

Like content types, it is important to figure out which of these fields should be migrated. You should check which of the fields are important in your existing site and which of them are no longer relevant for the new site. Examine the number of users logging in, reviews, ratings, views and other taxonomy terms too.

In this way, you get a chance to completely revamp the architecture of your website.

  • Move Content Securely

Migrating web content is an integral business decision where you must take precautions to avoid any security breach or data theft. Ensuring your database and development infrastructure is up-to-date with the latest upgrade, wiping out all your data including user accounts from database infrastructure and not sending database dump via unsafe channels are few things which need to be kept in mind.

  • Prepare a Backup Plan for Theme Mismatch

Up until Drupal 7, PHPTemplate has been the default Drupal Theme engine. But Drupal 8 uses Twigs (part of Symfony2 framework) to render pages in a highly flexible and secure way. It won’t allow your existing (D7) theme to port directly to D8. Note that no single module can move your existing theme to Drupal 8.

Upon migrating the developer portal, custom CSS styles will be overwritten. So the new default theme needs to be applied along with custom CSS styles manually post migration.

  • Search Modules upon Migration

Drupal 7 core modules and many contributed modules are now available in Drupal 8 core. While most of them are automatically upgraded, a few modules will need manual upgrade as they are not mapped to the same Drupal 8 module or are now segregated into different modules. 

Due to Drupal 8’s revamped architecture, if you’re unable to find a particular contributed module in Drupal 8, you can:

  • Simply archive the module’s data, or
  • Find a similar community module sharing common functionality, or
  • Hire a developer and get a custom module built with the required functionality

However, when it comes to custom modules, you need to port them in Drupal 8. You can hire Drupal developers who can help you with porting the modules.


All you need to do the following things before migrating the developer portal to Drupal 8: 


  1. Prepare the Migration script for Drupal 8 considering the number of developers on Drupal 7 portal, capturing all the custom field data attached to a user entity. Do a parity check on Drupal 7 portal users with the new Drupal 8 portal and list all the extra fields needed to be created on the new portal. Migration script should execute avoiding the API call to Apigee to update a developer.
  2. Sync Developer apps and developer API products with Drupal 8 via Apigee Contributed module. If there are any custom attributes attached to app or API products as dependent, this should be processed via custom migration script.
  3. Migrate Open API spec’s documentation content on developer portal to Drupal 8 Portal via Drupal 8’s Apigee Catalog module or DevPortal Module. Migration script should write the documentation pages to new Drupal 8 portal, based on the option chosen to present doc’s on Drupal 8 Portal.
  4. Migrate any other monetization related configuration (triggering get or post data to Apigee) to Drupal 8 via custom migration script. 
  5. Implement customization done on contributed Apigee Devconnect module newly on Drupal 8 Portal and the data related to this implementation should be processed via migration script.

Wrapping it up

Migrating your developer portal to the latest version is a difficult decision to make. However, it proves to be a brilliant decision once you get a secure, accessible, modern, and responsive website, which suits your needs and stays compatible with updates for years.

For a successful migration that keeps in mind all these steps, you'll need to work with experienced developers. Our team of experts can help you in migrating your developer portal to Drupal 8 to future proof your digital presence, solve your queries around API security and provide a range of services around API designed with a strategy tailored to your success. Contact us today.

Dec 30 2019
Dec 30

Laravel Mix allow to use relatively easily Webpack without having to worry to much about configuration, which can become quite complex. Here is a way to use it in your Drupal theme in order to build your assets from SASS and ES6 (if you want), automatically copy images and fonts, watch the file changes and synchronize your browser while developing.


New theme

Let's define a new theme, for instance called d8t (as Drupal 8 theme) :


name: D8t
: theme
: 'Custom Drupal 8 theme'
: 8.x
base theme
: classy
: Header # Drupal core, do not remove
: Primary menu # Drupal core, do not remove
: Secondary menu # Drupal core, do not remove
: Highlighted # Drupal core, do not remove
: Help # Drupal core, do not remove
: Content # Drupal core, do not remove
: Sidebar first # Drupal core, do not remove
: Sidebar second # Drupal core, do not remove
: Footer # Drupal core, do not remove
: Breadcrumb # Drupal core, do not remove
 - d8t/global

Now, let's define our global library that we just declared. In Laravel's world, we would have written app instead of global, but in Drupal a theme can define various librairies. This library will have the 3 CSS files required by Drupal as well as a JavaScript file :


: {}
: {}
: {}
: {}

So far, nothing new. Let's create the structure of images, SASS and JS source:


Laravel Mix

Now, let's initialize a node modules package, add dependencies and scripts: Here is the final result:


  "name": "d8t",
  "version": "1.0.0",
  "main": "index.js",
  "author": "Guillaume Duveau",
  "license": "MIT",
  "devDependencies": {
    "@fortawesome/fontawesome-free": "^5.12.0",
    "browser-sync": "^2.26.7",
    "browser-sync-webpack-plugin": "^2.0.1",
    "cross-env": "^6.0.3",
    "laravel-mix": "^5.0.0",
    "materialize-css": "^1.0.0",
    "node-sass": "^4.13.0",
    "resolve-url-loader": "^3.1.0",
    "sass-loader": "^8.0.0",
    "vue-template-compiler": "^2.6.10"
  "dependencies": {},
  "scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"

I also added Font Awesome and Materialize CSS, we will see later how to include them. They are of course facultative. All other modules are mandatory. For the scripts, we will mainly use watch when developing and production to generate the final production assets.

At last, let's add this configuration file:


const mix = require('laravel-mix')

    module: {
      rules: [
          test: /\.s[ac]ss$/i,
          use: [
              loader: 'sass-loader',
              options: {
                sassOptions: {
                  includePaths: [
  .js('resources/js/app/app.js', 'public/js/app')
  .sass('resources/sass/app/base.scss', 'public/css/app')
  .sass('resources/sass/app/layout.scss', 'public/css/app')
  .sass('resources/sass/app/components.scss', 'public/css/app')
  .sourceMaps(true, 'source-map')
    proxy: 'localhost:8080'

  • We ask sass-loader to include the node modules for the additional librairies that we use (Font Awesome and Materialize CSS), we will see later how to use them.
  • setPublicPath('public') tells Webpack the directory where the final built files must be written.
  • setResourceRoot('../../') is a tip to use the on-fly URL replacement for images and fonts and their automatic copy.
  • browserSync({ proxy: 'localhost:8080' }) must be adapted to your local development URL.

The configuration could be more complex but it's enough for now.

External SASS / JavaScript librairies

At last here is how we can use the node modules librairies. For starters, let's add Font Awesome:


@import '[email protected]/fontawesome-free/css/all.css';

  • The ~ tells Webpack to search in the node_modules directory.
  • Font Awesome fonts (.eot, .svg, .ttf, .woff, .woff2) are automatically copied in d8t/public/fonts/. If we add images for instance as backgrounds in the SASS, the images files will also be copied.

Now, let's use Materialize CSS. We could just import everything:


@import "~materialize-css/sass/materialize";

Personally, in order to reduce the assets size and to be able to customize Materialize CSS' variables, I prefer importing everything manually, using just what I need:


 * The order of imports must be respected.
 * @see <a href="https://github.com/Dogfalo/materialize/blob/v1-dev/sass/materialize.scss">https://github.com/Dogfalo/materialize/blob/v1-dev/sass/materialize.scss...

// We need colors for variables, later.
@import "~materialize-css/sass/components/color-variables";
@import "~materialize-css/sass/components/color-classes";

// We want to override materialize-css variables.
@import "components/variables";

// This is necessary.
@import "~materialize-css/sass/components/normalize";
@import "~materialize-css/sass/components/global";

// Now we import only what we need.
@import "~materialize-css/sass/components/grid";
// We override this one.
@import "components/navbar";
@import "~materialize-css/sass/components/typography";
@import "~materialize-css/sass/components/buttons";
@import "~materialize-css/sass/components/forms/input-fields";
@import "~materialize-css/sass/components/sidenav";
@import "~materialize-css/sass/components/waves";

  • In components/_variables.scss I copied and modified the library's _variables.scss.

At last, let's write the JavaScript's theme to have the parallax effect on the title block:


import { Parallax } from 'materialize-css'

Drupal.behaviors.gd8t = {

  attach: function (context, settings) {
     * Parallax.

    const parallaxElems = document.querySelectorAll('.parallax')
    const parallaxInstances = M.Parallax.init(parallaxElems)


Feels good to have modern JavaScript in a Drupal theme, right?

Next step for me: trying Webpack Encore. In the end it's anyways the awesome Webpack but that helper is by Symfony, so it kind of makes sense to use it in Drupal too!

Dec 27 2019
Dec 27

I developed this module for my own Drupal shop site because I wanted a block with the page title and a responsive image with a parallax effect. The image can come from a node or a taxonomy field, and can fall back to your selection of default images in contexts where there is no responsive image field available.

gd header drupal 8 module

2.x is for Drupal theme developers, not any more "install and forget". The parallax is not included. I use Materialize CSS's parallax but any lib could be used since you can have the image URL in the Twig template. Of course it's not much, but if that's your use case, it might quicken your dev. I'm open to any suggestions to make it more interesting!

PS: Not so happy about Materialize CSS so far. I'm used to the exceptional MaterialUI for React and it's coming quite short in comparison. Any suggestions for an awesome UI toolkit apart from the usual suspects ?

Dec 26 2019
Dec 26
Drupal Commerce 2.16: cart expiration, exact promotion time & more!

E-commerce opportunities are endless nowadays. More and more business owners decide to hire e-commerce developers and skim the cream off online sales. Today, we will describe the new opportunities offered by Drupal Commerce 2.16.

Read more
Dec 26 2019
Dec 26

Drupal 8 has lot of inbuilt functionality within it, one of the main important features is Configuration Synchronization. It will help us to migrate full setup properly on site deployment. But the main problem is that, According to the Drupal 8 CMI documentation,

The Configuration Manager module in Drupal 8 provides a user interface for importing and exporting configuration changes between a Drupal installation in different environments, such as Development, Staging and Production, so you can make and verify your changes with a comfortable distance from your live environment.

The same idea appears in this article,

Perhaps the most important concept to understand is that the configuration system is designed to optimize the process of moving configuration between instances of the same site. It is not intended to allow exporting the configuration from one site to another. In order to move configuration data, the site and import files must have matching values for UUID in the system.site configuration item. In other words, additional environments should initially be set up as clones of the site. We did not, for instance, hope to facilitate exporting configuration from whitehouse.gov and importing it into harvard.edu.

So Still we hardly depends on the Features module, But we can use the CMI (Configuration management Interface between two different sites with simple hacking solution.

The CMI works with based on the site UUID, If the sites have different UUID then, it won’t work, So changing destination site’s UUID with Source site’s UUID would solve the problem.

Just follow the below steps to use CMI between two different sites,

1. Export Configuration from your source site (Site A)

2. Extract the file, Open the system.site.yml file and get the Source site (Site A) UUID

3. Run the drush command in your destination site (Site B)

drush config-set "system.site" uuid "Your Source Site UUID here"

4. After that, try as usual Import Process in destination site (Site B)

It will accept the Site A configuration in Site B. So we can migrate all datas into our another site.

FYI : I am not sure, It is a effective / Proper way to do it.. If there is any problem with this method please mentioned in the comment.

Dec 26 2019
Dec 26

In such a time, i want to place blocks in sidebar region with the dynamic weight. It means the blocks should render in different position for each page request. I have searched and tried lots of method but unfortunately i can’t find proper method to do that. So i have decided to do that with some hacky way.

Drupal 8 is providing a hook to alter the region template_preprocess_region, it would prepares values to the theme_region. I have planned to use the hook to alter the block's position to be rendered in the region.

Adding the following codes in THEMENAME.theme file would solve the problems,

function themename_preprocess_region(&$variables) {
  if ($variables['region'] == 'sidebar_second') {
    $variables['elements'] = shuffle_assoc($variables['elements']);
    $content = '';
    foreach ($variables['elements'] as $key => $value) {
      if (is_array($variables['elements'][$key])) {
        $content .= \Drupal::service ('renderer')->render($value);
    $variables['content'] = array(
      '#markup' => $content,

function shuffle_assoc($list) {
  if (!is_array($list)) {
    return $list;

  $keys = array_keys($list);
  $random = array();
  foreach ($keys as $key) {
    $random[$key] = $list[$key];
  return $random;

It is working well in my site but i know it is the hacky way, not sure about the proper way to do that. If anyone of you know about this kindly share it in the comments :)

Dec 26 2019
Dec 26

Twig can be extended in many ways; you can add extra tags, filters, tests, operators, global variables, and functions. You can even extend the parser itself with node visitors. In this blog,

I am going to show you how to create new custom twig filters in drupal. For example we are going to create a filter to remove numbers from string, will explain with hello_world module.

Create hello_world folder in modules/custom/ folder with the following files,

1. hello_world.info.yml // It would contains normal module .info.yml file values, Check here for more details

2. hello_world.services.yml // It would contain following lines,

    arguments: ['@renderer']
    class: Drupal\hello_world\TwigExtension\RemoveNumbers
      - { name: twig.extension }

3. src/TwigExtension/RemoveNumbers.php It would contain followings in that,

namespace Drupal\hello_world\TwigExtension;

class RemoveNumbers extends \Twig_Extension {    

   * Generates a list of all Twig filters that this extension defines.
  public function getFilters() {
    return [
      new \Twig_SimpleFilter('removenum', array($this, 'removeNumbers')),

   * Gets a unique identifier for this Twig extension.
  public function getName() {
    return 'hello_world.twig_extension';

   * Replaces all numbers from the string.
  public static function removeNumbers($string) {
    return preg_replace('#[0-9]*#', '', $string);


Enable the hello_world module and clear the cache, then you could use the “ removenum “ filters in your twig file,

{{ twig-value-with-numbers | removenum }}

It would remove the all numbers from the string, enjoy with your custom filters !

Download the hello_world module here

Dec 26 2019
Dec 26

One of the most favourite and  valuable features in drupal is multisite configuration, Drupal 8 provide simple way to create multisite it reduced lots of works. The following steps shows to configure multisite in drupal 8,

  • Should have more than one domain and databases, I am going to use the domain (www.domain1.com, www.domain2.com) and databases (domain1, domain2).
  • Create two folders in drupal-8/sites/ folder with domain1, domain2 name, the folder path would be like this drupal-8/sites/domain1/ and drupal-8/sites/domain2/
  • Create files/ folder in both the folder (drupal-8/sites/domain1/files)
  • Copy the default.settings.php file and paste it into the both folder then rename it as settings.php ( drupal-8/sites/domain1/settings.php, drupal-8/sites/domain1/settings.php)
  • Edit the settings.php file for domain1 to adding the database,
$databases['default']['default'] = array (
  'database' => 'domain1', // Change value to domain1 for www.domain.com and domain2 for www.domain2.com.
  'username' => 'root',
  'password' => 'root',
  'prefix' => '',
  'host' => 'localhost',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
  • Copy the drupal-8/sites/example.sites.php file and paste in on the same location then change the file name to sites.php (drupal-8/sites/sites.php)
  • Add the following line in the bottom of the drupal-8/sites/sites.php file
$sites = array(
 'domain1' => 'domain1.com', // Folder name => Domain name.
 'domain2' => 'domain2.com',

Thats all, both domain would works well with the different db with a single instance.

Dec 26 2019
Dec 26

I needed a way to check the currect user has permission to view the currect/particular page, Searched lot finally got the exact way, going to show the tricks to you in this blog.

Drupal has an api called " drupal_valid_path " , Normally it used to test the url is valid or not. but the trick is that, It also check the user has permission to view the currect/particular page.

It will return TRUE If path is valid and user has permission to view the page, otherwise it will return FALSE,

For example,

$path = current_path();
if (drupal_valid_path($path)) {
  // Your code here.
Dec 26 2019
Dec 26

Most of the times developers don't like the GUI, It makes feel lazy. Drupal has a tool (Drush) to do some management work from command line.

And also the installing the drupal site makes very lazy while doing with browser, The Drush has an option to install the full site with a single command.

The Following command will install the drupal in standard method,

drush site-install standard --account-name=admin --account-pass=[useruser_pass] --db-url=mysql://[db_user]:[db_pass]@localhost/[db_name]
Dec 24 2019
Dec 24

Remember how 2015 was filled with anticipation in the run up to the release of Drupal 8? Well, 2020 is all set to be a repeat of that - the same rush, excitement, innovative work will be happening around Drupal 9. But that’s not the only thing to look forward to for Drupalers in 2020.

From charting new growth paths, to ensuring an enhanced experience and easier adoption of Drupal for beginners, to creating closer integration with other technology frameworks - 2020 has a lot in store for Drupal. And here are the ones we are most excited about.

Drupal 9

Well that’s an obvious one and will definitely be at the top of the list everyone in the Drupal community. 

Drupal 9 is all set to release on 3 June 2020. The big deal with Drupal 9 is that it shouldn’t be a big deal. And that thinking is exactly what is new.

That’s because Drupal 9 is not being built on a new core, but rather within Drupal 8. Here’s how:

  • New features and functionalities will be added to D8 as backward-compatible code. These will start being available to D8 users as experimental features, that can be used and modified. All this while, older D8 features will work without a hitch.
  • Once these new features are stable, their older counterparts will be deprecated. 
  • And finally, 3rd party dependencies, like those with Symfony and Twig, will be updated to offer support for their latest versions.

This collection of new stable features and updated 3rd party dependencies will be what forms Drupal 9.

Drupal-9 - Drupal in 2020We’ve already covered what to expect with Drupal 9 and how to prepare for it and ensure a smooth upgrade experience.

So let’s move on to the other interesting developments slated for 2020.

Drupal 9 Product Tracks

The launch of Drupal 9 is also significant because this is the first time the community has a strategic roadmap for how we want Drupal 9 to grow. Dries’ State of Drupal address in Drupal Amsterdam outlined the four product tracks envisioned for D9:

  • Reduce the cost and effort involved in managing a Drupal 9 website. So the focus will be on introducing new features and functionalities that simplify website support, maintenance and updates - configuration management, automated updates and more.
  • Enhance the beginners’ experience with Drupal by making it simpler to install and get it running out of the box. The first two initiatives in this track are two new themes - Olivero for the frontend and Claro for admins.
  • Work towards ensuring an Open Web that’s accessible, secure, inclusive and interoperable. In the next decade, the Drupal community will collectively ensure that their work - project, websites, solutions - consistently meet these standards
  • Prepare Drupal to be one of the best structured data and content repositories, ready to work seamlessly with a range of devices and delivery channels

2020 will see these product tracks being actively discussed within the community and work starting on several new initiatives.

Drupal 8.8

Drupal 8.8 was released on 4 December 2019 and sites on Drupal 8 can look forward to harnessing great new features and functionalities in 2020. Some of the key upgrades are:

  • Media Library being marked as stable, so content writers and editors can add media content right from the WYSIWYG editor
  • Official support for Composer out-of-the-box, meaning Drupal is simple and easy to install and update with Composer taking care of updating all third-party dependencies
  • The Automatic Update module is available in early alpha stage and has a set of very convenient features. It allows you to configure your site to display PSA messages for required updates or mail them directly to the site admins. You can check if your site is ready for update, with all requisite file permissions, and update your site with just a click, if all prerequisites are in place.
  • The JSON:API Explorer which is an interactive query builder to explore your JSON:API server, strengthening Drupal’s positioning as an effective decoupled solution.

Decoupled Drupal

Yes, Decoupled Drupal has been talked about for quite a few years now, but 2020 and the following decade will be when it becomes extremely commonplace. This will be primarily due to the growth of a complete ecosystem of features and solutions that make it easier to pull off decoupled Drupal solutions. 

While the API-first initiative and the project around building a reusable component library are key to great decoupled Drupal implementations, there are also third-party frameworks and solutions launched in 2019 that will drive decoupled Drupal in 2020:

  • Acquia Content Cloud: A platform that allows content creators to write, edit, and review content independent of the channel where it will be published. The content created here can be pushed to multiple different channels simultaneously or at different times, and will be automatically formatted to best fit the channel. 
  • GatsbyJS: A React-based site generator that offers the perfect JAMstack for a headless Drupal architecture. GatsbyJS drives greater site performance and smooth user experience. It offers a full plugin library to allow almost any kind of content to be pulled in for site creation, via GraphQL. The not-so-steep learning curve and growing community of developers means GatsbyJS will see higher adoption as enterprises try to get more done with Drupal. 

Growing the Drupal Community

This decade is going to be special for us as well as Srijan puts in concerted efforts to grow the Drupal community in India and Asia at large. As a part of this, we plan to:

  • Commit greater number of resources to contributing to Drupal, working across a diverse range on ongoing initiatives and Drupal 9.
  • Drive the Drupal India Association to bring structure and increased participation of different firms and developers in the Indian Drupal community.

Much like the last decade, 2020 and beyond will be marked by exciting new developments in Drupal. But unlike before, these developments will not just be around core Drupal, but rather focussed on how Drupal will interact and operate with other technology solutions and frameworks to solve key enterprise challenges. 

What are you most excited about Drupal's future in 2020?

And if you are wondering how Drupal can help you solve a particular challenge at your organization, just drop us a line and our Drupal experts will be in touch.

Dec 23 2019
Dec 23

Multilingual websites have clear business benefits. Customers who order website creation or improvement want the highest level of their user-friendliness.

Among the vital elements of an easy-to-use multilingual site is a language switcher. Let’s discuss what this switcher is, see beautiful examples of it, and review how it works in Drupal 8 — the best CMS for multilingual websites.

What is the language switcher?

A multi-language switcher is a UI element allowing users to view content in their preferred tongue. Switchers are included in the website’s header, footer, navigation, near the content posts, and more.

They can be in the form of buttons, dropdown menus, lists, flags, etc. The form doesn’t matter — it just needs to be obvious and convenient for users to switch between the versions.

Best Examples of Language Switch Designs


Germany’s version of the famous e-commerce platform offers a handy dropdown with radio buttons. The languages presented on amazon.de are German, Dutch, Polish, Turkish, and Czech.

Language switcher on the amazon.de website


Very user-friendly in its simplicity, the multilingual switcher on the Nokia Corporation’s website offers links to the appropriate versions. Their list is really impressive and contains 26 languages.

Language switcher on the Nokia website


The Drupal 8 website for the Croatian National Tourist Board has a very stylish switcher. Fifteen languages to a person’s choice are presented as country flags with labels. The flags are filled with color when the user hovers over them.

Language switcher on the croatia.hr site

Language switcher in Drupal 8

Since Drupal 8 is multilingual out-of-the-box, it also has a built-in language switcher. It is included in the whole package of its impressive multilingual features (almost a hundred languages supported, interface translations ready, easy setup, RTL, and more).

The switcher can be added anywhere on your website and allows flexible configuration as to the languages included, custom label (e.g. “Choose your language”), etc. These are pretty basic things, the rest is up to developers who can create the switcher’s perfect look and functionality.

How to add a language switcher in Drupal 8

Adding a switcher only becomes available after you enable the multilingual functionality. So we will run through these preparatory steps very briefly — although there are many other interesting options to configure.

1) Enabling the multilingual modules

We need to enable the multilingual modules in Drupal 8 core:

  • Configuration Translation
  • Content Translation
  • Interface Translation
  • Language
Enabling the multilingual modules in Drupal 8

2) Adding a language

Then in the Configuration section, we will see the “Regional and language” subsection. We click on “Languages” to add new ones to the site. It will offer a dropdown of almost a hundred languages as well as the “custom language” option.

Adding a language to a Drupal 8 siteAdding a language to a Drupal 8 site

3) Creating a language selector for editors

The language selector is a kind of language switcher but for content editors. To get it, we need to choose which content types and their particular fields will be translatable in “Regional and language” — “Content language and translation.”

Making content translatable in Drupal 8

This will let editors select the language to write in and use the “Translate” tab.

Option to choose language during content creation on a multilingual Drupal 8 siteOption to translate content on a multilingual Drupal 8 site

4) Creating a language switcher for users

Finally, we can get a content switcher for website users so they can switch between the content versions. Drupal provides a “Language switcher” block. Like all other blocks, it is found in Structure — Block layout.

We need to click on the region in which we want to place the switcher. Then we find the language switcher block on the list of available blocks, click “Place block” again, and save blocks.

Finding the language switcher block in multilingual Drupal 8

While placing the block (or at any time) we can choose a custom title for it (for example, “Select language”) or choose to display no title at all. We can also select the languages to show in the switcher, which by default will mean all.

Configuring language switcher on a multilingual Drupal 8 site

We put in the “Sidebar first” region:

Basic language switcher in sidebar first region of a Drupal 8 site

Or maybe we could move it to the header by clicking on the pencil near the block and opening the configuration settings:

Basic language switcher in header of a Drupal 8 site

This and many other options are provided by Drupal out-of-the-box. But, of course, your language switcher will look much more stylish after our developers apply their CSS, JavaScript, and other front-end skills.

Video about creating a language switcher to a Drupal 8 site

We have created a brief video with the above described process. Enjoy!

[embedded content]

Create a language switcher or a multilingual site!

You can always entrust our Drupal support experts with:

  • creating a language switcher for your site according to your vision
  • building you a feature-rich multilingual site from scratch in any industry

Let’s do it — your multilingual audience is waiting!

Dec 23 2019
Dec 23

From time to time conversations come up among developers, and other fellow travelers, about being self-taught vs getting formal training. Over time I’ve come to realize that the further and further you get into your career, the less the distinction means anything; eventually we are all mostly self-taught.

I’ve written before about the value of my liberal arts education and I stand by my assertion that what I learned in that setting was, and is, valuable to my life and work. But just because something was useful to life does not mean it was the only way to acquire the skills. It’s a good way for many people, but far from the only way.

For anyone in a technical field, and most professional fields really, to succeed over time you need to learn new tools, skills, and techniques. The tools I knew when I graduated college are all largely outmoded or significantly upgraded, and I’ve had to learn a variety of technologies that didn’t exist in 2001.

Within the Drupal community lots of people talk about being self-taught, sometimes with pride sometimes with embarrassment, but in truth very few people were formally trained on the platform. Lots of very successful developers in the Drupal community (and beyond) have degrees in fields like religion and art history, not computer science, and have taught themselves how to do awesome things. In fact, I’ll argue that just about every Drupaler taught themselves most of what they know about Drupal. How they did that can vary widely, but we are a community with few formal training programs and lots of people who stumbled into Drupal trying to solve a non-technical problem. Even advanced workshops at conferences dig deep into one small area and expect you to generalize that knowledge to your projects, which I count as self-teaching. For example, I had a friend ask the other day about how to control the PDO connection settings in Drupal 7 — which I didn’t know how to do, but knew they were similar to Drupal 8 — so I sent him my Drupal 8 instructions and he figured it out how from there. He’s now taught himself how to do what he needed for that project and in the process generalized the approach for whatever he may need next time.

So then it is important for all of us to find, and hopefully share, techniques for self-teaching — even for those who have some kind of formal training. Here are my suggestions for people who are starting out and haven’t yet found the pattern that works for them:

  1. Assume you first solution is wrong. Most of us have, or will, stumble our way through a project where we don’t really know what we’re doing without a lot of support. We usually learn a great deal in the process, and launching those projects can feel pretty good cause you’ve succeeded at something hard. It is easy to get into the habit of assuming the solutions from that project were correct because they worked. In truth those projects are really rough around the edges, and just because we got it to work does not mean the solution was good. Assuming the first solution is good enough forever is how you become an expert beginner which then takes a lot of effort to undo. Once you have a working solution, step back and see if you can think of a better one, or see if you now can guess better search terms to see if someone else wrote up a different solution to the same problem. Admit your work could be better and try to improve it.
  2. Learn a few more programming languages. Most people who are self-taught from the start, and even some who have a BA/BS in Computer Science, only know 2 or 3 programming languages (PHP, JS, and CSS+HTML are often the only languages new people learn at first). One of the courses I took by chance in college forced me to learn 8 in 16 weeks. It was grueling, miserable, and darned useful. I can still learn a new language in just a couple weeks and rarely do I hit a language construct I don’t recognize. You don’t need to go that far. When I first started out a mentor told me you should learn a new language every year, and for several I did. Some of those, not the languages I learned in college, are the ones I use most day-to-day. All told I’ve spent time writing code in more than twenty different languages. That many isn’t terribly useful but the more languages you learn, the more you learn to understand the elements of your primary language.
  3. Learn basic algorithms and to measure complexity. The kind of thinking that goes into formal algorithms will help you be a better developer overall; badly thought through processes is the place I tend to see the largest gaps between developers with and without formal training. Any college-level CS program will put you through an algorithms course that teaches a variety of specific algorithms and force you to understand their structures. If you didn’t go through one of those programs, this is probably the course that will help you the most. On the one hand most of us rarely rewrite these algorithms as on modern platforms some library or another will provide a better version than we are likely to craft for our project. But learning what they are, when they are used, and how to understand their performance is useful for any project that involves lots of data or processing. MIT has a version of their algorithms course from 2011 online, or find one through another provider. Even if you just watch the lectures (really watching, not just vaguely have them on while cooking and cleaning), you can learn a great deal of useful information. I learned a lot watching those lectures as it refreshed and updated my understanding of the topics.
  4. Find and learn from mentors. Notice I used a plural there; you should try to find a few people willing to help you learn your profession, and more generally help you learn to advance in your field. Most of us benefit from learning from the experiences of multiple people, and who we need to learn from changes over time. I had the great experience of having a few wonderful mentors when I was first starting out, and much of the advice they gave me still serves me well. Some of it contradicted, and resolving those contradictions forced me to learn to do things my own way and find my own solutions.
  5. Learn other platforms. This is both a protection against future shifts in the market, and also a way to see how things work from outside your current professional bubble. Drupal developers can learn a lot from writing a WordPress plugin, or better yet an add-on for a platform in another language (think about Plone, Gatsby, or Hugo). Or try to learn to work with a platform like Salesforce or AWS. Other platforms have different communities, different learning styles, and different patterns. Like understanding additional languages, different platforms help you broaden your understanding and provide insights you can bring back to your main work.
  6. Learn to give and take criticism. Part of learning is getting feedback on your work, and part of being on a team is sharing feedback with others. If you took art or music classes in high school or college you probably learned some of the basic lessons you need here, but if you didn’t, consider taking one now at your local community college or art center. The arts are wonderful for getting experience with criticism. For all art is often open to interpretation, it also requires specific skills. If you play off-key, it sounds wrong. If your sculpture collapses under its own weight, the project failed. If your picture’s subject is out of focus, you need to re-shoot it. Sure there are brilliant artists who can violate all the rules, but if you have never experienced an art critique you are not one of those artists. The experience of getting direct, blunt, and honest feedback will help you understand its value and how to give that feedback yourself.
  7. Share what you think you know. We learn a great deal with we teach others. Both because it forces us to refine our thinking and understanding so we can explain it, and because learners ask questions we cannot answer off the top of our heads. This can be user group or conference presentations, internal trainings for your team, mentoring junior developers, writing a blog, or anything else that gets your from learning to teaching. It’s okay if you’re not 100% right, that’s part of how we learn. A few years ago I was doing a joint project with a junior developer who asked me a lot of questions, and pushed hard when she thought I was making mistakes. When she asked why I was selecting a solution or setting a pattern, she was never satisfied with “because that’s the best way to do it.” She wanted me to explain why that was the best way. If I couldn’t walk her through it right away, I went back and hunted for reference material to explain it or if that failed I tested her counter ideas against my plans to see if I was missing something. While I was usually right, not always and we did make changes based on her feedback. More importantly it forced me to show my work in fine detail which was a good exercise for me and gave her insights to help her do better work.
  8. Find your own patterns. At the start I said this list was for people who didn’t have their own patterns yet. In the long-run of your career you need to figure out what you need to know to get to where you want to go next. Eventually you will need to find a pattern that works for you and the life you are living. No one can tell you what that is, nor how to learn it all yourself. Experiment with learning styles, areas of work, roles, and types of projects as much as you are able until you feel your way to the right solutions for you.
Dec 23 2019
Dec 23

Making multilingual sites is hard. I’ve been using Drupal since version 5 and I can say a few things about the evolution of Drupal multilingual capabilities:

  • First, Drupal 8 is – in my opinion – the first version of Drupal where someone could say that multilingual works, pretty much out of the box.
  • Second, the documentation about how to deal with different scenarios is quite good.
  • And third, from a user experience perspective, translating the user interface of a site is really hard.

In this post we will talk about the third point and what we did to manage that complexity.

Our Current Scenario

We are building a really complex site, and the main challenges we faced regarding multilingual are:

  • The site is a multisite architecture, one database using Organic Groups.
  • Each group represents a country, and each country needs its site in one or more languages.
  • We have several variations of the same language depending on the region this language is spoken in.
  • We don’t want to let content editors translate the site directly from the UI.
  • We don’t speak all the languages the site is in.

The last item is quite relevant, when you don’t speak a language, you cannot even be sure if the string you are copying into a textbox says what it should.

The First Attempt

We started with a translation matrix to store all the translations. A simple Google drive spreadsheet to track each string translation in each language.

Each column uses the language code as a header.

Using a tool to convert Spreadsheets into po files we get each translation file fr.po, es.po, pt.po.

We used wichert/po-xls to achieve this with good results.

Not So Fast

This initial, somewhat naive, approach had a few problems.

  • Drupal string translations are case sensitive. This means that if you made a typo and wrote Photo instead of photo the translation will fail.
  • Some strings are the result of a calculation. For example. Downloads: 3 is actually managed by Drupal as Downloads: @count.

But the more complex item is that Drupal 8 has two ways to translate strings. The first one is inherited from Drupal 7. The one that makes use of the well known t function for example t('Contact us.').

The other one is a new way that allows site builders to translate configuration entities.

The two scenarios that allow translation of a Drupal site.

Translating Configuration Entities is Really Hard

To translate configuration entities, you need to identify which configuration needs translation, and find the exact part relevant to you. For complex configuration entities like views, this could be quite hard to understand.

Even for an experienced site admin this can be hard to understand.

Another problem that we had to solve was the vast amount of configuration alternatives you have when dealing with a medium-size Drupal site.

Each category has a lot of items to translate.

It was clear to us that in order to translate all those items we needed to find another way.

More problems&mldr; Identifying Which Strings to Translate is Hard

One thing to consider when dealing with Drupal translations is that it’s not easy to identify if a string is displayed somewhere in the frontend or if it is only a backend string.

Translating the entire codebase may not be a viable option if you want to keep a short list of translations reviewed by a group of people. In our case, it was important to make sure that translations are accurate, and that translators do not feel overwhelmed.

We don’t have a great solution to this problem yet. One of the strategies we used was to search for all the strings in twig templates and custom modules code using a grep search.

egrep -hro "[\>, ]t\('.*'\)" . | cut -c 5-   # Get strings inside ->t(...) and t(...)
egrep -hro "{{ '.*'\|\t" .                   # Get twig strings '....'|t
egrep -hro " trans .*" .                     # Get twig strings inside trans

However, as we figured out later by reading the documentation, twig strings cannot be used as a source for translations. Internally, Drupal maps those strings back to the regular use of t('strings').

This means that strings like:

{% trans >}}Copyright {{ year }}{% endtrans >}}

Are actually converted to

t('Copyright @year')

And that last string is the one you should use as source of the translation.

At the end, we cleaned up the spreadsheet list using visual inspect, and so far it has been working fine.

How We Solved the Problems?

To recap the problems we had:

  • We did not want to translate all the available strings.
  • We did not know all the languages, therefore copy and pasting was a risk.
  • Translators were expecting to have a reduced number of strings to translate.
  • Configuration translations are quite complex to track.

As we mentioned before using the xls-to-po tool, we were able to obtain the PO files to translate one part of the strings that we needed to translate.

We also used drush_language to automate the process.

drush language-import --langcode=fr path/to/po_files/fr.po

This little snippet iterates over all of the po files in the po_files directory and imports the language using the drush command mentioned above.

find po_files -type f -name *.po | xargs basename --suffix=.po | \
xargs [email protected] drush language-import --langcode=@ @.po

The xls spreadsheet has in the first column the Message Id, and the language codes of the system

By using conditional cell colors, we can quickly identify which translations are pending.

Solving the Configuration Translation Problem

The second part of our problem was a bit more tricky to fix.

We used a custom script to get all the config entity strings that were relevant to us.

Here is a simplified version of the script.

$prefix = 'views.view.custom_view';
$key = 'display.default.display_options.exposed_form.options.reset_button_label';

$configFactory = \Drupal::service('config.factory');
$list = $configFactory->listAll($prefix);

$rows = [];

foreach ($list as $config_name) {
  $columns = [];
  // Add the unique identifier for this field.
  $columns[] = $config_name . ':' . $key;

  // Get the untranslated value from the config.
  $base_config = $configFactory->getEditable($name);
  $columns[] = $base_config->get($key);

  $rows[] = $columns;

If you wonder how to get the $prefix and $key, they are obtained by inspecting the name of the field we want to translate in the Configuration Translation UI.

You need to inspect the HTML of the page, see the name attribute.

We print the result of the script to obtain a new CSV file that looks like this

The first column is a unique id that combines the prefix and the key.

Then, we copy and paste this CSV file as a new tab in the general translation matrix, and complete the header with the rest of the languages translations.

Finally we use a spreadsheet formula to find the translation we want for the languages we are interested in.


This will search for a match in the Strings matrix, and provide a translation.

Spreadsheet magic.

Final step: Importing the Configuration Strings Translation Back to Drupal

Once we have all the translations we need. We export the CSV file again and use this other script (simplified version) to do the inverse process:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\CsvEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

$filename = 'path/to/config_translations.csv';

$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
$configFactory = \Drupal::service('config.factory');
$languageManager = \Drupal::service('language_manager');

$serializer->encode($data, 'csv');
$data = $serializer->decode(file_get_contents($filename), 'csv');

foreach ($data as $row) {
  $name_key = array_values($row)[0];
  list($name, $key) = explode(':', $name_key);

  // The languages we care start after the second column.
  $languages = array_filter(array_slice($row, 2));

  foreach ($languages as $langcode => $translation) {
    $config_translation = $languageManager
                            ->getLanguageConfigOverride($langcode, $name);
    $saved_config = $config_translation->get();
    $config_translation->set($key, $translation);

Some Other Interesting Problems We Had

Before finishing the article, we would like to share something interesting regarding translations with contexts. As you may know, context allows you to have variations of the same translation depending on, well&mldr; context.

In our case, we needed context to display different variations of a French translation. In particular, this is the string in English that we needed to translate to French:

Our organization in {Group Name}

In France, this translates into Notre organisation en France. But if you want to say the same for Canada, due to French grammatical rules you need to say Notre organisation au Canada (note the change en for au).

We decided to create a context variation for this particular string using context with twig templating.

{% trans with {'context': group_iso2_code} >}}
Our organization in { group_name }
{% endtrans >}}

This worked ok-ish, until we realized that this affected all the other languages. So we need to specify the same translation for each group even if the language was not French

This is not what we want...

After some research we found the translation_fallback module but unfortunately it was a Drupal 7 solution.

Long story short, we ended up with this solution.

{% if group_uses_language_context >}}
  {% trans with {'context': country_iso2_code} >}}
    Our organization in { group_name }
  {% endtrans >}}
{% else >}}
  {% trans >}}Our organization in { group_name }{% endtrans >}}
{% endif >}}

Which basically provides two versions of the same string. But if the group needs some special treatment, we have the change to override it. Lucky for us, xls-to-po has support for strings with context. This is how we structured the translations for strings that require context:

CA, in this case, is the ISO code for Canada


For us, this is still a work in progress. We will have to manage around 20 or more languages at some point in the project. By that point, having everything in a single spreadsheet may not be maintainable anymore. There are other tools that could help us to organize source strings. But so far a shared Google Sheet worked.

We still use configuration management to sync the strings in production. The snippets provided in this post are run against a backup database so we can translate all the entities with more confidence. Once we ran the script we use drush config:export to save all the translations to the filesystem.

Dec 22 2019
Dec 22

One of OSTraining’s members wants to have a carousel slider in her site. She wants the carousel to show 3 image slides and some text below them, and the carousel to move only one position at a time when you click the “Next” button. 

This is possible to achieve, thanks to the Drupal Slick module which has several options and settings to customize this interaction with a couple of clicks. 

Keep reading in order to learn how to use this module!

191216 slick

Step #1. Install the Module

  • In order to build the carousel, we have to install two modules and their corresponding third-party libraries.

    • Open the Terminal application of your system 
    • Type: composer require drupal/slick 

191216 slick 000 

 Now, it is time to add the JS library for the slick module. You can use the file manager of your operating system or the terminal for the next operation: 

  • Type the following commands in order:

mkdir libraries 

This creates a directory called libraries in the root folder of your Drupal installation.

cd libraries

To access the directory.

wget https://github.com/kenwheeler/slick/archive/1.8.0.tar.gz

This command downloads the slick library from its GitHub repository in a compressed tar.gz file.

tar xzvf 1.8.0.tar.gz

To uncompress the tar.gz file.

191216 slick 001

mv slick-1.8.0/ slick

To change the name of the uncompressed folder.

cd ..

To go back to the root folder.

composer require “drupal/blazy:1.0-rc4”

This will download the specific version of Blazy, required for Slick to work properly, since the stable version of Slick works only with version 1.0 of Blazy.

191216 slick 003

mv blazy-master/ blazy

To change the name of the uncompressed folder.

rm *.zip && rm *.tar.gz

To delete both compressed files. 

191216 slick 004

You should at the end have the following folder structure:

191216 slick 005

The files slick.min.js and blazy.min.js are inside the slick and blazy folders respectively. 

cd ..

To go back to the root folder.

composer require drupal/slick_views

This will download the Slick Views module, which integrates Drupal Views with Slick.

  • Click Extend.
  • Enable the following modules:
    • Blazy
    • Blazy UI
    • Slick
    • Slick UI
    • Slick Views
  • Click Install.

191216 slick 007

We are now set and can proceed with configuring the Slick Optionset.

Step #2. The Slick Optionset

  • Click Configuration > Slick.

191216 slick 008

The first configuration screen shows the list of available Slick optionsets. Imagine optionsets as cassettes or CDs, which you can exchange in your player to get the right song (in this case the right carousel). The bottom half of the screen shows all different skins, that can be applied to the carousel. This functionality will be covered in a future tutorial. The UI tab has two options regarding the style of these skins.

  • Click Add slick optionset.

191216 slick 009

You will be presented with a lot of options, most of them are self-explanatory. Let’s take a look at some of them.

  • Give the optionset a proper label.
  • Replace the Previous and Next arrows text with the symbols “<” (less than) and “>” (greater than), so that the code reads like this:

<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0"> < </button>

  • Increase the number of Slides to show to 3.
  • Increase the speed to 900ms (making the slide effect slower).
  • Change the CSS override to swing.
  • Click Save.

191216 slick 010

Step #3. - Create the Carousel View

  • Click Structure > Views > Add view.
  • Enter a proper name for the view.
  • Show Content of type Article.
  • Select Create a block.
  • Choose Slick Carousel of fields.
  • Set the number of Items per block to 0.
  • Click Save and edit.

191216 slick 011

  • Click Add in the Fields section.
  • Enter Body in the search box.
  • Check the Body option.
  • Enter Image in the search box.
  • Check the Image option.
  • Click Add and configure fields. 

191216 slick 015

  • Change the Formatter option to Trimmed.
  • Set the number of characters to 150 as the Trimmed limit.
  • Click Apply and continue.

191216 slick 013

  • Change the Image style to Medium.
  • Link the image to the Content.
  • Click Apply.

191216 slick 014

  • Rearrange the fields in this order: 
    • Image
    • Title
    • Body
  • Click the Slick Carousel Settings.
  • Check Vanilla Slick.
  • Select the optionset you created before.
  • Click Apply.

191216 slick 015

  • Save the view

Step #4. - Place the Block

  • Click Structure > Block layout.
  • Scroll down to the Content section.
  • Click Place block.
  • Search for the view you have just created. 
  • Click Place block.

191216 slick 016

  • Drag the block behind the Main page content block.
  • Scroll down and click Save blocks.

Now you can take a look at one of your articles and test the carousel. Congratulations!

The rest is CSS styling. To improve the layout, for example with CSS Grid, take a look at this article.

Thanks for reading!

About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.
Dec 20 2019
Dec 20

If you're currently running a Drupal 8 site and are interested in upgrading to Drupal 9 when it is released in the summer of 2020, the first step is to update to the recently-released Drupal 8.8. Drupal 8.8 contains both the deprecated APIs and the new APIs that will become standard in Drupal 9, so once your site is on 8.8, you can begin to review your contrib modules and update your custom code to move from deprecated APIs to the state of the art. No new features will be added in the 9.0 release, which means that 8.8 has feature parity to streamline the upgrade path between 8.x and 9.x.

The update to 8.8 is more involved than previous Drupal 8 point releases because 8.8 renames some configuration variables and changes the core drupal packages and dependency structure in composer.json, which means that updates need to be made to both settings.php and composer.json.

At Palantir, our team maintains many Drupal 8 sites in both active development and support, and we've documented some important tips that are important to keep in mind when updating your site to 8.8. We also want to give a shout-out to the folks at PreviousNext for their post on what they learned when updating to the 8.8 beta release.

Update process overview

  1. Contrib module conflicts: If your site is using the contrib modules Pathauto, Workspace, or Coder, update those first.
  2. Update settings.php: Change the temp and config sync directory variables settings.php
  3. Update composer.json: Manually update your composer.json
  4. Run the Drupal database updates
  5. Export changed config

Contrib module conflicts


We use the Pathauto module on all of the sites we build, and Pathauto needs some handholding in this update process. If you don't update Pathauto while you're still on Drupal core 8.7, you could lose your path alias data!

  1. While your site is still running Drupal 8.7, update Pathauto to the latest release (8.x-1.6):
    composer require drupal/pathauto:^1.6
  2. Deploy the updated code
  3. Run the database updates:
    drush updatedb
  4. Begin your Drupal 8.8 update

Workspace isn't common on our sites, so running into an issue with it usually means doing some research. The contrib Workspace module has been moved into core, and renamed "Workspaces"; installing both modules on the same site creates code-level conflicts. Additionally, the Drupal 8.8 release introduces an incompatibility between core Content Moderation module and the contrib Workspace module.

As of December 2019, there is no ready-made upgrade path from the contrib module to the core module; the recommendation is to uninstall the contrib module -- which will delete all workspace content that is not yet live -- and then install core's module (documentation).


If you're using Coder to do automated code review against the Drupal coding standards, you may need to update. Drupal 8.8 requires a minimum of version 8.3.2.

  1. Check your coder version:
    composer show drupal/coder
  2. You'll see the package information with the version -- in this case, 8.2.10:
    [ 3:15P ~/repos/example] (develop) $ composer show drupal/coder
    name : drupal/coder
    descrip. : Coder is a library to review Drupal code.
    keywords : code review, phpcs, standards
    versions : * 8.2.10
    type : library
  3. Update the package:
    composer require drupal/coder:^8.3.2

Updating settings.php

First, find your settings.php file; this will be within your Drupal site at sites/default/settings.php, or may be an include file named like sites/default/settings.*.php.

Config sync directory

The config sync directory is where Drupal stores your exported configuration YAML files. Before Drupal 8.8, you could configure multiple directories for exporting config; now there's only one, and the variable name has changed.

Check settings.php files for the $config_directories variable:

$config_directories = [];
$config_directories[CONFIG_SYNC_DIRECTORY] = '../config/sites/default';

Replace this (using your original path) with:

$settings['config_sync_directory'] = '../config/sites/default';
More information
Temporary (temp) directory

The temp directory is usually specific to your host or the environment where your Drupal site is running, so you may need to set this differently for production vs. local development.

Check your settings.php files for the temp directory configuration:

$config['system.file']['path']['temporary'] = $_ENV['TEMP'];

Replace this (using your environment-specific path) with:

$settings['file_temp_path'] = $_ENV['TEMP'];
More information

Update composer.json

Drupal 8.8 introduced scaffolding in core and separated dev dependencies into a separate package. The scaffolding manages core files like index.php and .htaccess, which are required for Drupal to run but don't live within the core/ directory. You might already be using drupal-composer/drupal-scaffold for this purpose, which will need to be replaced.

Because these changes involve replacing existing packages and updating composer plugin configuration, they need to be manually applied to your composer.json.

Use the drupal/core-composer-scaffold package

Edit your composer.json and to the require section, add:

        "drupal/core-composer-scaffold": "^8.8",

This should replace the drupal-composer/drupal-scaffold package, if you were using it.

This is a composer plugin, and needs to be configured in the extra section of your composer.json. Add or update the drupal-scaffold configuration:

        "drupal-scaffold": {
"locations": {
"web-root": "web/"
"allowed-packages": [
"file-mapping": {
"[web-root]/.htaccess": {
"mode": "replace",
"path": "web/core/assets/scaffold/files/htaccess",
"overwrite": false

Double check the web-root location and change web/ if necessary -- for example, if you're hosting on Acquia, set this to docroot/.

Also check the file-mapping section and make sure the value for path is correct. This file-mapping configuration will prevent your .htaccess file from being overwritten if you've customized it, but can be left out otherwise.

More information

This will install your core Drupal requirements.

Edit your composer.json and in the require section, replace the drupal/core package with:

        "drupal/core-recommended": "^8.8",
Add the new drupal/core-dev package to your Composer dev requirements

This will install optional, development-specific core dependencies so that you can run things like automated testing.

Edit your composer.json and to the dev section, add:

        "drupal/core-dev": "^8.8",

This should replace the webflo/drupal-core-require-dev package, if you were using it.

More information
Finally, run Composer

Now that you've updated your composer.json file, run Composer to update your packages. In order to update only the packages you've changed (and not every package all at once), run:

composer update --lock
Troubleshooting Composer

After making these changes to your composer.json, you may see the following error when you run composer install or composer update:

Installation failed, reverting ./composer.json to its original content.
Could not delete /srv/users/serverpilot/apps/sandbox/drupal/web/sites/default/default.services.yml:

This happens because the scaffolder (which runs on composer install and update) is trying to write files to your sites/default/ directory, but doesn't have the permissions. You can resolve this with:

chmod +w web/sites/default

See Troubleshooting: Permission issues prevent running Composer for more details.

Running the update scripts

Finally, you'll need to do the normal Drupal update process: run the database exports, and export any config changes:

drush updatedb
drush config:export
Troubleshooting the database updates

If you're testing the database updates multiple times on the same environment, you may run into this error:

[error] Update failed: system_update_8804

This happens because system_update_8804 creates new database tables. If you are using drush sql-sync to test and re-test the update against a copy of the production database, you'll need to clear your local database with drush sql-drop first, in order to delete tables created by a previous run.

What next?

Once your site has been updated to Drupal 8.8, you'll be in good shape for the upgrade to Drupal 9, which is currently anticipated on or around June 3, 2020. Between now and then, we'll be working alongside other Drupal contributors to make sure that key contributed modules are ready for Drupal 9, as well helping our clients make sure that custom code and modules on their sites are free of deprecated APIs. Stay tuned for more!

Dec 19 2019
Dec 19

Holiday gift: Automatic Updates

As of today, the Automatic Updates contributed module for Drupal 7 and Drupal 8 has had its first stable release! This represents the completion of Phase 1 of the Automatic Updates Initiative, and the culmination of more than 18 months of work.


Please note: this phase 1 work provides automatic update coverage for many scenarios, but not for every Drupal use case.

With this phase 1 release you can:

  • See Drupal PSAs that the security team determines are highly critical directly in your administrative interface.
  • Run readiness checks to determine if your site is eligible for automatic updates (is the filesystem writable, no custom edits to updated files, etc).
  • Automatically update Drupal 7 and Drupal 8 sites
    • Current limitations
      • Updates Drupal core, but not contributed projects
      • Right now, can update only if the sites are not built or maintained with Composer 
      • Database updates are supported in Drupal 8, but not supported in Drupal 7 (if there are DB updates, an automatic update in D7 will be rolled back)

The Automatic Updates module will not be an official solution until the second phase is complete and the feature becomes part of Drupal Core. However, we believe that even as a contributed module Automatic Updates provides a significant improvement in maintenance and cost of ownership for a broad base of existing Drupal 7 and 8 sites, particularly those managed by small, independent site owners.


The second phase of this initiative will focus on solving the remaining requirements and getting automatic updates ready for inclusion in Drupal core. The outstanding requirements include:

  • Support for Composer-built sites
  • Support for contributed modules and themes
  • Support for a more robust roll-back process
  • More robust support for database updates

We are currently seeking sponsors for the second phase of this initiative, so please reach out to us at the Drupal Association if you'd like to support this work!

Many thanks!

Thank you to these individuals:

And to these organizations:

Dec 19 2019
Dec 19

Forums or message boards are an implementation of an early way of communicating, generating content and interacting through the internet, by creating threaded discussion boards, called bulletin boards. Despite the fact of being one of the most traditional ways to exchange information over the web, forums are still a very effective way to build a community around your website or web application. 

Drupal 8 offers by default the Forum module in Core. This module allows you to implement a basic forum on your Drupal site or web application. 

Keep reading, in order to learn how to use this module! 

Step #1. Enable the Module

  • Click Extend
  • Scroll down until you find the forum module, or use the search box to filter it out
  • Enable the module
  • Click Install

 191126 drupal forum  

No further modules are required.

 Step #2. - The Forum Settings

The Forum module has created a new content type called Forums.

  • Click Structure > Forums 

191126 drupal forum 001

The concepts to configure the module are the following: 

  • Topics are Drupal nodes posted into a forum. The comments to these nodes are the threaded replies to the forum topic.
  • Topics have to be always inside a forum. It is not possible to place a topic inside a container. 
  • Forums can contain unlimited forums and can even contain other forums, called child forums.
  • Containers are created to hold (wrap) a group of forums. It is possible to wrap a container around many forums, the same way a forum can hold one or multiple containers holding at the same time multiple forums.

As you can see, with the right planning, it is possible to create complex nested structures to categorize the content of users. 

  • Click Edit to configure the General discussion forum
  • Scroll down and click Delete

191126 drupal forum 002

  • Click Add container

 191126 drupal forum 003

If your site was about pets, then it is very probable that you would have a section for dogs and a section for cats, for example. To organize the forum content, it makes sense to create a global container for each one of these pets. 

  • Enter the required information
  • Click Save

191126 drupal forum 004

  • Click Add forum
  • Create as many forums as needed, according to your own categorization

These forums will be placed at the first level of the container

 191126 drupal forum 005 

Besides these forums on the first container level, we are going to create additional child forums, to preserve the information structure and be able to do comparisons between them later on.

191126 drupal forum 006

The final structure should look like the image below.

191126 drupal forum 007

Step #3. - Adding Topics to the Forum

  • Click on the root link, that is the link of the main container (in this case Dogs)

The system will send you to a page with the following URL pattern:


Notice that the column Topics on the table shows no results. That is because we have not added a topic to any of the forums. 

  • Click on the Food link below the parent forum Herding group

191126 drupal forum 008

  • Click Add new forum topic

191126 drupal forum 009

Check that you are placing the topic in the right place. 

  • Click Save

191126 drupal forum 010 

Each one of the comments to this new node will increase the count on the forums table.

191126 drupal forum 011

191126 drupal forum 012

If you click on the forum link, you will see a table with all the topic details of that particular forum. 

191126 drupal forum 013

I hope you liked this tutorial. Thanks for reading!

About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.
Dec 19 2019
Dec 19

by Elliot Christenson on December 19, 2019 - 12:04am

In November 2021, Drupal 7 will be End-of-Life (EOL). To continue getting security updates, you'll need to get Extended Support (D7ES). But if you sign up before EOL, you'll get automatic security updates until then AND a better price when EOL comes.

In case you haven't heard, the Drupal project is discontinuing "official support" for Drupal 7!

Drupal 7 will continue to be supported a bit longer than in the past - until November 2021, but you'll need to update to Drupal 8 (or more likely 9) eventually!

Or do you? What if the expense or timeframe won't work for your organization.

We've previously mentioned our intention to offer Drupal 7 Extended Support, but what we'd like to clarify now is an important piece: the PRICE.

Our Drupal 6 pricing costs a bit more than our current Drupal 7 pricing. We want to offer special pricing for our existing clients. For as little as $99 per month, they can keep your Drupal 7 website running for years to come!

We'd like to offer that same deal to anyone else that wants to join us before the coming wave of 2020 and 2021. We aren't sure how long this special pricing will last, so please contact us now to begin discussing how we can help!

A great way to get started is with our FREE SITE AUDIT.

Contact Us for a FREE Site Audit and to Learn More About D7ES!

If you buy Drupal 7 Maintenance and Support now, you'll get to keep that price when the change to Drupal 7 Extended Support happens in 2021!

Dec 18 2019
Dec 18
Project: Drupal coreVersion: 8.8.x-dev8.7.x-dev7.x-devDate: 2019-December-18Security risk: Critical 17∕25 AC:Basic/A:User/CI:All/II:All/E:Proof/TD:UncommonVulnerability: Multiple vulnerabilitiesDescription: 

The Drupal project uses the third-party library Archive_Tar, which has released a security improvement that is needed to protect some Drupal configurations.

Multiple vulnerabilities are possible if Drupal is configured to allow .tar, .tar.gz, .bz2 or .tlz file uploads and processes them.

The latest versions of Drupal update Archive_Tar to 1.4.9 to mitigate the file processing vulnerabilities.

Edited to clarify the nature of the upstream release.


Install the latest version:

Versions of Drupal 8 prior to 8.7.x are end-of-life and do not receive security coverage.

Additional information

All advisories released today:

Updating to the latest Drupal core release will apply the fixes for all the above advisories.

(Note that this SA is the only one in the list that applies to Drupal 7.x)

Reported By: Fixed By: 
Dec 18 2019
Dec 18
Project: Drupal coreVersion: 8.8.x-dev8.7.x-devDate: 2019-December-18Security risk: Moderately critical 10∕25 AC:Basic/A:User/CI:Some/II:None/E:Theoretical/TD:DefaultVulnerability: Access bypassDescription: 

The Media Library module has a security vulnerability whereby it doesn't sufficiently restrict access to media items in certain configurations.

  • If you are using Drupal 8.7.x, you should upgrade to Drupal 8.7.11.
  • If you are using Drupal 8.8.x, you should upgrade to Drupal 8.8.1.

Versions of Drupal 8 prior to 8.7.x are end-of-life and do not receive security coverage.

Alternatively, you may mitigate this vulnerability by unchecking the "Enable advanced UI" checkbox on /admin/config/media/media-library. (This mitigation is not available in 8.7.x.)

Additional information

All advisories released today:

Updating to the latest Drupal core release will apply the fixes for all the above advisories.

Reported By: Fixed By: 
Dec 18 2019
Dec 18
Project: Drupal coreVersion: 8.8.x-dev8.7.x-devDate: 2019-December-18Security risk: Moderately critical 14∕25 AC:Basic/A:Admin/CI:Some/II:All/E:Theoretical/TD:DefaultVulnerability: Multiple vulnerabilitiesDescription: 

Drupal 8 core's file_save_upload() function does not strip the leading and trailing dot ('.') from filenames, like Drupal 7 did.

Users with the ability to upload files with any extension in conjunction with contributed modules may be able to use this to upload system files such as .htaccess in order to bypass protections afforded by Drupal's default .htaccess file.

After this fix, file_save_upload() now trims leading and trailing dots from filenames.


Install the latest version:

  • If you use Drupal core 8.7.x: 8.7.11
  • If you use Drupal core 8.8.x: 8.8.1

Versions of Drupal 8 prior to 8.7.x are end-of-life and do not receive security coverage.

Additional information

All advisories released today:

Updating to the latest Drupal core release will apply the fixes for all the above advisories.

Reported By: Fixed By: 
Dec 18 2019
Dec 18
Project: Drupal coreVersion: 8.8.x-dev8.7.x-devDate: 2019-December-18Security risk: Moderately critical 12∕25 AC:None/A:None/CI:None/II:None/E:Theoretical/TD:AllVulnerability: Denial of ServiceDescription: 

A visit to install.php can cause cached data to become corrupted. This could cause a site to be impaired until caches are rebuilt.


Install the latest version:

Versions of Drupal 8 prior to 8.7.x are end-of-life and do not receive security coverage.

To mitigate this issue in any version of Drupal 8, you can also block access to install.php if it's not required.

Additional information

All advisories released today:

Updating to the latest Drupal core release will apply the fixes for all the above advisories.

Reported By: Fixed By: 
Dec 18 2019
Dec 18

To make queries and build listing pages on Drupal 8, or any other content to collect, we have EntityQuery, the API Database (see Make a SQL query on multiple tables with Drupal 8) or the Views module which provides us an extremely powerful requester and graphical interface. Each of these methods has its advantages and disadvantages and may be more appropriate in certain situations (complexity of the request, etc.).

One of the advantages of the EntityQuery is that it is easy to make complex queries under many dynamic conditions. However, Views requests can also be dynamically altered, although this type of alteration may be slightly more complex due to the power of Views.

A particularly useful use case can be to add a relationship to a View dynamically (the equivalent of $query->join()). Let's take an example right away, with a view based on the Node entity (base table: node), for which we want to add a relationship based on a field_user field referencing a user, and then be able to alter the query based on the Users entities referenced by this field.

To do this, we will implement hook_views_query_alter() which allows us to alter the request of a View before it is executed.

 * Implements hook_views_query_alter().
function my_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->id() == 'view_machine_name') {
    $current_user = $view->getUser();
    $condition = _my_module_custom_condition($current_user);
    if ($condition) {
      $definition = [
        'table' => 'node__field_user',
        'field' => 'entity_id',
        'left_table' => 'node',
        'left_field' => 'id',
      $join = \Drupal::service('plugin.manager.views.join')
        ->createInstance('standard', $definition);
      $query->addRelationship('my_relation', $join, 'node');

      $currentUserId = $current_user->id();
        'my_relation.field_user_target_id = :currentUid',
        ['currentUid' => $currentUserId]);

 * Helper function to test a condition.
 * @param \Drupal\Core\Session\AccountInterface $current_user
 *   The current user.
 * @return bool
 *   TRUE if condition passed.
function _my_module_custom_condition(AccountInterface $current_user) {
  $result = TRUE;
  // Some stuff.
  return $result;

In this example, according to any business condition, we can instantiate a new $join relationship, add this relationship as "my_relation" to the query, then add a condition to our query based on this new added relationship.

Not being a big user of Views except for specific use cases, I recently discovered the use of this type of Plugin used by Views to create and manage relationships to a view. A type of plugin that makes it possible to facilitate complex alterations of a view in a relatively clear way. With the help of a Drupal developer, we can use views designed by site builder profiles for these relatively complex use cases, and managed and maintained by users with different profiles.

All tastes are in nature, and it takes everything to make a world.

Dec 17 2019
Dec 17

Developer portals need three kinds of great content to succeed. 

  1. API Documentation

  2. Technical Documentation

  3. Marketing Content

Content is being consumed differently now than it was in the past. Dense long-form, bespoke technical communication is going away. Clear, highly visual , easy to read content is taking the lead.  When building a developer portal, content quality and organization needs to be a high priority for your team. .   

API Documentation

Clear API Documentation is a critical component of success.  Your developers rely on this documentation during development.   It needs to be easy to read and understand, and most importantly it needs to be consistent across all your APIs; this consistency starts with good planning upfront. This is content strategy with a particular focus on technical documentation and will result in a writing guide for API docs to help foster usability and readability. Templates and writing guides provide consistency that will increase your developer community’s happiness and productivity.  

Technical Documentation

Technical Documentation is your API program’s supporting content. These include practical use case scenarios, SDK documentation, Frequently Asked Questions, and other technical topic content. Paying attention to the quality of this content is important.  Rambling, bespoke technical documentation will not be consumed by your developer community and will slow the growth of your API acceptance. We help companies develop content governance strategy plans that create a consistent tone, tenor and taxonomy for your technical documentation. Consistent, easy to read, well tagged technical content is a winning combination. 

Marketing Content

Marketing Content. Digital transformation is being powered by APIs; the company API developer portal is becoming the place where these initiatives are being communicated. The ‘customer’ is the developer who comes to your site and consumes your API’s in order to build out new products, services and transactions. Growing adoption of API programs along these channels requires solid marketing material. This content communicates the business value of using your API products and should include all stakeholders in the process as you gather input from across the organization. Work with writers who will create great copy and content to sell your API program. 

The Apigee developer portal is a powerful content management system built using Drupal 8. It is the perfect platform to manage these three types of content.   

Chapter Three is a digital agency that helps organizations develop amazing Apigee developer portal experiences by providing API program strategic planning, content strategy, technical writing, development, training and support.

We look forward to partnering with you. 


About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web