The Drop Times: DXPR’s “Baby AI” Redefines Content Creation with Free AI Access for Drupal Users

DXPR Builder 2.7 introduces “Baby AI,” a free and integrated AI platform for Drupal, combining GPT-4o, Gemini, Claude, and other top models. Built to streamline content workflows without extra cost, DXAI gives developers and editors powerful tools to write, edit, and refine directly inside the CMS.

Drupal Association blog: Let’s support a pillar of Open source

Open source projects thrive because of the people and institutions that nurture it behind the scenes empowering innovation, collaboration, and digital freedom. One impactful institution is the Oregon State University Open Source Lab (OSL). The Drupal community owes much of our success and growth to Open Source Lab when they supported the project in 2005 by hosting our servers.

Today, OSL needs our support.

About Open Source Lab

The Oregon State University Open Source Lab is a nonprofit organization with a powerful legacy in the open source ecosystem. For years, it has provided secure, reliable hosting services to some of the most widely used and mission-critical open source projects like Apache, CentOS, Debian, Django, Docker, Eclipse, Mozilla Firefox, GNOME, Go, KDE, Node.JS, OpenBSD, OpenSSL, postgreSQL, Rust, sqlite, The Tor Project, Yum, and yes, Drupal.

Open Source Lab helped shape Drupal’s journey

In 2005, when a surge of interest melted down the shared server that was being used by Dries to host Drupal.org, Sun Microsystems donated a server but there was nowhere to host it. Open Source Lab stepped forward providing managed data center services, offering not only hosting but also long-term support through its student mentorship model. This commitment shaped the careers of many open source leaders, including former Drupal Association Infrastructure Manager Rudy Grigar and current Infrastructure Manager and Tag1 CTO Narayan Newton, both Open Source Lab alums. 

While the Drupal Association has now moved to a hybrid cloud architecture, we still operate some critical infrastructure at the Open Source Lab, including pre-production environments, mail transport, and legacy systems that are still mid-migration, and will be repurposed for things like our testing infrastructure. It is our hope for Drupal to continue to be present at the Open Source Lab for years to come.

A Critical Moment for Open Source Lab

In recent years, the Open Source Lab has faced a steady decline in corporate donations, leading to an operational deficit. Today the Open Source Lab is under threat, placing Open Source Lab’s future in jeopardy.

Unless they secure $250,000 dollars in commitments by 14 May 2025 they will have to close their doors.

If Open Source Lab shuts down, we lose a backbone of the open source world and a value-driven infrastructure provider. It would ripple across dozens of projects and thousands of contributors, setting back years of progress and community building.

Together, we can keep Open Source Lab alive

This is an opportunity for all of us to come together to support an unsung pillar of open source.

Here’s how you can help:

  • Your donations are vital to keep this precious resource for the public good open. Consider making a donation to support Open Source Lab’s future. Donate today.

  • If you are able to make a major gift, you can also reach out to: donations@osuosl.org 

  • Help raise awareness by sharing this post within your network and with anyone you think could help support Open Source Lab.

The Open Source Lab has played an important role in supporting the open source community, now it’s our turn to give back. By contributing today, you’re helping secure the future of open source innovation and sustaining essential digital infrastructure. It's time to come together to ensure the Open Source Lab’s legacy continues to thrive.

Golems GABB: Functional testing on DDEV Selenium Standalone Chrome

Functional testing on DDEV Selenium Standalone Chrome Editor Mon, 05/05/2025 - 11:42

DDEV has really changed the game for developers by making it easier to set up local development environments in no time! When you team it up with the amazing automation features of Selenium, you get a powerful duo for doing thorough functional tests. In this article, your favorite Drupal development team looks at how this combination can boost your development efficiency and enhance the quality of your projects.

The Drop Times: DrupalCamp Ouagadougou 2025 Builds Momentum for Drupal Community in West Africa

DrupalCamp Ouagadougou 2025, organized by the Drupal Burkina Faso Association, brought together developers, students, and digital professionals to promote Drupal as a key platform for digital transformation in West Africa. With over 500 interested participants and 177 confirmed attendees, the event featured training sessions on Drupal CMS, AI integration, and site-building workflows. It also served as a platform for discussing the future of Drupal in Africa, including plans to host the first DrupalCon on the continent. Despite limited resources, the camp highlighted strong community engagement, growing interest in open-source technology, and the potential for Drupal to support local capacity-building and digital sovereignty.

Mario Hernandez: Understanding The Owl Selector

With all the advancements in CSS over the past few years, it's surprising to discover a technique that's been available all along. If you're well-versed in CSS, you might already know this little nugget: selector > * + * {...}. Let's dive into it.

Lobotomized Owls 🦉 🦉

The Lobotomized Owl (* + *), or Owl selector, is one of my favorite techniques for managing document flow and achieving consistent spacing in a highly manageable way. While the Owl selector can be used for various style settings, my preferred use is to add spacing between sibling elements.

How does the Owl selector work?

The Owl selector targets elements that are preceded by an immediate sibling. This means that if you apply the Owl selector to a group of HTML elements, the styles will apply to all elements except the first one, as the first one doesn't have a preceding sibling. We'll see some examples shortly.

The Lobotomized Owl isn't a new CSS concept; it's been around since the beginning of CSS and was first discussed back in 2014 when A List Apart wrote about it. Read that article for a more in-depth description of the Owl selector.

Understanding the Owl selector

Concept

The Owl selector allows you to manage the document flow by using the next sibling combinator (+), along with the universal selector (*).

Example

Consider the following HTML:

<div class="parent"> <div class="child"></div> <div class="child"></div> <div class="child"></div> <div class="child"></div> </div>

Scoping the Owl selector

Using the Owl selector in its original form (* + *), could result in unexpected updates due to its broad scope. Narrowing the scope is prefered.

Chaining the Owl selector with .parent >:

.parent > * + * { margin-block-start: 2rem; }

Nesting it within .parent along with other rules that may exist:

.parent { /* other rules here. */ > * + * { margin-block-start: 2rem; } }

By narrow the scope as shown above, and using the child selector (>), a 2rem top margin is added to "direct" children of .parent, but only if they have a preceding sibling.

Visual example

A more visual representation of what the CSS is doing can be seen here:

Image removed.

FIG 1: Each white box represents a div while the purple boxes represent top margin.

Instead of writing styles, we’ve created a style axiom: an overarching principle for the layout of content flow. - Heydon Pickering.

Traditional approach for handling margin

In the past I would do something like this to handle margin on a group of elements.

.my-list { li:not(:first-child) { border-block-start: 1px solid #000; } }

That's not terribly bad, but the problem with this approach is that it increases the specificity of the rule, which could complicate overrides.

Before :not was a thing, I would also do something like this (please forgive me):

.my-list { li { border-block-start: 1px solid #000; } } .my-list { li:first-child { border: 0; } }

There's nothing wrong with this example except that it's more code and you're overriding rules. Ultimately, it works, so don't feel too bad if you've done this. Just don't do it again 😉. Instead, do this:

.my-list { > * + * { border-block-start: 1px solid #000; } }

A more complex example

The examples above are pretty simple, but in many cases, our HTML may not be as clean or uniform as the examples we've seen. Here's a more realistic example where our markup is a combination of different HTML tags.

<article class="blog-post"> <div class="blog-post__tag"> <a href="#" class="eyebrow">Drupal</a> </div> <header class="blog-post__header"> <h1 class="blog-post__title"> Using modern image formats to improve performance </h1> <p class="blog-post__subtitle"> Small wins, when added up can make a big difference. This is one of those small wins which can result in performance gains for your website.</p> <div class="blog-post__date"> <time datetime="2025-xxx-xx">April 12, 2025</time> </div> </header> <div class="blog-post__share"> <ul class="social-share" role="list"> <li class="social-share__item">...</li> <li class="social-share__item">...</li> <li class="social-share__item">...</li> </ul> </div> <div class="blog-post__content"> ... </div> </article>

The HTML above is actually the code used on each of the blog posts on this site. Let's break it down in an illustration form for a better visual representation.

Image removed.

FIG 2. Illustration of the markup structure of a Blog post.

From the code and FIG 2 above, we notice the following:

  1. The <article> tag is the top parent element with four direct child elements (Tag, Header, Share, and Article content).
  2. The <header> tag is also a parent element itself with three direct child elements (Title, Subtitle, and Date).
  3. There is a mix of HTML tags.

Let's start with the <article> parent selector:

.blog-post { > * + * { margin-block-start: 2rem; } }

The result of this CSS rule is a 2rem top margin on direct sibling children of the .blog-post selector, except the first/top one. I have highlighted in purple how this looks in FIG 3. below:

Image removed.

FIG 3. The purple boxes represent the space added by the CSS above.

Now let's apply the same treatment to the <header>:

.blog-post__header { > * + * { margin-block-start: 2rem; } }

To make it easier to diferentiate, this time I highlighted the margin in direct sibling children of the <header> tag, in blue. See FIG 4. below:

Image removed.

FIG 4. The blue boxes represent the space added by the CSS above.

With very little CSS code we have been able to achieve consistent spacing in direct sibling children of the <article> as well as nested ones inside the <header>. In the spirit of staying DRY, we could even combine both rules to reduce code repitition.

.blog-post, .blog-post__header { > * + * { margin-block-start: 2rem; } }

What if the HTML structure changes?

It's not uncommon for the HTML of a document to change. Some of my blog posts, for example, have subtitle text while others don't. The beauty of the Owl selector is that it doesn't depend on specific HTML tags or structure in your document. If new sibling elements are added or some are removed, the spacing previously defined with the Owl selector will continue to work as intended without breaking the document flow.

What about Gap?

Oh yes, enough about Owls 🦉, Gap is a beautiful thing and can even be used similarly to the Owl selector for adding space in between sibling child elements.

.parent { display: flex; flex-direction: column; gap: 2rem; }

Pros of gap

  • The CSS block above will behave exactly as the Owl technique, as in it will only add space between sibling child elements.
  • Another advantage of using Gap for spacing, is that when it comes to responsive design, the gap rules you apply to elements for mobile, will remain in place as you transition to tablet or desktop. No need to change the gap settings if the direction of your layout has changed. See FIG 5. below.
  • Gap is great for menu lists where you may want to add spacing in between each menu item except the ones at the end.

Image removed.

FIG 5. Visual of Gap on column and row mode.

Cons of gap

If you opt to use Gap for spacing, this means you either need to use display: flex or display: grid on the parent element. This is not a bad thing if you are already using flex or grid on that parent element, but if your only reason for using gap is for spacing purposes, then I would recommend using the Owl technique instead as it requires not additional properties on your parent selector.

In closing

I don't think there has ever been a more exciting time to work with CSS than now. The capabilities of CSS and browser support have never been better. Sometimes however, using some of the most basic techniques can make a great impact in our projects.

If you found this post useful, stay tuned for more like it.

Resources

DDEV Blog: DDEV Add-on Maintenance Guide

Image removed.

Introduction

Maintaining a DDEV add-on is more than a one-time task. As DDEV evolves, so should your add-ons. This guide will help you stay in sync with recent changes and keep your add-ons up-to-date, reliable, and aligned with current standards.

As part of preparing this guide, I also updated all official DDEV add-ons to reflect the latest recommendations and improvements.

Recommendations for Add-on Maintainers

Here are some high-level practices to follow:

  • Take inspiration from the official add-ons, see how they're structured and follow similar practices
  • Keep an eye on updates in ddev-addon-template
  • Track changes in DDEV releases
  • Configure your add-on repository settings
  • Add the ddev-get topic to your GitHub repository if it should be discoverable by the wider community. (If your add-on is currently just an experiment or a fork, wait until it matures to add the topic.)
  • Write a clear description and include relevant keywords to improve discoverability
  • Use #!/usr/bin/env bash instead of #!/bin/bash at the top of your command scripts, it's more portable and works better across different environments.
  • Ensure your add-on cleans up after itself: both ddev add-on get and ddev add-on remove should be idempotent. All files added via project_files and global_files must include a #ddev-generated stanza to support proper removal
  • Remember to publish a new release after any update (unless it's just a README.md change)

I'm currently working on a script to streamline the update process. It's a work in progress and available here. I'd appreciate any feedback!

What's New in the DDEV Ecosystem

DDEV development is moving fast, and new features are introduced regularly. Here are some recent updates you should be aware of:

ddev get Deprecation

The classic ddev get command is deprecated in DDEV v1.23.5 and replaced by ddev add-on get.

Huge thanks to @GuySartorelli for implementing this feature, and also for proactively updating many add-on README.md files. You've likely already seen a pull request for your add-on!

Better Testing with Bats Libraries

While all add-ons use the Bats framework for testing, many are still missing Bats libraries that simplify assertions and test writing.

Consider adopting these libraries to enhance test clarity and maintainability.

Example:

Issue and PR Templates

Make sure your add-on includes:

These improve the quality of contributions and bug reports.

Recommending DDEV Version Constraints

Your add-on should encourage users to keep DDEV updated. The current recommendation is to add this stanza to install.yaml:

ddev_version_constraint: ">= v1.24.3"

This ensures compatibility and resolves known issues, such as those related to the Mutagen Problem Report.

Add-on Badges

The old maintained badge required yearly updates, which became a maintenance burden, especially for contributors with many add-ons. It's now replaced by a last commit badge.

To improve visibility and engagement on the DDEV Add-on Registry, add the registry badge to your README.md.

Example:

Advanced Customization with Flags

Starting with DDEV v1.23.5, you can now use ddev dotenv set to manage environment variables more cleanly. This allows your add-on to read custom environment variables defined in .ddev/.env.* files, and use them inside your docker-compose.*.yaml configuration.

This feature is especially useful for advanced setups where flexibility and dynamic configuration are needed.

Example:

Making Small Changes to Docker Images

If your add-on needs a customized Docker image, the typical approach is to create a separate Dockerfile and configure your add-on to use it. However, for minor tweaks, you can take advantage of the dockerfile_inline option in your docker-compose.*.yaml file.

This approach lets you define a small Dockerfile directly in the YAML, avoiding the overhead of maintaining a separate file.

Examples:

MutagenSync Annotation for Commands

With DDEV v1.24.4, custom commands can now use the MutagenSync annotation.

You should use this annotation if your host or web commands modify, add, or remove files in the project directory. It ensures that file sync is handled correctly when Mutagen is enabled, preventing unexpected behavior or sync delays. (It does no harm and causes no performance issues if Mutagen is not in use.)

Example:

Support for Optional Compose Profiles

The same DDEV v1.24.4 release introduced support for optional docker-compose profiles, which can be used by add-ons to offer more flexible configuration.

Example:

Repository Configuration Best Practices

To keep your add-on repository tidy, safe, and aligned with community standards, consider adjusting the following GitHub settings:

General Settings

Go to Settings → General in your repository:

  • Uncheck features you don’t use, such as Wikis, Discussions, and Projects
  • Enable Allow squash merging with Pull request title
  • Disable Allow merge commits and Allow rebase merging
  • Enable Always suggest updating pull request branches
  • Enable Automatically delete head branches

Branch Protection Rules

Go to Settings → Rules → Rulesets:

  1. Click New ruleset → New branch ruleset
  2. Set Ruleset name to main
  3. Under Enforcement status, select Active
  4. Under Targets, click Add target → choose Include default branch
  5. Under Rules, enable:
    • Restrict deletions
    • Require a pull request before merging (set Allowed merge methods to only Squash)
    • Block force pushes
  6. Click Create to apply the ruleset

Conclusion

Keeping your add-on current means less work for users and fewer issues for you to manage. Use this guide as your checklist and stay in sync with the DDEV ecosystem.

Have questions, suggestions, or something cool to share? Join the conversation in our Discord, open an issue, or reach out via email. Your feedback helps improve the tools we all rely on.

If DDEV is helping you or your organization, please consider supporting its ongoing financial sustainability. Every bit helps keep the ecosystem growing and maintained.

Happy maintaining!

DXPR: 2.7 "Baby AI" Is Here: DXPR Builder Delivers Free AI Writing to Every Drupal Site

2.7 "Baby AI" Is Here: DXPR Builder Delivers Free AI Writing to Every Drupal Site Jurriaan Thu, 05/01/2025 - 14:58 Image removed.

In a move to empower the Drupal community, DXPR is providing free access to AI models through the release of DXPR Builder 2.7 “Baby AI.” This initiative allows developers and content creators to leverage the power of advanced AI tools without additional costs or complex integration.

By integrating top vendors including OpenAI's GPT-4o, Google Gemini 2.5 models, Anthropic's Claude 3.7, Grok 3 by XAI, Perplexity AI, and state-of-the-art EU based models by MistralAI. 

DXPR ensures that every Drupal user can experience enhanced content creation and management. This free access underlines our commitment to fostering innovation and creativity within the Drupal ecosystem.

These AI providers are integrated in "DXAI" — our own AI platform that ties it all together to provide superior web content writing capabilities.

Quick Tour of DXAI in CKEditor 5

  1. Slash command: Type /write a blog post about future Drupal 12 release (or any prompt) in an empty paragraph.
  2. Watch it stream: DXAI writes live, so you can stop, continue, or tweak on the fly.
  3. One-click refine: Select any text → choose “Improve clarity”, “Shorten”, “Change tone”, or your custom commands.

"Shown don't Tell" — DXAI in 3 GIFS


1. Adding a new AI text to the DXPR Builder  page

Image removed.

Demo of writing new text in DXPR Builder landing page, the AI is aware of all contents around the new text and therefore requires only a very basic prompt.

 

2. Adding a new AI text to the DXPR Builder  page

Image removed.

Demo of rewriting a text section in a different tone of voice. The tone of voice dropdown is managed with a Drupal Taxonomy.

 

3. Writing a new text from scratch.

Image removed.

The DXAI AI server integrates with state-of-the-art AI providers including Perplexity AI which is used for web research, fact checking, and preventing hallucinations.
 

Where to Configure DXAI

Site builders can enable DXAI under /admin/dxpr_studio/dxpr_builder/ai_settings (run update.php first). Key options:

  • Select primary and fallback AI vendors
  • Set token limits per role
  • Map taxonomy terms to command and tone menus

UI Refresh: Faster, Friendlier, Fully Accessible

2.7 ships a modernized editor chrome with clearer icons, higher contrast, and full keyboard / screen-reader compatibility. Mobile editing is smoother too—perfect for last-minute tweaks on the go.

Improved Drupal 11 Integration

  • Resolved JavaScript crashes in the editor chrome
  • Aligned media dialogs with new core markup
  • Verified compatibility with Drupal 11’s CKEditor 5 update stream

Other Highlights

  • Marquee element: Add scrolling announcements with fade edges and reduced-motion support.
  • Saved templates UI: Filter by layout and see thumbnails at a glance.
  • Inline editing upgrades: Edit buttons, alerts, progress bars, and more without opening popup windows (AI supported everywhere).
  • Drupal Media Library & Acquia DAM integration: Browse all your assets in one place.

How to Get “Baby AI” for Free

  1. composer require 'drupal/dxpr_builder:^2.7'
  2. Grab a free product key—no credit card, free forever for smal sites.
  3. Enable the DXPR Builder AI Agent module and run update.php.
  4. Configure DXAI settings, assign permissions, and start prompting!

Roadmap Sneak Peek

Today’s release is just the first step. Coming soon:

  • One-prompt landing pages: Describe your offer; DXAI designs and writes a complete page in DXPR Builder.
  • Clone from URL / PDF / image: Rebuild existing designs in minutes with structured, editable content.
  • Conversational refinement: DXAI will chat with editors to clarify goals, add citations, and align with strategy.

We Need Your Feedback

Because the AI beta is free, the only thing we ask in return is insight. Share your triumphs, glitches, and wish-list items on the issue queue or in our commercia support system

Ready to Build Smarter Drupal Experiences?

Test the Live Demo  |  Learn More About DXPR Builder

Happy building—and happy writing—with DXPR Builder 2.7 “Baby AI”!

.hover-style-gby4h650fj:hover {}.hover-style-gbwr97fs50:hover .az-image-content{}.hover-style-gb9a5lwwld:hover {}.hover-style-gbfhe9wze0:hover .az-image-content{}.hover-style-gbexyk080u:hover {}.hover-style-gbdk6ko2m4:hover .az-image-content{}.hover-style-gb619n0fmh:hover {}.hover-style-gbl7pspv26:hover {}.hover-style-gbv4lavke5:hover .az-image-content{}.hover-style-gbqh3tz5cv:hover {}

Category

Drupal Layout Builder DXPR Marketing Team

PreviousNext: My journey to becoming a Core maintainer

How do you find your niche and become a Drupal Core maintainer?

by daniel.veza / 1 May 2025

There are still roughly 23 subsystems of Drupal Core without maintainers. These gaps need to be filled. 

While some people may be daunted by this task, rather than trying to learn everything in Core, Daniel explains why it is more valuable to become an expert in one area. This was how he became a Drupal Core maintainer for Layout Builder.

In this video, you will learn about:

  • The steps Daniel took to reach Core maintainership.
  • Why he chose Layout Builder as his niche.
  • How to identify areas in Drupal Core that need maintainers.

Watch the video

Centarro: Revisiting semantic versioning in Drupal Commerce

Drupal modules are primarily maintained in Git repositories controlled by the Drupal Association on Drupal.org. Before the DA added support for semantic versioning in March 2020, our modules had version numbers like 7.x-1.0 or 8.x-2.1, with the first portion identifying Drupal API compatibility and the second identifying the major and minor version of the module.

However, with modern Drupal (Drupal 8+), a module can support multiple major versions so long as it does not depend on any deprecated APIs in Drupal, its dependencies, or PHP itself. Using the Drupal version number in module version numbers means many of our releases that support Drupal 9, 10, or 11 still start with 8.x-, never mind the fact that we don't support Drupal 8 at all any more.

Semantic versioning allows us to use branch names and tag releases for our various modules based on their own lifecycles. We don't need a new branch for each new major version of Drupal, and we can distribute more predictable updates to end users through Composer with major, minor, and patch versions of our modules.

When we first switched to semantic versioning, we created new branches based on the minor version. Thus, we went from an 8.x-2.x branch off of which we tagged releases to a 3.0.x branch. We never quite knew when to tag a patch versus a minor release in this scenario (i.e., 3.0.1 vs. 3.1.0) and created a situation where we'd have more branches to maintain than we really cared to (3.0.x, 3.1.x, 3.2.x, etc.).

We determined instead to start creating branches named only for the major version (3.x, 4.x, etc.) with release tags that still primarily use minor versions (3.0.0, 3.1.0, 3.2.0, etc.). This will permit us to focus on maintaining a single branch for each module until we need to introduce breaking changes while accommodating the occasional need to backport bug fixes to previous minor versions.

Read more