Drupal

Drupal single-directory components on production catalogues

Drupal

Drupal single-directory components are how I ship reusable Twig, CSS, and JavaScript on Drupal 11 catalogues without losing track of which library belongs to which card or teaser. I am Alan Vo, a Gold Coast web developer with 18 years on museum, regulator, and property Drupal builds. In 2026 SDC is part of core's render system from Drupal 10.3 onward, Drupal 11.2 added native variants, and the official docs still treat schemas as mandatory for module components and strongly recommended everywhere else. This note is for teams who already theme in Twig but want a production checklist before components/ spreads across every custom module.

The topic pairs with Drupal Canvas vs Layout Builder in 2026 when merchandisers need page-level flexibility while developers keep atoms consistent, and with Drupal CMS recipes for faster site builds when a recipe ships a starter theme you plan to extend. Background is in the Single-Directory Components overview, creating a component, and using a component in render arrays.

Why Drupal single-directory components matter in 2026

Drupal single-directory components matter in 2026 because core integrated them into the render pipeline, design systems expect variant shortcuts, and catalogue sites still mix custom modules, contrib formatters, and a single custom theme. Before SDC I saw CSS duplicated across three Twig templates, JavaScript loaded globally because nobody remembered which node type needed the slider, and block plugins that copied markup from a partial. SDC colocates my-component.twig, my-component.component.yml, and optionally my-component.css and my-component.js under components/my-component/, so asset discovery matches what editors see on the page.

Drupal 11.2.0 added first-class variants in the component YAML so authors can document primary versus secondary (or similar) without faking variants as untyped props. The 11.2.0 release announcement describes that as design-system alignment. For production catalogues the payoff is predictable overrides: only themes can replace another provider's component with the replaces key, and both sides need matching schemas, which stops silent drift between a base module card and a brand theme.

SDC is not a replacement for Layout Builder, Canvas, or Views. It is the layer beneath them where buttons, chips, product teasers, and alert banners stay consistent when fifty content types share the same visual language.

How Drupal single-directory components work in core

Drupal single-directory components work when a folder under your module or theme's components/ directory contains the required pair: name.component.yml and name.twig (note .twig, not .html.twig, per the creating a component guide). CSS and JS with the same basename attach automatically; extra dependencies go in libraryOverrides inside the YAML.

Drupal single-directory components documentation open beside a laptop

The component ID is provider:machine_name, for example olivero:chip or my_catalog:product-teaser. From PHP you render with a render element:

``php return [ '#type' => 'component', '#component' => 'my_catalog:product-teaser', '#props' => [ 'title' => $node->label(), ], '#slots' => [ 'media' => $media_build, ], ]; ``

On Drupal 11.2 and newer you may pass #variant when the YAML declares variants. From Twig, include or embed with the same provider:component string works when a render array is awkward, as documented under using your new single-directory component.

Schemas use JSON Schema types mapped to PHP and Twig. Module authors must ship schemas; themes may omit them but then cannot participate in replaces overrides. Validation during development needs drupal/core-dev (for justinrainbow/json-schema) and assertions enabled, typically ini_set('zend.assertions', 1) in local settings.php as described in the same creating guide. Production does not run those assertions for every request, but CI that builds with dev dependencies can catch invalid props before deploy.

Themes override module components by setting replaces: 'module:component' in the theme component YAML with compatible props and slots. Modules cannot override other modules that way, which keeps dependency direction clear on multi-vendor builds.

Drupal single-directory components production checklist

A Drupal single-directory components production checklist starts with naming, schema discipline, and a decision about where components live (theme only versus shared custom module) before the first merge request lands.

  1. Pick ownership. Put site-specific chrome in the custom theme. Put reusable catalogue widgets in a custom module if another theme or install profile might consume them. Document the rule in your README so contractors do not fork markup.
  2. Require schemas for modules. Every module component gets a complete props and slots schema. For themes, set enforce_prop_schemas: true in themename.info.yml if you want the same rigor.
  3. Standardize IDs. Use kebab-case directory names that match the machine name in YAML. One component per folder; nest components/atoms/ only when the team already thinks in atomic design.
  4. Wire through render arrays in plugins. Prefer #type => component in block build(), formatter viewElements(), and layout plugins so cache metadata and attachments stay correct. Reserve raw Twig include for templates that already own the render tree.
  5. Plan variants in 11.2+. Define variants in YAML with human titles and descriptions, then pass #variant or the Twig variant key instead of a loose string prop that duplicates design tokens.
  6. Asset budget. Named CSS and JS files load per component usage. Audit after migration from global libraries so LCP and INP do not regress when a listing page renders twenty teasers.
  7. Override path. If the brand theme replaces a module component, test that replaces still matches after a module upgrade changes schema. Pin a visual regression snapshot for one catalogue row and one detail hero.
  8. Enable SDC on older cores. Drupal 10.2 and earlier need the Single-Directory Components module enabled manually; 10.3+ treats it as part of the render system. Confirm core_version_requirement in custom code matches what you support.
  9. Export and deploy. Components ship as code in git, not configuration. Deploy with the same pipeline as theme and module updates; run update hooks if you rename component machine names.
  10. Editor-facing surfaces. When Canvas or Layout Builder blocks should expose component props, confirm whether your stack auto-generates forms from schemas yet or still needs custom block forms. Do not promise WYSIWYG parity until you test on staging.
Team workshop around a table planning a CMS rebuild

What breaks with single-directory components on live sites

What breaks with single-directory components on live sites is usually schema mismatch and asset duplication, not mysterious core bugs. Renaming a prop in YAML without updating every #props array yields validation failures in dev and subtle empty output in prod if assertions are off. Forgetting that only themes may use replaces leads to a module override that core ignores. Mixing .html.twig naming in components/ breaks discovery; the docs explicitly require .twig in the component folder.

Nested components that each ship JavaScript can multiply bytes on dense Views. A product grid that renders twelve SDC rows with twelve copies of the same behavior file hurts INP unless you refactor shared behavior into a parent library or a single initializer with event delegation.

Layout Builder sections that still use legacy template overrides may bypass SDC entirely, so editors see new components in Storybook-style demos but old markup on listing pages until you wire formatters or view modes to the render element. Multilingual sites must confirm translated strings pass through #props as translatable markup where needed; hard-coded English in PHP props shows up in every locale.

Upgrading from Drupal 10.2 without enabling the feature module first produces "component not found" errors that look like deployment failure. Patch 11.x minors can add schema requirements; read release notes before July production freezes.

Library stacks used as a stand-in for structured content

How to measure SDC adoption on a catalogue

How to measure SDC adoption on a catalogue is a mix of front-end weight, defect rate, and theming velocity, not a single Google Analytics event. I compare Lighthouse or WebPageTest on a representative listing before and after moving teasers into SDC, with the same cache warm and the same number of rows. I track kilobytes of CSS and JS attributed to the theme aggregate and watch for duplicate rules in coverage reports.

In the issue queue I tag tickets "SDC" when the fix touches components/. Velocity improves when designers can point to one folder per widget; measure median time to ship a new teaser variant before and after the migration quarter.

For accessibility, run axe or equivalent on one instance of each variant after a schema change. Variants that only swap CSS classes still need correct heading order and focus states in each Twig template.

Pair measurement with Drupal Search API on production catalogues sanity checks: search results templates are a common place SDC lands first, so search CTR and zero-result rates should not move because markup wrappers changed class names crawlers relied on.

Drupal single-directory components sit on the same sites where I already document JSON and admin UX. Royal Ontario Museum scale collections benefit when exhibition teasers share one SDC with variants for featured versus standard rows. NDIS Commission content-heavy regulator pages need alert and summary components that stay consistent across dozens of content types. Immobel property catalogues mix Drupal content with external commerce; SDC keeps listing cards aligned even when the purchase path leaves Drupal.

When decoupled consumers still exist, read How to ship Drupal JSON:API on production catalogues for read APIs; SDC remains the right tool for the themed HTML channel, not a substitute for JSON shapes.

FAQ

Are Drupal single-directory components stable for production in 2026?

Drupal single-directory components are production-ready on Drupal 10.3 and newer because core folded them into the standard render system, and Drupal 11.2 added variants without marking the API experimental. Treat schemas, asset loading, and theme overrides as contract code you test on staging each minor upgrade. Sites stuck on 10.2 must enable the feature module explicitly before relying on SDC in custom modules.

Must every Drupal single-directory component define a schema?

Module-provided Drupal single-directory components must define a schema in *.component.yml; themes may omit schemas but then cannot override other providers with replaces and lose early validation benefits. I recommend enforce_prop_schemas: true on custom themes so contractors get the same errors locally that CI catches. Schemas also map JSON Schema types to Twig expectations, which reduces blank slots when a formatter passes the wrong shape.

Government-style office desks and screens

When should I use #type => component versus Twig include?

Use #type => component from plugins and controllers when Drupal should manage cache contexts, attachments, and render bubbling the same way as other render arrays. Use Twig include or embed inside templates when you are already in Twig and only need a static partial without extra metadata. For shared catalogue widgets invoked from both a block and a formatter, standardize on the render element so behavior stays identical.

How do Drupal single-directory components interact with Layout Builder and Canvas?

Drupal single-directory components supply the atomic markup and assets that Layout Builder sections, custom blocks, and Canvas layouts compose into pages. They do not replace drag-and-drop placement. Wire blocks and view modes to SDC via render arrays so editors still arrange sections in the UI while developers own props, slots, and variants in git. When Canvas stores layout JSON separately, document which components each block plugin expects so exports stay portable.

Editor typing in a CMS during Drupal single-directory components work

Keep reading

Contact if you want this kind of work on a live store.