Planet Drupal

Syndicate content - aggregated feeds in category Planet Drupal
Updated: 7 hours 54 min ago

Dries Buytaert: Acquia a Leader in the 2021 Gartner Magic Quadrant for Digital Experience Platforms

Fri, 01/29/2021 - 18:39

Today, for the second consecutive year, Acquia was named a Leader in Gartner's Magic Quadrant for Digital Experience Platforms (DXPs).

Our leader position improved compared to last year. Acquia is now the number two. Market validation from Gartner on our vision is exciting and encouraging.

In the report, the analysts note the Drupal community as a powerful entity that sets Acquia apart from closed-monoliths. Closed monolithic stacks and martech silos are quickly becoming a thing of the past. Drupal's scale, modularity and openness is a real differentiator.

Mandatory disclaimer from Gartner

Gartner, Magic Quadrant for Digital Experience Platforms, Irina Guseva, Mick MacComascaigh, Mike Lowndes, January 27, 2021.

This graphic was published by Gartner, Inc. as part of a larger research document and should be evaluated in the context of the entire document. The Gartner document is available upon request from Acquia.

Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner's research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.

Dcycle: hook_update_N(), a powerful and dangerous tool to use sparingly

Fri, 01/29/2021 - 01:00
What is hook_update_N()?

Let’s say you are developing a Drupal module (custom or contrib) which tracks how many visitors landed on specific node pages, version 1 of your code might track visitors by nid (node id) in the database using a table like this:

nid visitors 1 4 13 22

Let’s set aside the debate over whether the above is a good idea or not, but once your code has been deployed live to production sites, that’s what the data will look like.

This module might work very well for a long time, and then you might have the need to track not only nodes but also, say, taxonomy term pages. You might rethink what your database table to look like this:

type id visitors node 1 4 node 13 22 term 4 16

To achieve this change when the first version of your database is already out in the wild, you need to tell target environments to update the database schema. This is done using hook_update_N(), and you would replace the N() by incremental numbers, something like this:

/** * Update database schema to allow for terms, not only nodes. */ function hook_update_9001() { ... }

If this case 9 is the major version (Drupal 9) and 001 because this is the first update to your code.

Each module tracks which version it’s using, so that if code introduces new hook_update_N() functions, it will know to run them only once. You can tell which schema version any installed module is using by running, for example:

drush ev "print(drupal_get_installed_schema_version('webform'))"

This might tell you, for example, that Webform’s current schema is 8621. This means that the latest update hook that was run is Webform’s hook_update_8621(). If the codebase introduces hook_update_8622(), say, or hook_update_8640() (you can skip numbers if need to), then the database will be marked as out of date and running drush updb will run the the new hook and update the installed schema version.

If you ever need to re-run an update hook (which happens rather rarely), you can update the schema, like this:

drush ev "drupal_set_installed_schema_version('webform', 8620)" So what’s wrong with this?

This works well almost all the time, and you can automate your deployment process to update the database, making sure your schemas are always in sync. However as developers and site users it is important to be aware of certain drawbacks of hook_update_N(), which I’ll get to in detail:

  • hook_update_N() tightly couples the database to the code version;
  • it makes gradual-deployment on multi-container setups such as Kubernetes fragile (or impossible);
  • rollbacks are not possible;
  • it can add considerable compexity to deployment of configuration.
The shaky foundation of database-driven websites

The idea of version control is paramount to how we conceive of computer code. If you’re following the precepts of continuous deployment, then every version of your code needs to “work” (that is, tests need to pass, or, at the very least, it needs to be installable).

For example, let’s assume a bug makes it to your production for version 5 of your code, and you know this bug was not present on version 4 of your code, you should theoretically be able to check out version 4 and confirm it was working, then figure out what the difference it between version 4 and 5.

In fact this is exactly how things work on static sites such as Jekyll: all your data and your functionality (Javascript) are in your codebase. Each version of your code will be internally coherent, and not rely on an external unversioned database to do something useful.

On database-driven projects based on Drupal or Wordpress, if you check out version 4 of your codebase, it will probably not do anything useful without a database dump which was created using version 4 of your code.

Therefore, although we all use version control for our code, we are almost fooling ourselves, because critical parts of our project are not version-controlled: the database dump, the ./sites/default/files folder, and the private files folder.

Although it makes sense for certain elements to be a database or on ./sites/default/files, for example, an encrypted user account password or a user’s avatar; for other elements such as your “About page” text, it would really make a lot more sense for this to be under version control.

In fact, the blog post you are reading right now is a file under version control on Jekyll, which you can see using this link, and not some collection of opaque, unversioned, entries in database tables with names like node__body, node__field_tags, node_field_revision, which can be changed at a moment’s notice by any module’s hook_update_N() functions.

Oh, did I mention that I love Drupal?

Tight code-database coupling

Let’s imagine a world where the database schema never changed. A world where hook_update_N() does not even exist.

In such a world, you could take any version of your code, and any version of your database dump (say, the latest version), combine the two on a test environment, and debug errors at will.

In the real world, every time any module updates the database schema, it makes the database more tightly coupled to the current version of the codebase.

Let’s take our “number of visitors per entity” code we had earlier: if I use an old codebase which expects my table to contain fields “nid” and “visitors”, but my only available database dump has fields “type” “id”, “visitors”, the history of my carefully version-controlled codebase will be useless, and old versions will fail with an error such as:

ERROR 1054 (42S22): Unknown column 'id' in 'field list'. Gradual deployments

Mostly we think of Drupal sites as being on a server with one copy of the codebase, and one copy of the database. So the concept of keeping the database and code “in sync” makes sense.

But as more and more teams use containers and Kubernetes-type container-orchestration systems, high-traffic sites might have, say, one performance-optimized database, and then 5, 10 or 20 load-balanced copies of your PHP code.

Acquia uses such a setup behind the scenes for its cloud hosting, so it’s good to develop with this in mind. On Acquia’s setup, each PHP container shares a single database, as well as the private and public files directories.

But the PHP containers do not share the /tmp directory. This means that every time you perform a web request on a server, the load balancer might direct you to a container with its own /tmp, whose contents differ from other containers’ /tmp.

It’s important to realize this when building large files over several web requests, and can lead to hard-to-diagnose bugs such as:

But in addition to providing you with headaches such as the above issues, multiple containers can also allow you to do gradual deployments of new code, reducing the risk of failure.

For example, let’s say you have 20 Drupal containers with 20 copies of your codebase, and each Drupal container is connected to a shared database, and shared files and private files directories. If you are deploying a risky update to your code, you might want to start by deploying it to 25% of the containers (5). Then if there are no adverse effects, scale up to 10 the next day, then the entire 20 the day after.

Code that uses hook_update_N() can break this workflow: because all containers share the database, if container 1 has the new version of your code and updates the database accordingly (so that the new database fields are “type” “id”, “visitors”); then container 10 (which uses the old version of your code) will fail when it looks up the database field “nid”.


Let’s forget about fancy container orchestration and just look at a typical Drupal website. A simple real-world site might have a “contact us” webform and some pages, plus some custom functionality.

Let’s say you are deploying a change to your codebase which triggers a hook_update_N(). No matter the amount of unit tests, stage testing, there is always the possibility that a deployment to production might trigger unforseen issues. Let’s assume this is the case here.

A typical deployment-to-production scenario would be:

  • You backup your production database.
  • You install your new code.
  • You run drush updb which updates the database schema based on your hook_update_N().
  • A few hours pass. Several people fill in your contact form, which means now your database backup is out of date.
  • You realize your newly-deployed code breaks something which was not caught by your stage testing or your automated tests.

In a situation like this, if you did not have hook_update_N()s in your code, you could simply roll back your codebase on production to the previous version.

However, this is no longer an option because your database will not work with previous versions of your codebase: there is no hook_downgrad_N(). You are now forced to live with the latest version of your code, and all the benefits of version-controlling your code are for naught.

Config management

Let us recall the elements which make up a Drupal website:

  • Versioned code.
  • Unversioned database and file directories.

If you are using configuration management and a dev-stage-production workflow, there is a third category:

  • Configuration, like enabled modules, node types, and fields, which exist both in the database and in unversioned code.

It is worth recalling a typical workflow:

  • add field_new_field to the article node type on your local machine.
  • the field is now in your local development database but not in your codebase
  • drush config-export
  • the field is now in your local development database and also in your codebase
  • do all your testing and push your code to production

At this point your field is in your production codebase but not your production database.

Don’t forget: your deployment script already has “drush updb” in it. The question is: do you run “drush config-import” before or after “drush updb”?

It turns out this is not that easy a question to answer. Drush also provides a drush deploy command which combines configuration import and database updates.

Regardless of your deployment process, however, we need to take into account a more troubling possibility:

In addition to relatively benign database schema updates, hook_update_N() can modify configuration as well.

In such a case, if you are not careful to run hook_update_N() first on your development environment, then export the resulting configuration, then run your deployment, you may run into the following problem:

#3110362 If an update hook modifies configuration, then old configuration is imported, the changes made by the update hook are forever lost.

Let’s look at a real-world example using the Webform module. Let’s install a new Drupal 8 site with Webform 5.23, then export our configuration, then upgrade to Webform 6.x and import our old configuration. We’ll this causes a bug, and we’ll see why after.

composer require drupal/webform:5.23 drush si -y drush en webform_ui -y drush config-export -y

This puts your current site configuration into code. Among said configuration, let’s focus on a single piece of configuration from Webform:

drush cget webform.settings settings.default_page_base_path # 'webform.settings:settings.default_page_base_path': form

The base path for webforms is form. This tells Webform to build URLs with a structure such as

Let’s now update webform, and our database.

composer require drupal/webform:6 drush updb -y drush config-import -y

In Webform’s webform_update_8602(), the config item webform.settings:settings.default_page_base_path is changed from “form” to “/form”.

But we are re-importing old config, which overwrites this change and reverts webform.settings:settings.default_page_base_path to “form”, not “/form”

To see the type of hard-to-diagnose error this might lead to, you can now log into your Drupal site, visit /admin/structure/webform, create a webform named “test”, and click on the “View” tab.

Because the base path lack the expected trailing prefix, you now get the “not found” URL /admin/structure/webform/manage/form/test, instead of the expected /form/test.

In addition, this has a number of cascading effects including the creation of badly-formatted URL aliases which you can see at /admin/config/search/path.

If you find yourself in this situation on production, you need to revert your Webform schema version on your development environment, export your config, reimoprt it on production, and resave your forms, and potentially fix all your paths starting with “form” on /admin/config/search/path so that they start with “/form”.

To be fair, this is not the fault of the Webform maintainers. In my opinion it shows a fundamental frailty in hook_update_N() combined with lack of documentation on deployment best practices. However, if we strive for Drupal to be a robust framework, there should not be a single point of failure (in this case not strictly adhering to fickle, badly-documented deployment procedures) which can lead to major instability on production.

How do we fix hook_update_N()?

Here are a few approaches to avoid the potential damage done by hook_update_N():

Approach 1: don’t use hook_update_N()

When possible, you might consider not using hook_update_N() at all. Consider our “number of visitors per node” module from earlier.

Instead of a hook_udate_N(), your code could do something like this:

  • Do not change the field name from “nid” to “id”. Even though “id” makes more sense, the field is called “nid”, just leave it at that.
  • Do not expect there to be a “type” field. If you need it, create it.
  • Assume an empty “type” means you are dealing with a node.

The above approach adds complexity to your code, which you can add to a “storage” abstraction class. Although not ideal, this does away with the need to use hook_update_N().

Approach 2: Don’t use hook_update_N() to update configuration

Updating configuration, as seen above, is even more dangerous than updating non-configuration database tables. So if at all possible, avoid it.

In the Webform example given above, it might have been reasonable to consider keeping with the old non-leading-slash format for path prefixes, rather than update configuration.

When you absolutely must update configuration, you could consider the possibility that certain users might have reimported old configuration, and provide error-checking and hook_requirements() (displaying error messages on the /admin/reports/status page) accordingly.

Approach 3: Robust exception handling

Do not assume that your database schema is up-to-date. If you decide that it is worth update the schema from, for example, “nid” and “visitors” to “type”, “id”, “visitors”, when querying the database, you might want to consider the possibility that for whatever reason the database is not up-to-date. Here is some pseudo-code:

public function num_visitors_for_entity($id, $type = 'node') : int { try { return $this->query_database($type, $id); } catch (\Exception $e) { $this->logAndDisplayException($e); return 0; } }

That way, if your database and code are not in sync, it’s not going to break your entire site.

Approach 4: keep config changing logic idempotent and separate from update hooks

Let’s look again at Webform’s webform_update_8602(), the config item webform.settings:settings.default_page_base_path is changed from “form” to “/form”.

I would recommend having a separate function to update config, and call that function from the update hook. That way, if a development team makes the mistake of not updating their configuration before importing it into production, it will become easier to run, say “my_module_update_configuration()”.

Then, your hook_requirements() might perform some sanity checks to make sure your configuration is as expected (in this example, that the “webform.settings:settings.default_page_base_path” config item has a leading slash). If this smoke test fails, developers can be directed to run my_module_update_configuration() which will update all configuration to the required state.

In addition, my_module_update_configuration() can be made idempotent, meaning: no matter how often you run it, you will always end up with the desired state, and never get an error.

Resources What is hook_update_N()?

Gabe Sullice: A Positive Digital Experience

Thu, 01/28/2021 - 16:07
This is a follow up to an earlier post titled Using Drupal for Digital Experiences; that post attempted to illustrate an abstraction for thinking about digital user experiences generally and suggested that Drupal could evolve into a tool for creating them. At the end of it, I asked readers to imagine practical applications for Drupal in that role as an experience builder. In this post, I share a story about a practical digital user experience IRL! Then, the post breaks down that experience and connects it back to how Drupal could power the same kind of experience. Finally, it highlights a contributed module that has the necessary functionality already.

DrupalEasy: How popular is Drupal, really?

Thu, 01/28/2021 - 10:00

As part of the interview process for Drupal Career Online, we provide potential students with some background information about Drupal so that they can make a more informed decision about whether or not the program suits them. One of the things we communicate is the scope of the Drupal project and its pervasiveness in the web development industry.

As anyone who has tried to find reliable numbers to answer the "how popular is Drupal?" question knows, finding reliable data is often a difficult process. While working to update our recruitment materials this year, we thought we'd share the data we found and the conclusions we've made.


To answer this question, in the past we have relied on the W3Techs (Web Technology Surveys) - a subsidiary of Q-Success, an Austria-based organization. Their methodology seems sound (they monitor the top 10 million web sites), but as their disclaimer states, "This information may be incomplete and inaccurate due to the vastness and complexity of the matter in hand"

As of January, 2021, they report that about 1.5% of all websites they monitor are Drupal-based. This is 2.4% of all web sites using a content management system.

W3Techs does provide a breakdown of usage among the top 1 million, 100,000, etc… sites, but only as part of one of their products (999 €). 

W3Techs reports that Drupal 7 is used by 66.4% of all the websites who use Drupal.

So, how do these numbers compare with other data sources?

Built With

Built With is an Australian company that provides lead generation lists in addition to web development trends among a plethora of technologies. 

They currently report that ~618,000 sites are using Drupal, which equates to 0.97% of all web sites. This is 4th among content management systems after WordPress, WooCommerce Checkout, and Joomla. Their sample size is over 35 million sites.

Their data for the top 1 million sites has Drupal with a 3.28% content management system market share (3rd place), 7.73% in the top 100,000 sites (2nd place), and 12.56% in the top 10,000 sites (2nd place).

Built With also reports that of the ~618k site running Drupal, the United States is responsible for ~250k, with Russia next on the list with ~41k sites.


SimilarTech appears to be primarily a lead-generation company with offices in Israel and the United States. They state that their "proprietary technology scans more than 30 billion web pages per month."

For Drupal, they report that ~236,000 unique domains run Drupal, which equates to ~337,000 sites (I'm assuming that subdomains account for the significant difference in these numbers). 

One potential major problem with their reports is that they often separate Drupal into multiple categories, including "Drupal", "Drupal 7", and "Drupal 8".

While they report that Drupal is used on 0.483% of all sites, it is not clear if this refers to just their "Drupal" category or includes their "Drupal", "Drupal 7", and "Drupal 8" categories. They appear to also break up other content management systems in a similar manner, making it difficult to draw reliable conclusions.

In their list of the top 1 million sites, they report that "Drupal" is used on 2.55% and "Drupal 8" on 0.81% (they only provide the top 8 positions). 

SimilarTech reports that after the United States, Russian sites account for the most Drupal sites with ~32,000. 


So, which data can we trust? What is the real answer? As you might imagine, it is difficult to say…

Removing the SimilarTech data from the equation for reasons stated above, let's look at a summary of we've found:

Metric W3Techs Built With

All sites (CMS + non CMS)

- 0.97% All sites (CMS) - - Top 10m sites (CMS + non CMS) 1.5% - Top 10m sites (CMS) 2.4% - Top 1m sites (CMS) - 3.28% Top 100k sites (CMS) - 7.73% Top 10k sites (CMS) - 12.56%


Clearly, using no-cost data from W3Techs and Built With, it isn't possible for a direct apples-to-apples comparison. But, combined, the data does seem to make sense. If you make the assumption that higher ranked sites have greater complexity and budget, along with the fact that Drupal 8 tends to be focused more on enterprise solutions, then it makes sense that Drupal has a higher percentage of usage among more popular sites.

Can we answer the question "how popular is Drupal?" - well, the answer is "sort of." Often answers to questions like this need caveats, as the table above illustrates. 

So what's the answer? Based on these sources, we're going to extrapolate, and go with Drupal runs about 3% of the top 1 million sites using a content management system as this seems well supported by two independent sources.

Liip: It all relates

Thu, 01/28/2021 - 00:00

"But… it all relates!" A reaction so often heard while facilitating (or participating) to group reflexion processes (brainstorming, agile retrospectives, …).

"You ask us to group things … but everything is connected!"

It often comes with a contrived smile ("things are complex, you know!"). Sometimes also with a counterproposal "let us make a single group around the central thing here which is X, since obviously all things relate to X."

A very human reaction, which if you’re unprepared as facilitator, can take you aback. Keeping the following arguments in your mind can help.

  1. That it all relates does not mean that it all ought to conflate. It makes sense to distinguish the different aspects of a situation or a problem, the different knots of its web of complexity. Some seem to think that seeing the big picture implies refusing to distinguish the whole from its parts. Yet if we can see the links, the relationships, it is because we have identified the parts.

  2. Although a holistic view provides a definite advantage when facing a complex situation, it is good to remind ourselves that action cannot be holistic. You cannot act on the system as a whole. You may only act on precise points of the system.

Two simple arguments to help us facilitate these "everything is connected" moments and realize that in a (group) reflexion process, taking things apart is the first step towards deciding meaningful action.

Photo: Ruvande fjällripa

Mediacurrent: Meet RainU: The Drupal CMS Platform for Higher Education

Wed, 01/27/2021 - 16:55

On the heels of our recent Drupal 9 release of Rain CMS, we are excited to officially announce the beta release of our Rain University platform, RainU. RainU CMS is a Drupal-based development platform made just for higher education. Colleges and universities can now launch new sites faster with full, flexible control over content.


The RainU CMS Theme

New RainU CMS theme homepage

The RainU theme is based on the main Rain base theme but adds additional features that are relevant for university websites. The navigation and content have been staged to help content authors get started quickly. Some of the new features added to RainU are the event and quote carousels, as well as more components for highlighting content.

Building pages

Rain CMS admin content edit page



Paragraph browser dialog


With Rain University, we give content authors the freedom and flexibility to build robust pages using a library of pre-stocked components (called “paragraphs” in Drupal). The Rain Admin UX offers many improvements over the stock Drupal admin which makes the overall experience more intuitive for editors.


Find out more

Currently, Mediacurrent’s Rain University CMS is available to new and existing clients. Our team of strategists, designers and developers can work with your organization to migrate your website from a legacy CMS onto an enterprise, open source platform.

For more information on the benefits of Rain University CMS and to schedule a free demo, please visit the RainU page or chat with us right now (see bottom right corner of the page). We would be happy to talk more about your project or schedule a demonstration.

Make Drupal Easy: Drupal 8 & 9: Resolved: The following reasons prevent the modules from being uninstalled: Fields pending deletion

Wed, 01/27/2021 - 09:29
When you try and uninstall a module that has a field that you have used, it can throw the following error:

Consensus Enterprises: Kubernetes Won't Save You

Wed, 01/27/2021 - 09:06
Kubernetes is popular and trendy. It is, however, overpowered for most projects and introduces unnecessary levels of complexity and overhead. A monolithic architecture is likely to be sufficient for most new projects, and makes it more likely that you will eventually develop the need for the sort of scaling supported by microservices.

Mateu Aguiló: Practical Progressive Decoupling Explained

Wed, 01/27/2021 - 01:00
I recently recorded a video series tutorial about progressive Drupal decoupling. In this series I take two of the official React app examples and turn them into widgets. Your Drupal editorial team can then embed those React applications (a calculator, and an emoji selector) as blocks in a page, as a field in a content type, as an embedded entity in the body field using the WYSIWYG, …

Liip: Svelte TypeScript Tailwind Setup

Wed, 01/27/2021 - 00:00

For the very impatient among us:

npx degit munxar/svelte-template my-svelte-project cd my-svelte-project npm i npm run dev



In this article I'll give you some insights how I set up Svelte with TypeScript and style components with Tailwind. There are plenty of articles around, but I found a lot of them overcomplicate things, or don't fit my requirements.

So here are my goals for the setup:

  • stay as close to the default template as possible, to make updates easy
  • production build should only generate css that is used
  • use typescript wherever possible
What Do I Need?

You'll need at least some node version with npm on your machine. At time of writing I have node version 15.6.0 and npm version 7.4.0 installed on my machine.

node -v && npm -v v15.6.0 7.4.0 Install the Svelte Default Template

To setup Svelte I open a terminal and use the command from the official Svelte homepage. TypeScript support has been already added to this template, so nothing special here.

npx degit sveltejs/template my-svelte-project # or download and extract cd my-svelte-project Enable TypeScript # enable typescript support node scripts/setupTypeScript.js

At this point I try out if the setup works by installing all dependencies and start the development server.

# install npm dependencies npm i # run dev server npm run dev

If everything worked so far, pointing my browser at http://localhost:5000 displays a friendly HELLO WORLD. Let's stop the development server by hitting ctrl-c in the terminal.

Install Tailwind

Back in the Terminal I add Tailwind as described in their documentation.

npm install -D tailwindcss@latest postcss@latest

After this step I generate a default tailwind.config.js file with

npx tailwindcss init

If you prefer a full Tailwind config use the --full argument:
npm tailwindcss init --full
See the Tailwind documentation for more infos about this topic.

Configure Rollup to use Postcss

The default Svelte template uses Rollup as a bundler. When I run the setupTypeScript.js from the first setup step, I get the famous svelte-preprocess plugin already integrated into the rollup setup. The only thing left is that I add the config for postcss as options to the svelte-preprocess plugin. Here are the changes that I make in rollup.config.js:

// rollup.config.js (partial) ... export default { ... plugins: [ svelte({ preprocess: sveltePreprocess({ postcss: { plugins: [require("tailwindcss")], }, }), }), ... ], ... };

At this point Rollup should trigger postcss and therefore the Tailwind plugin. To enable it in my application, I still need one important step.

Adding a Tailwind Component to the App

Now it's time to create a Svelte component that contains the postcss to generate all the classes. I call mine Tailwind.svelte but the name doesn't really matter.

// src/Tailwind.svelte <style global lang="postcss"> @tailwind base; @tailwind components; @tailwind utilities; </style>

Some things to note here:

  • The component only has a single style element with no markup.
  • The attribute global tells the svelte-preprocess plugin to not scope the css to this component. Remember by default Svelte scopes every css to the component it was declared, in this case I don't want this.
  • The lang="postcss" attribute is telling svelte-preprocess to use postcss for the content. As a goody, some IDE extensions now display the content with the correct syntax highlighting for postcss.

Now use the Tailwind component in src/App.svelte

// src/App.svelte <script lang="ts"> import Tailwind from "./Tailwind.svelte"; </script> <Tailwind /> <div class="bg-gray-200 px-4 py-2 rounded">Hello Tailwind!</div>

Now my browser displays a Tailwind styled div. Very nice!
Let's clean up the public/index.html and remove the global.css link tag and remove the corresponding file from public/global.css I don't use it.

<!-- public/index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset='utf-8'> <meta name='viewport' content='width=device-width,initial-scale=1'> <title>Svelte app</title> <link rel='icon' type='image/png' href='/favicon.png'> <link rel='stylesheet' href='/build/bundle.css'> <script defer src='/build/bundle.js'></script> </head> <body> </body> </html>

Let's finish the setup for production builds. Right now it's perfect for development. I can use any Tailwind class and except for the first start of the development server, where all the Tailwind classes get generated, it behaves very snappy on rebuilds.

Production Builds Purge

When it comes to production builds, right now I have not configured anything so I'll get a bundle.css with all Tailwind classes. I don't want that for a production build, so I modify the tailwind.conf.js to use it's integrated purgecss for that purpose.

// tailwind.config.js module.exports = { purge: ["src/**/*.svelte", "public/index.html"], darkMode: false, // or 'media' or 'class' theme: { extend: {}, }, variants: { extend: {}, }, plugins: [], };

With this modification Tailwind removes all classes that are not used in .svelte files and in the public/index.html html file. I added the public/index.html file because sometimes I add containers or some responsive design utilities directly on the tag. If you don't need this, you can remove the index.html file from the purge list, or add additional files I don't have listed here. For example: if I use some plugins that contain .js, .ts, .html, ... files that use Tailwind classes, I would add them to this purge array too.

There is one little detail about the Tailwind purge: it only is executed if NODE_ENV=production which makes sense. I set this environment directly in my package.json scripts:

// package.json (partial) { ... "scripts": { "build": "NODE_ENV=production rollup -c", ... }, ... }

With these settings my bundle.css only contains the Tailwind classed I really use, plus the mandatory css reset code that Tailwind provides.


One last thing to add for production is vendor prefixes. I usually go with the defaults and just add autoprefixer as postcss plugin. If you need more control, add configuration as you please.

Install autoprefixer with npm:

npm i -D autoprefixer

Add it as postcss plugin in rollup.config.js:

// rollup.config.js (partial) { ... preprocess: sveltePreprocess({ postcss: { plugins: [ require("tailwindcss"), require("autoprefixer"), ], }, }) ... }

That's it.

Features of this Setup Tailwind Classes

I can apply every Tailwind class on a every html element even in the index.html template.

Tailwind @apply

Additionaly I can use @apply inside a style tag of a Svelte component like this:

<!-- src/Button.svelte --> <button> <slot /> </button> <style lang="postcss"> button { @apply bg-blue-800 text-white px-3 py-2 rounded hover:bg-blue-900; } </style>

This will generate a class scoped to the button of this component. Important part here is the attribute lang="postcss", without this postcss would not process the content of the style tag.

Typesave Components

Let's implement a simple logo component with an attribute name of type string and a default value of "Logo".

<!-- src/Logo.svelte --> <script lang="ts"> export let name = "Logo"; </script> <div>{name}</div>

When I use this component the svelte language service of my IDE (visual studio code) will yell at me, if I try to pass something as the name attribute that is not of type string.

<!-- src/App.svelte --> <script lang="ts"> import Logo from "./Logo.svelte"; </script> <!-- this results in an error --> <Logo name={42} /> <!-- valid type --> <Logo name="Hello, World" /> <!-- valid because of the default value --> <Logo />

If you have a IDE that supports the svelte language service, you get all the intellisense stuff you would expect inside your editor. I use Visual Studio Code with the very good svelte.svelte-vscode extension.


I demonstrated how easy it is to setup a Svelte project with the default template enable TypeScript and add production ready Tailwind support.

I hope you find some helpful information and write some amazing apps!

The source code is available at:

Docksal: Mailhog and Swiftmailer in Local Development

Tue, 01/26/2021 - 22:32

I recently updated the Simplenews module for my Drupal site and I needed to do some serious testing. Going from Simplenews 1.0-beta1 to 2.0-beta2 wasn’t a simple task, but it was necessary for our Drupal 9 preparation and failure was not an option. Testing is important for any module update, but being able to test sending emails in a local development environment was key here.

We already had MailHog setup and I noticed that I was not getting any emails when I expected to. Not only was I not getting them from a newsletter being published, I wasn’t getting them even running the email test through Swift Mailer. The settings necessary for the Docksal environment are different than what was set on the server.

Adding MailHog for Docksal is simple. The docksal.yml file should contain:

version: 2.1services:
# MailHog
file: ${HOME}/.docksal/stacks/services.yml
service: mail

For the Swift Mailer settings for Docksal, I added this to my local.settings.php file:

* Mail configuration for local mail.
$config['swiftmailer.transport']['transport'] = 'smtp';
$config['swiftmailer.transport']['smtp_host'] = 'mail';
$config['swiftmailer.transport']['smtp_port'] = '1025';
$config['swiftmailer.transport']['smtp_encryption'] = 0;
$config['swiftmailer.transport']['smtp_credential_provider'] = 'swiftmailer';

Now I have Swift Mailer sending mail and MailHog receiving it.

Mailhog and Swiftmailer in Local Development was originally published in Docksal Maintainers Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Chromatic: Edit Once. Publish to Many. Smart Strategies for Content Sharing

Tue, 01/26/2021 - 15:00

Sharing content across multiple sites with a publishing platform offers tremendous opportunities, but it isn’t always easy. Understanding the editorial and technical hurdles is key to creating a solution that works well and addresses the business needs.

Mediacurrent: 5 Digital Focus Areas to Navigate University Marketing Challenges

Tue, 01/26/2021 - 14:25

As we look ahead to the end of the future academic year and what the future looks like, we see uncertainty clouding what is a typical admissions season for teams in higher education. 

Recently, we asked our partners in higher education to share their digital challenges. We heard that admissions personnel, as well as marketing teams at the college and university level, are feeling the pressure. They need to make sure the expectations of stakeholders are met or exceeded despite the unpredictable path ahead. 

Even though teams may face challenges ahead, one thing is certain: rethinking digital strategy to set your path forward will set your team up for success and your institution apart from others. 

The website is the heart of your digital strategy, and both should be built to adapt. That’s why many higher education institutions choose Drupal for their organization’s CMS. 

Below are five areas to focus your digital strategy, with some of our favorite tips and tools to improve campaigns moving forward.

Reevaluate Your Content Strategy

Universities used to enjoy a steady flow of students enrolling in programs. However, the future is now uncertain because of the COVID-19 pandemic leading many students to forego education or to choose online courses over taking classes in a traditional, physical environment. 

The uncertainty affected not just marketing teams at universities, but students as well. When the McKinsey higher education survey was conducted in April 2020, 37% of responding students were confident that things would return to normal by the end of summer. However, the 2020-2021 school year has thus far reflected much of what the previous school year 

Findings from our own client survey showed that uncertainty in the 2020 recruitment season led to several shifts in strategy to further help the user journey in the decision making process of choosing programs such as the following: 

  • Virtual tours rather than in-person tours
  • Live video conferences rather than in-person sessions
  • Website content to supplement brochures and physical marketing materials

Changes in academia lead to a shift in messaging, so teams need to evaluate if their content strategy is still working or if more needs to be done to cater to today’s student and their new priorities. 

Some ways in which evaluating content strategy can be done include: 

Persona research

 Although you may have a general idea of who your target audience is, more thorough research that includes user surveys can help create a better understanding of who your content should speak to. For instance, you may learn from user surveys that students and parents are uncertain about returning to in-person learning because they want to know more about what is being done to keep people safe in the classroom. With this information in mind, you might develop more content about COVID-19 cleaning protocols to give them peace of mind.

Content audit

Is your content resulting in growth, and does it cater to your users? If you are not getting the most out of it, an audit can help address gaps and find opportunities. 

Dashboard creation

Making sense of data is an important responsibility of a university’s marketing team. User-friendly dashboards can simplify the process of reviewing data and making decisions based on findings. Working with a digital strategy team with experience in higher education to improve your approach can yield results that allow your content to better serve student needs.

Give Your Marketing Team The Tools to Succeed

Giving the university marketing team agency in creating content quickly and efficiently is a top priority of many agencies that work directly with these teams. However, finding a CMS that provides the flexibility they want and a user-friendly editorial experience they need can be a challenge.  

RainU CMS can improve the editorial experience for content editors looking for a solution that allows for easier workflows that match with your existing design standards. With the ability to launch sites in 30 days or less, Rain helps both content editors and developers create flexible websites fast.

If your site is on Drupal, creating a decoupled solution with Gatsby may be just what you need. The business case for decoupled Drupal with Gatsby can help you determine if the cost and benefits are right for your university. Our developers are well adept at providing guidance in setting up GatsbyJS.

Using Drupal with Gatsby is a great way to get an enterprise-quality CMS for free, paired with a great modern development experience and all the benefits of the JAMstack, like performance, scalability, and security.

Make Smarter Use of Resources  

Unprecedented changes in higher education likely result in unexpected changes to budgets and priorities. Streamline the routine maintenance of your Drupal site to shift more budget toward new features. Here’s how Mediacurrent’s development solutions like Automated Updates and Multisite+ can help:

With Automated Updates, you can save hours of manual development work. Our automation services initiate pull requests, create JIRA issues, and stage updates within Pantheon’s multidev environment. Your team of project managers and developers can focus on productive work rather than administrative tasks when using Automated Updates for your project. 

Need to create multiple sites? Spin up new instances with Multisite+! With a shared codebase, your sites can go from concept to creation quickly and efficiently, and each has its own database, configuration, files, and base domain or URL to help with organizing your content. 

We have a wide variety of development services to meet your university marketing needs. 

Enhance Web Accessibility 

Universities cater to individuals of all abilities, so it’s important to make sure the digital experience is accessible to all. Using a tool like Siteimprove can help university marketing teams better understand how their site’s accessibility matches up to Web Content Accessibility Guidelines (WCAG) standards. 

SiteImprove's automated reports provide an easy way to measure and document progress toward accessibility goals

Failing to keep on top of website accessibility could lead universities to face warnings from the Department of Education as well as lawsuits. Mitigation measures such as using Siteimprove or working with a skilled accessibility team to audit and remediate your site allows your team to take steps that minimize the possibility of lawsuits as a result of your site’s digital experience. 

Launch New Campaigns Faster 

Colleges and departments within universities often need to launch campaigns quickly, and depending on the technology involved, expediency is integral. Teams must have a workable solution to accomplish the goals of an individual college or department.

Marketing teams can take advantage of RainU CMS to launch to market in 30 days or less. 

Gain more control over your site with RainU CMS such as:  

  • Robust Security - Mitigate attacks from hackers - RainU CMS has several built-in security hardening features to help.
  • Flexible Content Feature-Packed - Build pages with a flexible, easy to use interface in RainU CMS for rapid development.
  • Component-Based Theme - Like with other Drupal sites, RainU CMS has reusable components and a built-in style guide which reduces design time.
Demo RainU CMS 

Ready to take your higher ed site and marketing campaigns to the next level? Explore how RainU CMS can get you there and check out the demo below. 

Specbee: Top 7 Remarkable Education Websites Built on Drupal (and Why was it Chosen)

Tue, 01/26/2021 - 13:27
Top 7 Remarkable Education Websites Built on Drupal (and Why was it Chosen) Shefali Shetty 26 Jan, 2021 Top 10 best practices for designing a perfect UX for your mobile app

What’s common between Universities and Drupal? Both are powered by communities and both fuel community-based initiatives. In this article, we will look at some amazing educational websites built on Drupal and why they choose Drupal as their CMS.

Did you know every Ivy league school website is built on Drupal while 71% of the top 100 Universities around the world use Drupal? Numbers speak volumes about a good CMS, but we have many more reasons to prove that Drupal is the best CMS for educational websites. Read on to find out.

This list has been curated with information obtained from

Why do top universities rely on Drupal

Top universities like Stanford, MIT, Oxford, and others alike, choose Drupal as their Content Management System. Universities are built on large communities – there’s the student community, the teaching staff community, the community of departments, the management, and other working staff. Being a community-driven CMS, Drupal helps knitting all these communities together. Drupal addresses issues in a way that streamlines information between each of its communities. 

  • Drupal allows for scalability to accommodate the ever-growing communities and varied web projects associated with them. The CMS is also well-known for dealing with a large user-base and high-traffic websites which is great for universities with a growing student base.
  • Drupal empowers educational institutes to build varied flexible solutions – from intranets to complex web applications to simple static web portals.
  • Drupal’s multi-site approach lets universities easily manage and create independent websites from a single codebase.
  • Features like multilingual, mobile-responsiveness, effective workflow management, access control, and others are now out-of-the-box with Drupal 8, thus making it an ideal choice for educational institutions.
Some Remarkable Education Institute Websites built on Drupal 1. George Washington University

Known best for producing some great leaders in every domain, George Washington University (GWU) relies on Drupal to create an engaging web presence for them. 

Why Drupal was chosen:
  • Drupal’s multisite feature now allows them to spin up new sites faster than ever before. 
  • Accessibility – GWU is committed to web accessibility and so is Drupal.
  • Responsive Web Design – The GWU website is completely responsive on all devices.
  • Ability to build scalable features and functionalities with customizable layouts.
  • GWU expected a reliable digital experience platform. And Drupal delivered.
  2. University of Oxford

The prestigious University of Oxford has been at the top of the world university rankings for five years in a row. They offer over 250 different programs with a student population of over 24,000.

Why Drupal was chosen:
  • The open-source nature of Drupal worked out well for them financially and also meant that they will not have to depend on one company for all their development needs.
  • A global community of driven developers working towards making Drupal better every day.
  • To collaborate and work better with other units of the university who were already using Drupal.
  • Drupal’s list of quality case studies, including the White House, turned out impressive enough to make the final call.
  3. Rutgers University

Rutgers is New Jersey’s state university and is one of the highest-ranked public universities in America with over 71,000 undergrad and grad students. They moved their website to Drupal more than 10 years ago.

Why Drupal was chosen:
  • They wanted a design that looked great on all devices.
  • To deliver a consistent user experience among their various school locations.
  • Distinguish between their different schools yet provide a unified experience.
  • Allowed for fast and easy admission application at different university locations.
  4. Bookshare

Although not a university, we had to mention the Bookshare website because it does a fantastic job at imparting knowledge to the visually challenged and people with learning difficulties. There are different formats of accessing the books – audio, large-sized printed, or braille.

Why Drupal was chosen:
  • Web accessibility – They needed to have the highest level of compliance (AAA) to ensure accessibility by the visually impaired.
  • Multilingual capabilities – Bookshare is made available to people across the world and is currently available in 7 different languages (and counting), thanks to Drupal’s multilingual feature and translation modules.
  • To support deep integration with their existing APIs.
  5. Georgia Tech Professional Education

Georgia Tech Professional Education is one of the many academic units of Georgia Tech, serving more than 36,000 learners globally. Georgia Tech is one of the top 10 universities in the US.

Why Drupal was chosen:
  • Its ability to integrate with various third-party marketing and communication tools.
  • Data security to protect student information.
  • Improved performance with smart caching.
  • To provide a user-friendly, easy to navigate and access website.
  6. UChicago News

The University of Chicago News office focuses on publishing new content ranging from student academic information to current affairs. They publish over 1000 stories every year that are later picked up and published by other media and publishing firms.

Why Drupal was chosen:
  • To improve website performance and speed during peak traffic events.
  • Powerful and smooth migration of their heavy websites with over 20,000 content nodes and over 10,000 taxonomy terms.
  • To be able to accommodate their growing number of pages, content types, and access control levels.
  • Easy creation and management of content with an effective workflow system in place.
  7. University of Minnesota

Founded in 1851, this top university has more than 50,000 students enrolled in its programs. University of Minnesota is one of the very few universities that can boast about having a medical school, an engineering school, a law school, an agricultural school, and a veterinary school – all in one campus! They had 600 sites that needed to be migrated to Drupal, each of them heavy in terms of storage size with millions of monthly visitors.

Why Drupal was chosen:
  • They needed a flexible CMS that could handle their humungous number of visitors and content with ease.
  • To be able to quickly create new sites from standard design and features – using Drupal install profiles.
  • To build a centrally maintained, yet independently distributed platform that can be used across departments, satellite campuses, organizations, staff, etc.
  • To offer a secure platform with an extremely low tolerance for failure.


Information is available on our fingertips today and it has become more important than ever to stay relevant and provide the right information at the right time. Educational institutes are no different when it comes to showcasing content to a wide range of audience. Creating a digital strategy and using the right platform is vital for these institutes’ survival. Drupal has proven time and again to be the top choice of CMS for educational institutes – ranging from universities to Ivy league schools to higher ed schools. With features like intuitive content management abilities, web accessibility, multisite approach, responsive design, seamless third-party integrations and more, no wonder Drupal is the number one choice for education institutes

Contact us today to know how our Drupal experts can help you with your next Drupal project. We’d love to hear from you!

Drupal Planet Drupal Development Drupal Drupal Module Shefali ShettyApr 05, 2017 Subscribe For Our Newsletter And Stay Updated Subscribe

Leave us a Comment

  Shefali ShettyApr 05, 2017 Recent Posts Image Top 7 Remarkable Education Websites Built on Drupal (and Why was it Chosen) Image Drupal 9.1 and its compatibility with PHP 8 – Learn what’s new and how to check compatibility Image Drupal – Is it a CMS for Everyone? Want to extract the maximum out of Drupal? TALK TO US Featured Success Stories

A Drupal powered multi-site, multi-lingual platform to enable a unified user experience at SEMI.


Discover how our technology enabled UX Magazine to cater to their massive audience and launch outreach programs.


Discover how a Drupal powered internal portal encouraged the sellers at Flipkart to obtain the latest insights with respect to a particular domain.


Golems GABB: Guide to creating page layouts with Drupal Paragraphs

Tue, 01/26/2021 - 12:02
Guide to creating page layouts with Drupal Paragraphs Editor Tue, 01/26/2021 - 13:02

Beautifully and logically arranged content is key to better user engagement. Luckily, Drupal abounds in modules to create web page layouts. Site builders and content editors can rely on the new Drupal 8/9’s Layout Builder, the Panels, the Display Suite, the Gutenberg … and, of course, on the super popular Paragraphs module. We decided to devote a few useful paragraphs here to using Drupal Paragraphs. Let’s begin!

DrupalEasy: Understanding common cache-related HTTP response headers

Tue, 01/26/2021 - 10:00

Having a basic understanding of caching is a requirement of being a professional Drupal developer. Unfortunately, there can be many layers of caching which can make it challenging to figure out exactly how best to configure cache settings and troubleshoot potential caching issues.

Web page caching can be thought of as moats around the castle, where each moat is a caching layer and the castle can be thought of as the site's web, database, and other origin servers.

HTTP headers provide a mechanism for the client (usually a web browser) and a server (usually a web server) to exchange information that is not visible to the end user, nor included in the HTML of the page. While there are few types of headers, cache-related headers are generally "response headers".

This blog post isn't meant to be a comprehensive guide to all layers of web page caching, rather we'll focused on common, cache-related HTTP response headers. Information in these response headers can help developers identify which caching layers, if any, were utilized in a given page request. Specifically, we'll be looking at how to view this response header information, and what it can tell us about Drupal page caching and content delivery network (CDN) caching activity on a per-request basis.

Keep in mind that there is not a constrained list of headers that can be added to a page request or response. While there is a common set defined by the Internet Assigned Numbers Authority (IANA) additional proprietary (custom) headers can be added by developers and vendors. It is also important to note that header names are case-insensitive, so the header names "Cache-Control" and "cache-control" are equivalent.

Instructions for viewing cache-related HTTP headers is included at the bottom of this article.

Categories of cache-related response headers

Cache-related response headers can be categorized as either "standard" or "proprietary". Standard headers are those defined by IANA while proprietary headers are added by developers and vendors. Below is a sample of some of the commonly-used cache-related response headers:

Standard (non-proprietary) cache-related response headers
  • Age: the time (seconds) that the object (file) has been cached.
  • Cache-control: general directives for caching mechanisms. For example, if this is set to "no-cache", then the file won't be cached.
  • Expires: the date/time after which the response will be considered stale, and then refreshed from the source. For Drupal sites, by default, this value is set to Dries Buytaert's birth date.
Common proprietary response headers

Again, these are not industry-standard response headers, and different vendors (hosting companies, content delivery networks) may have different implementations. It is best to refer to your specific vendor's documentation for additional details.

  • x-drupal-cache: Drupal-specific header set by Drupal core, values include "HIT", "MISS", and "UNCACHEABLE". Provided by the core Internal Page Cache module, applies only to anonymous users.
  • x-drupal-dynamic-cache: Drupal-specific header set by Drupal core, values include "HIT", "MISS", and "UNCACHEABLE". Provided by the core Internal Dynamic Page Cache module, applies to both anonymous and authenticated users. Allows for partial responses. See blog post by Wim Leers for more information.
  • x-served-by: this header is added by various tools to (normally) indicate the server that provided the response. This includes some (but not all) hosting companies and content delivery networks.
  • x-cache: in general, this indicates if the file was served by a CDN or the origin server. Multiple x-cache values often correspond to multiple "x-served-by" values.
  • x-cache-hits: for some CDNs, this value closely mirrors the "x-cache" value, only with a value of "0" being equivalent to "MISS" and any positive value equivalent to a "HIT" (the value being equal to the number of tries before a hit).
  • cf-cache-status: set by Cloudflare CDN, indicates the status of a cache request. Values include "HIT", "MISS", "DYNAMIC", "EXPIRED", and others. Note that in its default configuration, Cloudflare will not cache HTML - only things like static images.
  • cf-ray, cf-request-id: set by Cloudflare CDN to help trace requests through the Cloudflare network. Used for troubleshooting.

At this point, it is important to note an important difference between two of the more widely-used content delivery networks, Fastly and Cloudflare. Fastly is primarily a content delivery network built on top of the Varnish web application accelerator. While Fastly does have some web application firewall (WAF) capabilities, Cloudflare is both a content delivery network and a full, security-focused web application firewall provider. In some cases (including for, both Fastly and Cloudflare can be used - Fastly for its CDN and Cloudflare for its WAF.


Below are a couple of examples of cache-related response headers along with a short discussion about what they mean. cache-related response header values for HTML page Authenticated user

Cache-Control: no-cache, must-revalidate x-served-by: cache-sea4481-SEA, cache-mia11376-MIA x-cache-hits: 0, 0 x-cache: MISS, MISS

Non-cached page served from the "origin server" (located at Oregon State University) due to the "Cache-Control" value.

The "x-cache" values indicate that for authenticated users,'s CDN (Fastly) did not serve the page. The first "x-served-by" value is the Fastly server closest to the origin server, while the second value is the Fastly server closest to the user loading the page. While "x-cache" indicates that a cached version of the page was not used, it was Fastly's servers that initially processed the request and ultimately retrieved the page from the origin server.

Anonymous user

Cache-Control: public, max-age=900 x-drupal-cache: MISS x-served-by: cache-sea4420-SEA, cache-mia11369-MIA x-cache-hits: 1, 4 x-cache: HIT, HIT

The "Cache-Control" value provided by the origin server indicates that the page can be cached for up to 900 seconds (15 minutes). The "x-cache" values indicate that the cached page was served by the Fastly server closest to the user ("cache-mia11369-MIA" in this example). cache-related response header values for HTML page Authenticated user

Cache-Control: no-cache x-served-by: cache-mdw17368-MDW, cache-mia11364-MIA x-drupal-dynamic-cache: UNCACHEABLE x-cache-hits: 0, 0 x-cache: MISS, MISS cf-cache-status: DYNAMIC

DrupalEasy is hosted on Pantheon (which includes the Fastly CDN) and uses the Cloudflare CDN. The "x-cache" values indicate that for authenticated users, Pantheon's default CDN (Fastly) did not serve the page. The first "x-served-by" value is the Fastly server close to the origin, while the second value is the Fastly server close to the user loading the page. While "x-cache" indicates that a cached version of the page was not used, it was Fastly's servers that processed the request and ultimately retrieved the page from the origin (Pantheon) server.

The "cf-cache-status" of "DYNAMIC" indicates that the file is not eligible for caching by Cloudflare. This is normally a result of a directive from the origin server to never cache the file ("Cache-Control: no-cache").

Anonymous user

cache-control: max-age=60, public x-served-by: cache-mdw17325-MDW, cache-mia11383-MIA x-drupal-cache: HIT x-drupal-dynamic-cache: MISS x-cache-hits: 0, 1 x-cache: MISS, HIT cf-request-id: 0775a92a710000e958291b2000000001 cf-ray: 60cfaaf0aa52e958-MIA cf-cache-status: DYNAMIC

For an anonymous user, the "x-cache" value of "MISS, HIT" indicates that the 2nd "x-served-by" value (the Fastly server close to the user) provided a cached response. cache-related response header values for image (site logo) Anonymous and authenticated users

Cache-Control: max-age=31622400 Expires: Fri, 31 Dec 2021 17:54:40 GMT x-served-by: cache-mdw17349-MDW, cache-mia11320-MIA x-cache-hits: 1, 1 x-cache: HIT, HIT cf-cache-status: HIT

The "cf-cache-status" value of "HIT" indicates that Cloudflare served this image. The "Cache-Control" value indicates that the image can be cached for up to 3162240 seconds (< 36 days). Note that the image was cached every step of the way on both Fastly and Cloudflare.

Manually "bust" the cache

During development, sometimes it is necessary to "bust" the cache - that is, to request an uncached version of the content. While this can be done by clearing/purging/rebuilding caches at every level of the site's infrastructure (Drupal, Fastly, Cloudflare), it can also be done by adding a unique querystring variable to the content as they are cached according to their unique URL, including querystring variables. So, if you want to request an uncached version of "logo.png", simply append a meaningless querystring variable to it - for example, "logo.png?buster=2358973430985234895".


As the previous examples show, in order to be able to make sense of cache-related response headers, it is important to know which, if any CDNs are being used as well as which, if any, Drupal-level caching modules are enabled.

Resources Viewing cache-related HTTP headers

All major browsers provide relatively easy access to HTTP header information, if you know where to look. Here's a quick guide:

  • Open Web Inspector ("Inspect Element" anywhere)
  • Go to "Network" tab.
  • Reload page.
  • Click on (usually) first entry in list of files - this will be the main HTML file for the page.
  • Click on the "Headers" sub-tab.
  • Open the network tools via the "Tools|Web Developer|Network" menu item.
  • Reload page.
  • Click on (usually) first entry in list of files - this will be the main HTML file for the page.
  • Click on the "Headers" sub-tab.
  • Open the network tools via the "View|Developer|Developer Tools" menu item.
  • Go to "Network" tab.
  • Reload page.
  • Click on (usually) first entry in list of files - this will be the main HTML file for the page.
  • Click on the "Headers" sub-tab.

  • Open Developer Tools (Crtl-Shift-I).
  • Go to "Network" tab.
  • Reload page.
  • Click on (usually) first entry in list of files - this will be the main HTML file for the page.
  • Click on the "Headers" sub-tab.

Thanks to Andy Giles from Blue Oak Interactive for reviewing this blog post.

DrupalCon News: You've got this! Notes about impostor syndrome

Tue, 01/26/2021 - 09:32

The program committee shares about impostor syndrome and wants to remind community members that you know more than you give yourself credit for.

Promet Source: Documenting Web Accessibility: Do You Need a VPAT?

Tue, 01/26/2021 - 08:34
It has become increasingly common to find located in the footer of many websites a link to their Statement of Accessibility. In a few cases you will find some sites with a VPAT (Voluntary Product Accessibility Template) and Statement of Accessibility linked. What are these documents? What is their purpose and should your site have one or both?