Editorial cover graphic with component infrastructure motif in gold on cream.

Drupal 11 and the component-first front-end

Drupal 11 completes the infrastructure for component-first theming. What that actually means for how you build.

I spent a day last month rebuilding a Drupal 10 theme into Drupal 11 to see what actually changed for component work. The obvious changes are there — deprecated functions removed, API cleanups, single Directory Components more polished. The thing that struck me was subtler: Drupal 11 assumes you are building components. Not as an option, not as an advanced pattern. As the foundation.

This is not because the Drupal team suddenly decreed that component-first is the only way. It is because Drupal 11 removed enough boilerplate, clarified enough APIs, and made enough patterns explicit that building Drupal themes in any other way now feels quaint.

The infrastructure shift

In Drupal 10, you could build component-first themes using Single Directory Components, but it felt like going against the grain. The core preprocess system was still the primary mental model. SDC was an alternative. The docs assumed you were building traditional Drupal templates.

Drupal 11 inverts that. SDC is the preferred path. The component model is the default. When you create a theme, the assumption is that you are building discoverable, isolated components with defined props — not building templates that Drupal will decorate.

This is not a breaking change. Traditional theming still works. But the gravity has shifted. New developers will find the component path clearer. The examples assume components. The tooling supports components. An old-school preprocess function still runs fine, but it now reads like a legacy pattern.

The practical impact shows up immediately when you start a new theme. Instead of creating a template directory and a preprocess file, you create a components directory with component.yml files alongside your Twig templates. The autodiscovery works. The registry picks them up. A component that lives in components/card/card.component.yml is automatically available as <Card /> in any Twig template.

What props actually mean now

Drupal 10 introduced typed props in SDC files through YAML schemas. Drupal 11 made that schema validation pervasive. When you render a component with props that do not match the schema, Drupal warns you at runtime.

components/card/card.component.yml
$schema: "https://git.drupalcode.org/project/drupal/-/raw/11.0.x/core/modules/sdc/schema.json"
name: Card
props:
schema:
type: object
properties:
title:
type: string
description: The card's title
excerpt:
type: string
description: A short excerpt, max 150 characters
image:
type: object
properties:
src: { type: string }
alt: { type: string }
required: [src, alt]
metadata:
type: object
properties:
author: { type: string }
date: { type: string }
additionalProperties: false

This seems like extra work — why write YAML schemas when you could just pass data? The reason is that a component with a typed schema is not just code, it is a contract. The tooling can now lint against it. An editor passing the wrong data structure gets told immediately instead of six months later when a template breaks on a missing key.

For a multisite platform where five teams are building on a shared component library, that contract becomes foundational. A component can say “I need an excerpt that is a string, maximum 150 characters.” A site that passes a node object gets a build warning instead of silently truncating at the wrong place.

How this changes integration

In Drupal 10, integrating a component into the broader site meant writing preprocess functions to bridge the gap between Drupal’s data structures and the component’s expectations. A component that needed an excerpt had to get that excerpt extracted from a node in preprocess, because the template itself did not have that context.

Drupal 11 makes that integration more explicit. A component declares what it needs. The site-wide integration layer (which could be a preprocess function, a view controller, a Twig filter, or a field formatter) translates Drupal data into that shape.

src/Preprocess/ArticleCardPreprocess.php
// Old pattern: preprocess does everything
public function preprocessArticleCard(&$variables) {
$node = $variables['node'];
$variables['title'] = $node->getTitle();
$variables['excerpt'] = $this->truncateText($node->body->value, 150);
$variables['image'] = $this->processImage($node->field_image);
$variables['metadata'] = [
'author' => $node->getOwnerId(),
'date' => $node->getCreatedTime(),
];
}
// New pattern: preprocess maps Drupal data to component props
public function preprocessArticleCard(&$variables) {
$variables['card'] = $this->mapNodeToCardProps($variables['node']);
}
// The component defines what it needs
// properties: title, excerpt (max 150), image (with alt), metadata

The benefit is that the mapping logic is now isolated. A developer can read the component schema and understand exactly what the integration layer needs to provide. The component is not magical — it does not introspect the node and figure out which field is the image. The integration layer translates explicitly.

What still requires decisions

The one thing that Drupal 11 does not solve — because it is a scaling problem, not an API problem — is how to handle variation in components across a multisite platform. A component for a “featured article” might need different styling on the homepage than in a sidebar. One site might want featured articles to be clickable overlays; another wants them to open in a new tab.

Drupal 11’s component layer is now solid enough that you can build patterns for variation — maybe the component accepts a variant prop, maybe you create separate component variants for different contexts. But the decision about which pattern to use is still architectural. There is no one right answer, and choosing the wrong one will haunt you for years.

# Option 1: variants as props
properties:
variant:
type: string
enum: [default, overlay, tab]
# Option 2: separate components per context
# components/featured-article-homepage/
# components/featured-article-sidebar/

I think the strongest implementations will use composition at the page level (a featured-article-hero contains a card component, a call-to-action, and an image group) and variation within components only for styling, not for structural changes. But that is architectural guidance, not something the framework enforces.

Drupal 11 gives you the tools to build well. It does not guarantee that you will.