Themes
Theme scaffold is an example of a Drupal theme.
We recommend creating a custom your_site_theme theme for your project to place
custom styling and front-end features specific to your site.
The theme uses the site machine name convention (your_site_theme in this case),
while modules use the abbreviated prefix (ys_ for your_site).
We understand that front-end theming is often highly project-specific and
subject to team preferences. The provided your_site_theme scaffold isn't
intended to dictate how your theme should be built - it demonstrates how
custom themes can integrate with the Vortex tooling and automations.
Feel free to adapt or replace it with your preferred theme.
Build system
The theme includes a complete Node.js-based build system composed of npm
scripts over Sass, PostCSS
with Autoprefixer, Terser, and
chokidar:
- SCSS compilation
- JavaScript concatenation and minification
- CSS auto-prefixing for browser compatibility
- Linting for both CSS (Stylelint) and JavaScript (ESLint)
- Watch mode for development
Build commands
cd web/themes/custom/your_site_theme
# Install dependencies
npm ci
# Build production assets
npm run build
# Build development assets (unminified)
npm run build-dev
# Run linting
npm run lint
# Auto-fix linting issues
npm run lint-fix
# Watch for changes during development
npm run watch
Ahoy commands are configured to call the appropriate npm scripts from the theme directory:
# Install front-end dependencies
ahoy fei
# Build production assets
ahoy fe
# Build development assets (unminified)
ahoy fed
# Watch for changes during development
ahoy few
# Lint front-end code
ahoy lint-fe
# Fix front-end lint issues
ahoy lint-fe-fix
These commands run within the container to use the Node.js environment and tools installed there, ensuring consistency across development environments.
When adding your own theme with a custom build system, it's a good idea to follow the same command structure and naming conventions. This keeps things consistent across projects and makes it easier for other developers to work with the build system without learning a new process.
File structure
The main directories and files (build outputs, lint configuration files, and static assets are trimmed for brevity):
your_site_theme/
├── .storybook/ # Storybook configuration
│ ├── main.js # Story sources and framework
│ └── preview.js # Story render endpoint
├── components/ # Single Directory Components (SDC)
│ └── button/ # Sample button component
│ ├── button.component.yml # Component schema (props and slots)
│ ├── button.twig # Component template
│ ├── button.stories.twig # Component stories
│ └── button.css # Component styles
├── scss/ # Sass source files
│ ├── _variables.scss # Theme variables
│ ├── _mixins.scss # Sass mixins
│ ├── _fonts.scss # Font definitions
│ ├── _rem.scss # REM unit utilities
│ ├── styles.scss # Main stylesheet
│ └── components/ # Component-specific styles
│ └── _header.scss # Header component styles
├── js/ # JavaScript source files
│ └── your_site_theme.js # Main theme JavaScript
├── templates/ # Twig template overrides
│ └── layout/
│ └── region--footer-bottom.html.twig # Renders the button component
├── tests/ # Theme tests
│ └── src/
│ ├── Unit/ # Unit tests
│ ├── Kernel/ # Kernel tests
│ └── Functional/ # Functional tests
├── your_site_theme.info.yml # Theme definition
├── your_site_theme.libraries.yml # Asset libraries
├── your_site_theme.theme # Theme functions
├── package.json # Node.js dependencies
└── logo.svg # Theme logo
Libraries
The theme defines asset libraries in your_site_theme.libraries.yml for
organized CSS and JavaScript loading with proper dependencies and browser
compatibility.
Single Directory Components
The theme ships a sample Single Directory Component
(SDC) in components/button and uses it from
templates/layout/region--footer-bottom.html.twig to render a "back to top"
link, demonstrating real component usage from a template.
Components are validated with SDC Devel:
ahoy lint-sdc
➡️ See SDC Devel for how the validator is set up and where it runs.
Storybook
Storybook documents the theme's components and is enabled by selecting it during installation. Drupal renders every story through the Storybook module, so the library shows the same markup the site renders.
Stories are authored in Twig next to the component they document, as
<component>.stories.twig, and compiled into <component>.stories.json by
Drush. The compiled files are generated artifacts and aren't committed.
Commands
# Start the development server on port 6006
ahoy storybook
# Generate the stories from the Twig sources
ahoy storybook-stories
# Build the static application
ahoy storybook-build
The development server runs inside the CLI container and reaches Drupal through
the STORYBOOK_DRUPAL_URL variable, which ahoy storybook sets to the local
site URL.
Published component library
Provisioning generates the stories, builds the static application and publishes
it into the public files directory, where the web server serves it at
/storybook. This runs in the local, ci, and dev environments only, which
are the environments where the story render route is reachable. Set
DRUPAL_STORYBOOK_SKIP=1 to skip the build and shorten provisioning.
The web server configuration in .docker/config/nginx/storybook.conf expects
the public files directory at its default location, sites/default/files.
Adjust the alias if the project overrides DRUPAL_PUBLIC_FILES.
Tests scaffold
The tests directory contains working examples of tests that can be used as a
starting point in your project.
It also has a set of helper Traits that you may find useful when writing your
tests. Remove them if you don't need them.