24 Feb 2026

feedDrupal.org aggregator

Specbee: How to decide between a Drupal agency and a general web agency

The real difference between a Drupal agency and a general web agency isn't what you think. Are you asking the right questions? Read this article to find out what you're missing.

24 Feb 2026 10:41am GMT

MidCamp - Midwest Drupal Camp: MidCamp Chicago 2026 call for sessions open through Feb 26

We're excited to celebrate you -- our future speakers! If you've got an idea for a session, now's the time to get involved in MidCamp 2026, happening May 12-14 in Chicago.

Call for Speakers

Since 2014, MidCamp has hosted over 300 amazing sessions, and we're ready to add your talk to that legacy. We're seeking presentations for all skill levels, from Drupal beginners to advanced users to end users and business professionals!

For full submission details and guidelines, visit: midcamp.org/events/2026/how-submit-session

Key Dates

Sponsor MidCamp

Looking to connect with the Drupal community? Sponsoring MidCamp is the way to do it! Whether you're recruiting talent, growing your brand, or simply supporting the Drupal ecosystem, MidCamp sponsorship offers great value. Act early to maximize your exposure!

Stay in the Loop

Ready to submit your session? Click away and let's make MidCamp 2026 unforgettable!

24 Feb 2026 6:34am GMT

DDEV Blog: Using WarpBuild to speed up DDEV in CI

Warp Speed CI

For most developers, DDEV solves a common challenge: making sure that each developer has a consistent, stable local environment for building their web application. We had more and more success with DDEV at Lullabot, but another related issue kept coming up: how do we grow and develop our use of continuous integration and automated testing while avoiding the same challenges DDEV solved for us?

A typical CI/CD pipeline is implemented using the tools and systems provided by the CI service itself. For example, at a basic level you can place shell commands inside configuration files to run tests and tools. Running those commands locally in DDEV is possible, but it's a painful copy/paste process. If you're a back-end or DevOps engineer, odds are high you've wasted hours trying to figure out why a test you wrote locally isn't passing in CI - or vice versa!

As a first step, we used Task to improve our velocity. Having a unified task runner that works outside PHP lets us standardize CI tasks more easily. However, this still left a big surface area for differences between local and CI environments. For example, in GitHub, the shivammathur/setup-php action is used to install PHP and extensions, but the action is not identical to DDEV. Underlying system libraries and packages installed with apt-get could also be different, causing unexpected issues. Finally, there was often a lag in detecting when local test environments broke because those changes weren't tested in CI.

This brought us to using DDEV for CI. It's a great solution! Running all of our builds and tasks in CI solved nearly every "it works on my machine" problem we had. However, it introduced a new challenge: CI startup performance.

Unlike using a CI-provider's built-in tooling, DDEV is not typically cached or included in CI runners. Just running the setup-ddev action can take up to a minute on a bad day. That doesn't include any additional packages or Dockerfile customizations a project may include. At Lullabot, we use ddev-playwright to run end-to-end tests. Browser engines and their dependencies are heavy! System dependencies can be north of 1GB of compressed packages (that then have to be installed), and browsers themselves can be several hundred MB. This was adding several minutes of setup time just to run a single test.

Luckily, based on our experience building Tugboat, we knew that the technology to improve startup performance existed. When WarpBuild was announced with Snapshot support in 2024, we immediately started testing it out. We theorized that the performance improvement of snapshots would result in significant startup time improvement. Here's how we set it up!

We had three parallel jobs that all required DDEV:

  1. Playwright Functional Tests - these were using 8 "large" runners from GitHub to complete our test suite fast. Before WarpBuild, each runner took between 15 and 20 minutes to run tests.
  2. Static tests running PHPStan, PHPUnit, and so on.
  3. ZAP for security scanning.

Note that our Playwright tests themselves run in parallel on a single worker as well, using lullabot/playwright-drupal. This allows us to optimize the additional startup time for installing Drupal itself (which can't be cached in a snapshot) across many tests.

After linking WarpBuild to our GitHub repository, we had to update our workflows. For the full combined example, see the repository at ddev/ddev-ci-warpbuild-example.

Here is an example representing the changes we made to our workflow after enabling Snapshots in the WarpBuild UI. At a high level, here's the flow we want to create with our GitHub jobs:

flowchart TD
    A[determine-snapshot: <br>Hash key files] --> B[Request WarpBuild runner<br>with snapshot key]
    B --> C{Snapshot exists?}
    C -->|"Yes (fast path)"| D[Restore snapshot<br>DDEV pre-installed]
    C -->|"No (first run)"| E[Install DDEV, browsers,<br>and dependencies]
    D --> F[Start DDEV & run tests]
    E --> F
    F --> G{First run?}
    G -->|Yes| H[Clean up & save snapshot]
    G -->|No| I[Done!]
    H --> I

Start with a basic workflow to trigger on pull requests and on merges to main.

name: "WarpBuild Snapshot Example"

on:
  push:
    branches: [main]
  pull_request:

Before running our real work, we need to know what snapshot we could restore from. We start by creating a hash of key files that affect what gets saved in the snapshot. For example, if Playwright (and its browser and system dependencies) are upgraded by Renovate, we want a new snapshot to be created. Extend or modify these files to match your own project setup.

jobs:
  determine-snapshot:
    # This could be a WarpBuild runner too!
    runs-on: ubuntu-24.04
    outputs:
      snapshot: ${{ steps.snapshot-base.outputs.snapshot }}
    steps:
      - uses: actions/checkout@v6

      - name: Determine Snapshot Base
        id: snapshot-base
        run: |
          set -x
          hash=$(cat .github/workflows/test.yml test/playwright/.yarnrc.yml test/playwright/yarn.lock | md5sum | cut -c 1-8)
          echo "snapshot=$hash" >> $GITHUB_OUTPUT
        shell: bash

WarpBuild needs some additional configuration to tell GitHub Actions to use it as a runner. This could be as simple as runs-on: 'warp-<runner-type>' if you aren't using snapshots. WarpBuild has many runner options available, including ARM and spot instances to reduce costs further.

The runs-on statement:

  1. Skips snapshots via commit messages.
  2. Uses a "16x" sized runner so we can run tests in parallel.
  3. Creates a snapshot key with the project name, the ddev version, a manual version number, and the short hash of the files from above.

We also switch to the WarpBuild cache (so it's local to the runner) and check out the project. Update the cache paths as appropriate for your project.

jobs:
  # other jobs...
  build-and-test:
    needs: [determine-snapshot]
    runs-on:
      "${{ contains(github.event.head_commit.message, '[warp-no-snapshot]') &&
      'warp-ubuntu-2404-x64-16x' ||
      format('warp-ubuntu-2404-x64-16x;snapshot.key=my-project-ddev-1.25.1-v1-{0}', needs.determine-snapshot.outputs.snapshot) }}"

    steps:
      - uses: WarpBuilds/cache@v1
        with:
          path: |
            ${{ github.workspace }}/.ddev/.drainpipe-composer-cache
            ${{ github.workspace }}/vendor
            ${{ github.workspace }}/web/core
            ${{ github.workspace }}/web/modules/contrib
          key: ${{ runner.os }}-composer-full-${{ hashFiles('**/composer.lock') }}

      - uses: actions/checkout@v6

We need to add logic to either start from scratch and install everything or restore from a snapshot. Since DDEV isn't installed by default in runners, we can use its presence to easily determine if we're running from inside a snapshot or not. We save these values for later use.

jobs:
  # other jobs...
  build-and-test:
    steps:
      # ... previous steps ...
      - name: Find ddev
        id: find-ddev
        run: |
          DDEV_PATH=$(which ddev) || DDEV_PATH=''
          echo "ddev-path=$DDEV_PATH" >> "$GITHUB_OUTPUT"
          if [ -n "$DDEV_PATH" ]; then
            echo "ddev found at: $DDEV_PATH (restored from snapshot)"
          else
            echo "ddev not found (fresh runner, will install)"
          fi

If ddev exists, we can skip installing it:

jobs:
  # other jobs...
  build-and-test:
    steps:
      # ... previous steps ...
      - name: Install ddev
        uses: ddev/github-action-setup-ddev@v1
        if: ${{ steps.find-ddev.outputs.ddev-path != '/usr/bin/ddev' }}
        with:
          autostart: false
          # When updating this version, also update the snapshot key above
          version: 1.25.1

At this point, we've got DDEV ready to go, so we can start it and run tests or anything else.

jobs:
  # other jobs...
  build-and-test:
    steps:
      # ... previous steps ...
      - name: Start ddev
        run: |
          # Playwright users may want to run `ddev install-playwright` here.
          ddev start
          ddev describe

      - name: Run tests
        run: |
          ddev exec echo "Running tests..."
          # Replace this with one or more test commands for your project.
          ddev task test:playwright

Now, tests have passed and we can create a snapshot if needed. If tests fail, we never create a snapshot so that we don't accidentally commit a broken environment.

We shut down DDEV since we're going to clean up generated files. This keeps our snapshot a bit smaller and gives us an opportunity to clean up any credentials that might be used as a part of the job. While we don't typically need a Pantheon token for tests, we do need it for some other jobs we run with DDEV.

jobs:
  # other jobs...
  build-and-test:
    steps:
      # ... previous steps ...
      - name: Clean up for snapshot
        if: ${{ steps.find-ddev.outputs.ddev-path != '/usr/bin/ddev' }}
        run: |
          # Stop ddev to ensure clean state
          ddev poweroff
          # Remove any cached credentials or tokens
          rm -f ~/.terminus/cache/session
          # Clean git state and temporary files
          git clean -ffdx

Now we can actually save the snapshot. We skip this if we can since it takes a bit of time to save and upload. There's no point in rewriting our snapshot if it hasn't changed! The wait-timeout-minutes is set very high, but in practice this step only takes a minute or two. We just don't want this step to fail if Amazon is slow.

jobs:
  # other jobs...
  build-and-test:
    steps:
      # ... previous steps ...
      - name: Save WarpBuild snapshot
        uses: WarpBuilds/snapshot-save@v1
        if: ${{ steps.find-ddev.outputs.ddev-path != '/usr/bin/ddev' }}
        # Using a matrix build? Avoid thrashing snapshots by only saving from one shard.
        # if: ${{ matrix.shard == 1 && steps.find-ddev.outputs.ddev-path != '/usr/bin/ddev'}}
        with:
          # Must match the snapshot.key in runs-on above
          alias: "my-project-ddev-1.25.1-v1-${{ needs.determine-snapshot.outputs.snapshot }}"
          fail-on-error: true
          wait-timeout-minutes: 30

To test, once you have jobs passing, you can rerun them from the GitHub Actions UI. If everything is working, you will see all steps related to installing DDEV skipped.

Note: We don't pin actions to hashes in these examples for easy copypaste, but for security we always use Renovate to pin hashes for us. We would also like to use Renovate Custom Managers to automatically offer DDEV upgrades and keep the version number in sync across all files and locations.

The Results?

While this seems like a lot of work, it was only about half a day to set up and test - and that was when WarpBuild was in beta, had minimal documentation and some rough edges. We haven't really had to touch this code since. Setting up new projects is an hour, at most.

Do you have other optimizations for DDEV in CI to share? Post in the comments, we'd love to hear them!

24 Feb 2026 12:00am GMT

23 Feb 2026

feedDrupal.org aggregator

DrupalCon News & Updates: DrupalCon Chicago 2026: Must‑See Sessions for Seasoned Developers

Hey experienced developers! You know how to tame Drush, charm Composer, debug like a detective, juggle configs, and wrestle with tricky modules. But there's an event that will max out your RAM with Drupal hacks, insights, and wisdom.

Chicago may be famous for deep-dish pizza, but this spring it's serving up something even more satisfying: deep dives into Drupal. DrupalCon Chicago 2026 is the place for seasoned developers to sharpen their skills, swap stories, and maybe laugh at a few module mishaps along the way.

It's a code playground with a side of professional growth - sessions designed to challenge, inspire, and connect. Ready to level up your craft and enjoy a few geeky chuckles? The program is packed with standout sessions, but here are a few you absolutely won't want to miss.

Top DrupalCon Chicago 2026 Sessions for Experienced Developers

"The state of JavaScript Code Components in Drupal Canvas" - by Bálint Kléri

Drupal Canvas, the new-generation page builder, offers multiple ways to create pages for different audiences. Non-tech users will enjoy intuitive drag-and-drop tools, ready-made components, and even building pages from a prompt to an AI agent. But what's in it for developers? First of all, it's Code Components.

JavaScript in Drupal keeps evolving, and Code Components in Drupal Canvas are the latest twist worth watching. First unveiled at DrupalCon Atlanta, they came with a zero‑setup, in-browser editor and instant support for React and Tailwind CSS.

Things have moved fast: data fetching and Next.js-style image optimization are now supported, and experiments with server-side rendering and third-party imports are in progress. And editing isn't limited to the browser anymore - a new CLI lets you work with Code Components anywhere, opening doors to decoupled frontends and fresh workflows.

Catch Bálint Kléri (balintbrews), the technical lead for JavaScript components in Drupal, in his insightful session, where he will walk through what's stable, what's experimental, and what's next. You'll discover specific approaches and techniques for working with Code Components.

"AI Agents for Site Builders" - by Marcus Johansson

AI-driven automation is changing the ways organizations handle content personalization, workflows, customer support, and data insights. One of the most exciting tools to emerge from the Drupal AI initiative is AI agents - autonomous systems that carry out tasks, make decisions, and pursue goals on behalf of users.

You can learn more about Drupal's new AI Agents framework from Marcus Johansson (marcus_johansson). On his drupal.org page, Marcus describes himself simply: "I tinker with AI." But his "tinkering" is transforming Drupal from the ground up: Marcus leads the Drupal AI initiative in Drupal, shaping its architecture, driving its development roadmap, and steering the future of AI-powered tools in Drupal.

In this session, Marcus will show you how Drupal's Agents framework lets you create business-specific agents without writing a single line of code. Instead of slogging through implementation details, you'll see how prompt writing and communication skills can drive the interaction, while Drupal quietly handles the complexity behind the curtain.

Join Marcus as he unpacks what agents are, how the framework was built, and how it connects with the MCP (Model Context Protocol). For experienced developers, this session is a chance to explore a tool that cuts through the noise and unlocks fresh possibilities.

"Advanced Site Building with Drupal Canvas" - by Ted Bowman

Drupal Canvas is gaining serious momentum, and it deserves a closer look from more than one angle. Alongside the earlier-mentioned session on Code Components, this one is a hands-on exploration of how Canvas works hand in hand with some of Drupal's most powerful tools.

Ted Bowman (tedbow), a long-time Drupal contributor, will show how Drupal Canvas can be combined with core features like Views and popular contributed modules to build advanced setups - all without writing a single line of code.

You'll see an exciting demo packed with practical examples: creating dynamic landing pages, formatting structured content with Canvas templates, linking field data to SDC (Single-Directory Components) and Code Component properties, building Views inside Canvas templates, and using template slots to give editors more control.

As Canvas continues to evolve, Ted will also spotlight the latest features and contributed modules that extend its capabilities even further.

"Next Generation ECA - Vision and Progress update" - by Jürgen Haas

Drupal offers many ways of workflow automation. But having tasks quietly carried out in the background - triggered by events, checked against conditions, and completed through actions - is a special kind of magic.

Experienced developers may remember the Rules module that pioneered this idea. Today, its modern successor, the Event-Condition-Action (ECA) module, takes the concept further, reimagined for Drupal's current ecosystem. With a no-code/low-code approach and graphical modeling tools like BPMN, ECA makes building workflows more intuitive and far less intimidating.

Despite the amazing graphical interface with diagrams for ECA workflows, ECA needed to become even more approachable, especially for people without prior Drupal experience. So after solid real-world use and plenty of feedback from the community, ECA is entering its next phase. In his session, ECA's creator, Jürgen Haas (jurgenhaas), the creator of ECA, will share how things are going with the revamp.

By lowering the barrier for site builders and project managers, the evolving ECA creates more room for developers to extend, integrate, and scale automation. The refreshed interface makes workflows easier to work with, while the underlying architecture opens fresh opportunities for custom plugins, enterprise integrations, and performance tuning.

"A Taste of the Future: Site Templates and Recipes in Drupal" - by Jim Birch

Drupal has always had a knack for ambitious site building, but the Recipes Initiative is cooking up something new. Instead of distributions that lacked flexibility, we now have lightweight, composable recipes and site templates that make functionality easier to share, remix, and extend.

For experienced developers, it's about speeding up the boring parts so you can focus on the interesting ones. Default content APIs and config actions are steadily maturing, and the community is already serving up recipes that cut down setup time while keeping flexibility intact.

Step into this session led by Jim Birch (thejimbirch), a renowned Drupal core committer and initiative coordinator. He will walk you through the progress so far, highlight examples from the community, and demonstrate practical authoring workflows. You'll leave with a clear sense of how recipes fit into Drupal's future, how to find and apply them effectively, and how to contribute your own to the growing ecosystem.

"Beyond Iframes: Modern Embedding in Drupal with Media and oEmbed" - by Pedro Cambra

Embedding external content in Drupal has become trickier as platforms tighten security rules and content policies. If iframes keep letting you down, this session offers a cleaner, more future-proof approach.

Join Pedro Cambra (pcambra), an experienced Drupal contributor, as he shares practical guidance on embedding external content with oEmbed. He explores how Drupal uses the oEmbed standard together with core Media tools and contributed modules like oEmbed Providers to embed third-party content safely and reliably. You'll get a clear look at how oEmbed works behind the scenes, which modules fit best for different use cases, and how CKEditor handles embedded objects.

The session also touches on enhancing embeds with authentication or privacy controls and building your own oEmbed resources for custom content. Practical examples keep things grounded, with plenty of tips you can apply right away. If you've ever wrestled with embeds or want a more robust setup that plays nicely with modern platforms, this session is well worth your time.

"Future Proof Theming: Best Practices for Drupal's New Era" - by Mike Herchel and Andy Blum

Theming in Drupal is entering a new era, and this training is designed to keep even seasoned developers ahead of the curve. It will be led by Mike Herchel (mherchel) and Andy Blum (andy-blum), key contributors driving theming innovations in Drupal. The training session dives into Single Directory Components, Drupal Canvas, and modern CSS/JS techniques that will shape how we build themes going forward.

Through hands‑on exercises, you'll learn to craft reusable components, streamline workflows with Storybook, and deliver designs that are fast, accessible, and maintainable.

You'll pick up strategies to dodge common page‑builder pitfalls and keep your themes flexible for whatever comes next. If you're ready to sharpen your skills and future‑proof your toolkit, this training belongs on your schedule. It must be noted that training sessions require an additional ticket.

Driesnote - by Dries Buytaert

Every DrupalCon has its traditions, and the Driesnote is one of the most anticipated. For developers who spend their days building and maintaining Drupal sites, the Driesnote is a chance to catch a glimpse of what's emerging in the platform.

Beyond the usual updates, it's the place to hear the newest features, initiatives, and announcements that set the stage for what's coming next for Drupal. You'll discover new tools, architectural changes, and exciting directions for core and contributed projects, all straight from Dries Buytaert. Right in the main auditorium, you'll catch demos that haven't been shown anywhere else yet.

This session is Drupal's roadmap in real time. Experienced developers will walk away with inspiration for their own projects, and an insider's view of upcoming improvements that could change how we work with the platform.

Final thoughts

Wrapping up the developer sessions at DrupalCon Chicago, the vibe is clear: Drupal keeps giving us new tools, and it's up to us to explore them, stress-test them, and help shape what comes next. Canvas, ECA V2, Recipes, Site Templates, and other cool innovations are all evolving fast, and the fun part is digging into the details to see how they really work.

For experienced developers, the focus shifts away from shiny demos to spotting patterns, catching edge cases, and laughing when the "easy" stuff turns into a rabbit hole. These sessions are a reminder that Drupal's future is being built in real time - and that we still get to shape it through commits, patches, and the occasional late-night debugging marathon.

Authored By: Nadiia Nykolaichuk, DrupalCon Chicago 2026 Marketing & Outreach Committee Member

23 Feb 2026 8:08pm GMT

Talking Drupal: Talking Drupal #541 - Mautic

Today we are talking about Mautic, marketing automation, and its history with Drupal with guest Ruth Cheesley. We'll also cover Mautic ECA as our module of the week.

For show notes visit: https://www.talkingDrupal.com/541

Topics

Resources

Guests

Ruth Cheesley - ruthcheesley.co.uk RCheesley

Hosts

Nic Laflin - nLighteneddevelopment.com nicxvan John Picozzi - epam.com johnpicozzi Catherine Tsiboukas - mindcraftgroup.com bletch

MOTW Correspondent

Martin Anderson-Clutz - mandclu.com mandclu

23 Feb 2026 7:00pm GMT

Mike Herchel's Blog: Fun, dancing, and contribution at Florida DrupalCamp (photos included)!

Fun, dancing, and contribution at Florida DrupalCamp (photos included)! mherchel

23 Feb 2026 6:32pm GMT

The Drop Times: Architecture Before Alchemy

Every technology cycle has its buzzwords. This one has AI stamped on every roadmap, budget request, and vendor pitch deck. As Nitish Chopra argues, the rush to "integrate AI" into content management systems feels less like strategy and more like panic. Organizations are bolting large language models onto legacy stacks without confronting a harder truth: most digital architectures were never designed to support structured, machine-readable intelligence.

The pattern is becoming predictable across the CMS landscape. Some teams chase quick wins through plugin overload and surface-level integrations. Others pay enterprise premiums for repackaged APIs marketed as innovation. A third group disappears into technical rabbit holes, overengineering AI experiments that never survive contact with production realities. In each case, the failure is architectural. AI is treated as a feature to be installed, not a capability that depends on disciplined data modeling, governance, and system design.

This is where the Drupal ecosystem enters the conversation. For years, Drupal's insistence on entities, fields, taxonomies, and structured content was criticized as overly complex. Yet those very foundations align with what AI systems require: clean schemas, reusable content objects, and predictable relationships. What once felt rigid now looks intentional. What was labeled pedantic now resembles preparation.

For Drupal builders, agencies, and enterprise stakeholders, the question is not whether to integrate AI, but how to do so without abandoning architectural discipline. AI success in Drupal will not come from chasing wrappers around APIs or cosmetic chatbot add-ons. It will come from doubling down on structured content architecture, refining data governance, and designing composable systems that can support automation at scale. In that sense, the ecosystem's competitive advantage is not novelty. It is discipline.

This week's edition reflects on that tension between momentum and method before turning to the stories shaping the ecosystem.

With that, let's shift the spotlight to the important stories from last week.

INTERVIEW

DISCOVER DRUPAL

DRUPAL COMMUNITY

EVENTS

ORGANIZATION NEWS

We acknowledge that there are more stories to share. However, due to selection constraints, we must pause further exploration for now. To get timely updates, follow us on LinkedIn, Twitter, Bluesky, and Facebook. You can also join us on Drupal Slack at #thedroptimes.

Thank you.

Alka Elizabeth
Sub-editor
The DropTimes

23 Feb 2026 4:07pm GMT

Jacob Rockowitz: Coding Drupal with AI

Introduction

There is a subtle bait-and-switch here: I am going to talk about my experience coding with AI in Python, but the lessons learned apply to Drupal and the broader challenges developers face when coding with AI.

Over the past few months, AIs have begun to understand and write code for Drupal, and I want to understand how AI can help me with my Drupal projects. I would be the first to say "Vibe Coding" sounds like something invented in a hipster cafe, but it is here to stay, just like the Frappuccino.

As a Drupal Developer who has written a lot of PHP code over the years, I welcome the opportunity to write less and think more. Call me old-fashioned, but I am a self-taught developer who learned by reading books, even though AI moves so fast that books on the topic are out of date within a year. I decided to look for a book to help with this journey.

A search for "Coding Drupal with AI" yields very few results, yet it is notable that a post titled "Claude Code meets Drupal" by Dries Buytaert, the creator of Drupal, appears on the first screen of results. Sometimes, when learning something new or facing a new challenge, I like to work around the challenge.

For example, when I first started learning Drupal 8 as an experienced Drupal 6/7 developer, I was stumped by Symfony and the OOP patterns being introduced into Drupal, so I spent a few weeks building a Symfony application and then dove deep into Drupal 8. So I decided to approach AI coding in Python because it is a popular programming language that I was curious to learn. I chose to read Coding with AI: Examples in Python by Jeremy Morgan because it focuses first on AI and secondarily on using Python.

My...Read More

23 Feb 2026 12:12pm GMT

UI Suite Initiative website: Live show - Display Builder demo on Talk On My Machine (TOMM)

Overall summarySparkFabrik continues to be a welcoming hub for the Drupal community, and this session was a great example of that. As part of their ongoing "Talk on My Machine" series, SparkFabrik hosted Michaël Fanini to present Display Builder - the latest addition to the UI Suite ecosystem, designed to simplify and unify the display-building experience in Drupal.

23 Feb 2026 10:59am GMT

20 Feb 2026

feedDrupal.org aggregator

The Drop Times: The Work Behind the Workflow: Stas Zhuk and the Future of DDEV

As a maintainer of DDEV, Stas Zhuk works behind the scenes to ensure thousands of developers rarely have to think about their local environments. In this interview with The DropTimes, he reflects on reliability, open source responsibility, AI-assisted development, and what it takes to keep critical infrastructure stable even during power blackouts in Ukraine.

20 Feb 2026 5:03pm GMT

Pivale: Using Agentic AI Without Vibe Coding

Practical guide to using Agentic AI in Drupal development without vibe coding. Learn where AI helps, where it fails, and how to produce reliable code.

20 Feb 2026 12:55pm GMT

ComputerMinds.co.uk: Drupal 11 Upgrade Gotchas - Slick Carousel

A bit of background

Even as a seasoned Drupal developer, when upgrading a Drupal 10.x site to Drupal 11.x you can still encounter a number of weird issues with some older legacy code on the site, which had previously (unbeknownst to you) relied on functionality that has now changed in some way, shape or form due to the upgrade to Drupal Core and its dependencies.

I've just gone through a long morning of debug hell with some JavaScript functionality on a client's site that has previously not had any issues throughout the last few Drupal upgrades. For context, this site was originally built as a Drupal 7 site (all those years ago!), has been entirely rebuilt and migrated to Drupal 9, upgraded to Drupal 10 and now is finally being upgraded to Drupal 11(.3).

The site has a fair number of different JavaScript powered Carousels on the site, and at the time of building the site originally, the 'in vogue' solution for responsive carousels was the excellent Slick Carousel (Github link). I won't go into too many details about this package here, but it's worked well and hasn't caused any issues over the years with previous Drupal upgrades.

The package is dependent on jQuery, and with the move to jQuery 4.x in Drupal core (an optional dependency!), this is where the problems started. Now, it's unfair to expect a package with the last official release of nearly 9 years ago to magically work with a newer version of jQuery which didn't exist at the time (the latest version in 2017 was 3.2 but the plugin was designed around jQuery 2.x), but with the aim of trying to keep within budget for this Drupal 11 upgrade, it was decided to not rewrite the entire functionality of the carousels on this site.

This would have involved having to implement an entirely new (ideally non jQuery dependent!) plugin such as Swiper or Glider and re-writing the DOM structure in all the Twig templates that contain the markup for each of the carousels, tweaking the styling for each carousel, and then re-writing the various JavaScript code to work with the new chosen plugin. If the site only had a simple type of carousel in a singular place, then swapping out would have been a suitable option but the carousels on the site in question are quite complex in some instances, so I decided to go with trying to make Slick work.

The initial problem

Even though there hasn't been an official release of the package since October 2017, there has been work in the master branch in the last few years to make the plugin work with more modern jQuery versions. The previous upgrade to use jQuery 3.x in Drupal core (versions 8.5 and above) didn't actually cause any noticeable issues with the Slick plugin (at least in our use case), but the version 4 upgrade as part of Drupal 11 finally caused us issues.

jQuery 4 has finally removed a number of deprecated APIs, one of which is jQuery.type, which is what Slick used internally in multiple parts of it's code.. without the function available anymore, of course, the JavaScript blows up! Luckily, there have been a number of commits to the master branch of Slick in the last few years and one in 2022, which fixed these deprecated calls, allowing it to work properly with more modern jQuery versions. The commit in question was designed to fix jQuery 3.x issues, but by swapping out deprecated API calls in time, it's enabled it to work (mostly) with 4.x as well.

So to get the master version in place instead of the latest official release (which is very old), I made the following change to our package.json (the project in question uses npm) in the list of dependencies, changing:

"slick-carousel": "^1.8.1",


to (the latest commit hash in the master branch):

"slick-carousel": "github:kenwheeler/slick#279674a815df01d100c02a09bdf3272c52c9fd55",


and then re-installed the projects JS dependencies to bring the new version in.

(For reference, we have some code that will take the version installed here into the node_modules folder and copy it into our sites custom theme directory in an appropriate folder, we then define this as a custom Drupal library and include only where needed.)

With the latest version in place, the JS error with the previously used deprecated API's was gone, yay! But now we had other issues to worry about.

Further problems

The first thing I noticed, now that the JS error was gone, was that a carousel on the homepage looked to be styled incorrectly compared to the version in production. Closer inspection of the DOM revealed that, for some reason now (after not changing any of the invocation calls to the Slick plugin), the slides were now wrapped in two extra divs, instead of the slides themselves getting the slick-slide class (amongst others).

At this point in time, I just assumed this was just a newer behaviour of the updated code of the Slick plugin.. so I set about just making a few quick style changes to the CSS that we had previously not had to take into account of these extra wrapping divs. Later on, I discovered the real reason for these additional wrapping divs... keep reading to find out what it was.

Broken:

broken slick carousel

Fixed:

fixed slick carousel

This solved this immediate problem, and then I went hunting for the other carousels on the site, which is where things got very interesting (and time-consuming!)

The next carousel's with an apparent problem were on the site's main product page, where one is used on the left hand side (displayed vertically) and acts as a navigation of thumbnails of the 'main' product image gallery that is displayed next to it. The left hand one appeared to be functioning mostly correctly in itself (with a small style issue), but clicking on it would not progress the main slideshow at all! With no JS errors in the console and nothing obviously wrong, cue the debugging rabbit hole....

Going deeper

I won't go into too much detail here of all the paths I went down whilst debugging this but needless to say it involved swapping out the usually minified version of the Slick plugin for the non minified version, using the excellent Chrome JS debugger and stepping through exactly what was going on when Slick was trying to set this carousel up and why it was behaving like it was.

After a while, I finally realised the issue was present when Slick had started initialising itself - after invoking the plugin in the site's code - but before finishing setup. During it's setup, something was going wrong internally with the reference to the slides, which meant they were not copied into the slick-track div and the previously mentioned (new) wrapping divs were there in the DOM, but with no classes on at all.

The JS debugging revealed that the number of $slides being returned from the following Slick code was actually zero!

_.$slides =
  _.$slider
    .children( _.options.slide + ':not(.slick-cloned)')
    .addClass('slick-slide');

This meant the rest of the code that would then do the copying of the slides into the slick-track div (amongst other setup procedures) was failing. But - how could this possibly be? because running some debug code before initialising Slick and checking the number of slides in the DOM was correct...

The devil is in the detail here, and it turns out that the children() selector here is no longer matching my slide container children. But if we didn't change anything about the code that invokes the carousel, why exactly is it broken?

The key lies in the (optional) slide parameter for Slick (which controls the element query to find the slide). The working vertical carousel (amongst others that were working) wasn't using the slide parameter (as the DOM structure for that carousel has the children directly below the slide container), but the broken carousel was using it (due to a specific reason which I won't get into too far into the exact details of, but it involves other markup in the DOM at that specific place for another purpose on the site, so hence needing to specify the selector).

It turns out that if you omit the slide parameter, internally it'll use > div as the selector for slide , and (obviously) if you specify a selector, it'll use that. Because the previous code we had invoking Slick had specified a custom selector, and now (as mentioned above) there were two extra wrapping divs in play, the Slick selector .children( _.options.slide + ':not(.slick-cloned)') was not matching anymore, as my targets for the slide are now inadvertent grandchildren! and after explicitly defining a selector that wasn't the default (> div), it no longer matched.

The real question?

But why are there now two wrapping <div> elements around each slide where previously there were not?

This is the real question that needs answering, now that we understand why the selector wasn't working during the setup for the slides themselves.

By default, Slick has a default setting for the rows of a slideshow of 1 (unless overridden when invoking the plugin). There is internal code inside of Slick in a buildRows() function (called during initialisation of the carousel) that checks if the number of rows is > 0, and if so, it wraps the inner slides in these two divs!

Slick.prototype.buildRows = function() {

    var _ = this, a, b, c, newSlides, numOfSlides, originalSlides,slidesPerSection;

    newSlides = document.createDocumentFragment();
    originalSlides = _.$slider.children();

    if(_.options.rows > 0) {

        slidesPerSection = _.options.slidesPerRow * _.options.rows;
        numOfSlides = Math.ceil(
            originalSlides.length / slidesPerSection
        );

        for(a = 0; a < numOfSlides; a++){
            var slide = document.createElement('div');
            for(b = 0; b < _.options.rows; b++) {
                var row = document.createElement('div');
                for(c = 0; c < _.options.slidesPerRow; c++) {
                    var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c));
                    if (originalSlides.get(target)) {
                        row.appendChild(originalSlides.get(target));
                    }
                }
                slide.appendChild(row);
            }
            newSlides.appendChild(slide);
        }

        _.$slider.empty().append(newSlides);
        _.$slider.children().children().children()
            .css({
                'width':(100 / _.options.slidesPerRow) + '%',
                'display': 'inline-block'
            });

    }

};

A quick check of setting rows to 0 in the carousel settings confirmed this was indeed the overall problem, and immediately, my carousels looked and behaved in the way they did before the update. The rows setting is designed for when putting Slick in a "grid mode" where you specify how many rows you want and also how many slides per row you want with the slidesPerRow parameter.

But why are most of the carousels now getting their slides wrapped in rows due to buildRows(), even if I haven't changed the rows parameter from its previous default of 1?

There is a slight confusion when looking at the documentation for the plugin, as it specifies the default value is 1, but also specifies "Setting this to more than 1 initializes grid mode. Use slidesPerRow to set how many slides should be in each row." But this is clearly not true, as we can see a commit that is present in the previous version we were using (1.8.1) had changed this check from if(_.options.rows > 1) to if(_.options.rows > 0) without having updated any of the documentation to say so.

... or is it? The final "gotcha" was that after comparing the minified JS provided in release 1.8.1 with the non-minified JS... the minified JS of 1.8.1 does indeed check if rows > 1, not rows > 0, but the non-minified code checks if rows > 0 - so they don't match, doh! 🤦

Minified code excerpt:

l.options.rows > 1) {

Non-minified code excerpt:

if(_.options.rows > 0) {

The master branch commit I'm running for the jQuery fixes correctly has the minified code matching the un-minified code, both checking rows > 0 - consistency, yey!

What a facepalm moment, eh?

TLDR - The solution:

After running either the updated Slick module code on a Drupal 11.x site that uses jQuery 4.x (or an un-minified 1.8.1 release on an older Drupal site running jQuery 3.x!) If you don't want your carousels to get the extra wrapping divs, which can cause serious selector issues (when you don't really need the 'grid mode' at all!) just pass rows: 0 as an option when initialising your Slick carousel along with the other options, and it'll behave as it did before.

e.g. (a super basic carousel options initialisation)

$('.some-carousel-selector').slick({
  arrows: true,
  dots: true,
  slidesToShow: 3,
  slidesToScroll: 3,
  rows: 0, // <-- This is the key if you don't need the grid mode!
});

If you've made it this far through the article, well done! Hopefully this article saves you from the same few hours of pain that I experienced!

Final thoughts

In hindsight, the amount of time it took to work out exactly what was going on here and write this article up, I could have probably spent getting most of the carousels working with an entirely different plugin and pretty much most of the way there. What should have been a 15-minute job here turned into hours, but sometimes these unexpected things just happen when doing upgrades, especially when some of the code being used is from a different era (2017 wasn't that long ago, was it?) It's sometimes a tricky choice to know when to leave legacy code in place, try and make it work or when it's time to jump ship to another solution.

If it turned out that there were a multitude of Javascript errors with the Slick plugin under jQuery 4.x and no obvious solutions without knowing the inner workings of the plugin, then I probably would have changed tact and started re-implementing the carousels with another solution. But this wasn't the case here, and the issues turned out to be a lot more nuanced.

On the plus side, another project that also needs a Drupal 11 upgrade also uses Slick carousel from a long time ago, so it really should be a 15-minute job on that one with the knowledge gained here :)

20 Feb 2026 11:02am GMT

Très Bien Blog: Dig for gold in Drupal Contrib code

Dig for gold in Drupal Contrib code

Fixing the contrib code search problem.

theodore

20 Feb 2026 2:49am GMT

19 Feb 2026

feedDrupal.org aggregator

Dries Buytaert: A better way to follow Drupal development

I've been reading Drupal Core commits for more than 15 years. My workflow hasn't changed much over time. I subscribe to the Drupal Core commits RSS feed, and every morning, over coffee, I scan the new entries. For many of them, I click through to the issue on Drupal.org and read the summary and comments.

That workflow served me well for a long time. But when Drupal Starshot expanded my focus beyond Drupal Core to include Drupal CMS, Drupal Canvas, and the Drupal AI initiative, it became much harder to keep track of everything. All of this work happens in the open, but that doesn't make it easy to follow.

So I built a small tool I'm calling Drupal Digests. It watches the Drupal.org issue queues for Drupal Core, Drupal CMS, Drupal Canvas, and the Drupal AI initiative. When something noteworthy gets committed, it feeds the discussion and diff to AI, which writes me a summary: what changed, why it matters, and whether you need to do anything. You can see an example summary to get a feel for the format.

Each issue summary currently lives as its own Markdown file in a GitHub repository. Since I still like my morning coffee and RSS routine, I also generate RSS feeds that you can subscribe to in your favorite reader.

I built this to scratch my own itch, but realized it could help with something bigger. Staying informed is one of the hardest parts of contributing to a large Open Source project. These digests can help new contributors ramp up faster, help experienced module maintainers catch API changes, and make collaboration across the project easier.

I'm still tuning the prompts. Right now it costs me less than $2 a day in tokens, so I'm committed to running it for at least a year to see whether it's genuinely useful. If it proves valuable, I could imagine giving it a proper home, with search, filtering, and custom feeds.

For now, subscribe to a feed and tell me what you think.

19 Feb 2026 4:14pm GMT

The Drop Times: Florida DrupalCamp Begins 20 February in Orlando with Canvas and AI in Focus

Florida DrupalCamp 2026 opens 20 February in Orlando with a program centered on Drupal Canvas 1.0 and AI-focused training. In a conversation with The Drop Times, organiser Mike Herchel outlined the Canvas-heavy agenda, hands-on workshops, lightning talks, and the camp's long-standing contribution culture.

19 Feb 2026 3:21pm GMT

Talking Drupal: TD Cafe #015 - Karen & Stephen - Non-Profit Summit at DrupalCon

Join Karen Horrocks and Stephen Musgrave as they introduce the upcoming non-profit summit at DrupalCon 2026 in Chicago. In this comprehensive fireside chat, they explore how AI can be integrated to serve a nonprofit's mission, plus the dos and don'ts of AI implementation. Hear insights from leading nonprofit professionals, learn about the variety of breakout sessions available, and discover the benefits of Kubernetes for maximizing ROI. Whether you're a developer, content editor, or a strategic planner, this session is crucial for understanding the future of nonprofit operations with cutting-edge technology.

For show notes visit: https://www.talkingDrupal.com/cafe015

Topics

Stephen Musgrave

Stephen (he/him) is a co-founder, partner and Lead Technologist at Capellic, an agency that build and maintains websites for non-profits. Stephen is bullish on keeping things simple - not simplistic. His goal is to maximize the return on investment and minimize the overhead in maintaining the stack for the long term.

Stephen has been working with the web for over 30 years. He was initially drawn to the magic of using code to create web art, added in his love for relational databases, and has spent his career building websites with an unwavering commitment to structured content.

When Stephen isn't at his desk, he's often running to and swimming in Barton Springs Pool, getting a bit too wound-up at Austin FC games, and playing Legos with his little one.

Karen Horrocks

Karen (she/her, karen11 on drupal.org and Drupal Slack) is a Web and Database Developer for the Physicians Committee for Responsible Medicine, a nonprofit dedicated to saving and improving human and animal lives through plant-based diets and ethical and effective scientific research.

Karen began her career as a government contractor at NASA Goddard Space Flight Center developing websites to distribute satellite data to the public. She moved to the nonprofit world when the Physicians Committee, an organization that she supports and follows, posted a job opening for a web developer. She has worked at the Physicians Committee for over 10 years creating websites that provide our members with the information and tools to move to a plant-based diet.

Karen is a co-moderator of NTEN's Nonprofit Drupal Community. She spoke on a panel at the 2019 Nonprofit Summit at DrupalCon Seattle and is helping to organize the 2026 Nonprofit Summit at DrupalCon Chicago.

Resources

Nonprofit Summit Agenda: https://events.drupal.org/chicago2026/session/summit-non-profit-guests-must-pre-register Register for the Summit (within the DrupalCon workflow): https://events.drupal.org/chicago2026/registration Funding Open Source for Digital Sovereignty: https://dri.es/funding-open-source-for-digital-sovereignty NTEN's Drupal Community of Practice Zoom call (1p ET on third Thursday of the month except August and December): https://www.nten.org/drupal/notes Nonprofit Drupal Slack Channel: #nonprofits on Drupal Slack

Guests

Karen Horrocks - karen11 www.pcrm.org Stephen Musgrave - capellic capellic.com

19 Feb 2026 12:00pm GMT