JavaScript frontends,
zero Drupalisms
Frontend developers are about to become first-class citizens. “An experience with no Drupalisms, no tradeoffs,” Dries promises — “I have two videos. Let’s start with the first one, about JavaScript components.”
“JavaScript frontends have been around for ten-plus years. They’ve grown and grown, and honestly, it’s where new engineers out of college or school start their careers.”
“Drupal has been supporting this for some time, but if we’re honest, it hasn’t always been perfect — there have always been a few compromises, a few Drupalisms sneaking through.”
“Thanks to the work of Laurie and Berlint and other people on the Canvas team, we’ve been really focused on treating frontend developers as first-class citizens — no Drupalisms, no tradeoffs.”
Building Modern JavaScript Frontends with Drupal Canvas & Code Components
Modern digital experiences demand dynamic, highly reactive user interfaces powered by standard JavaScript frameworks like React, TypeScript, and Tailwind CSS. Historically, integrating these modern frontend stacks into Drupal required navigating complex decoupled architectures or compromising with Drupal-specific Twig and PHP templating paradigms.
Drupal Canvas introduces Code Components: a developer workflow that eliminates these compromises. It allows frontend engineers to build with pure React, use automated AI coding agents, preview components in a dedicated zero-config workbench, and seamlessly sync everything into Drupal’s visual page builder for content teams.
Architecture Overview
View source diagram
+-----------------------------------------------------------------------+
| FRONTEND CODEBASE (Local) |
| |
| +--------------------+ +--------------------+ +---------------+ |
| | React + TypeScript | | Tailwind / Styling | | npm Packages | |
| +--------------------+ +--------------------+ +---------------+ |
| | | | |
| +------------------------+-----------------------+ |
| | |
| +--------------------------+ |
| | Canvas Workbench (Vite) | |
| | Zero-Config Live Preview| |
| +--------------------------+ |
+-------------------------------------^---------------------------------+
|
npx canvas push / pull
|
+-------------------------------------v---------------------------------+
| DRUPAL CANVAS (Server / CMS) |
| |
| +-----------------------------------------------------------------+ |
| | Visual Canvas Editor | |
| | [Header] [Hero Component] [Pricing Table] [Dynamic Articles] | |
| +-----------------------------------------------------------------+ |
| | Marketers & Content Editors drag, drop, and configure props | |
+-----------------------------------------------------------------------+Key Modules & Tools Covered
@drupal-canvas/create: Project scaffolding CLI.canvas-workbench: A Vite-based local development environment and preview server (an alternative to Storybook tailored specifically for Drupal Canvas).canvas-cli(npx canvas push / pull): Bi-directional synchronization between local code and Drupal.- AI Agent Skills (
.agents/skills/): Integrated workflow enabling AI coding assistants to generate, validate, and lint components against your design system.
Step 1: Scaffolding a Frontend Codebase
To get started, you do not need to configure complex Drupal modules locally first. A standalone frontend repository can be initialized with a single CLI command.
1.1 Run the Scaffolding CLI
Open your terminal and run:
npx @drupal-canvas/create@latestFollow the interactive prompts:
Drupal Canvas create
Enter the project name:
my-canvas-project
Enter the Drupal site URL:
https://drupal.ddev.site
Fetching template...
Done! Created my-canvas-project.1.2 Inspecting the Project Directory
Navigate into your new directory:
cd my-canvas-projectThe resulting project layout is standard modern frontend tooling:
View source diagram
my-canvas-project/
├── .agents/ # AI Agent skills and system prompt configurations
│ └── skills/
├── .github/
├── .husky/
├── src/
│ ├── components/ # React components + Drupal metadata
│ │ ├── card/
│ │ │ ├── component.yml # SDC-style prop/slot schema
│ │ │ ├── index.jsx # React implementation
│ │ │ └── mocks.json # Mock data for local testing
│ │ ├── hero/
│ │ ├── section/
│ │ └── pricing-table/
│ ├── pages/ # Visual page templates (JSON)
│ │ ├── home.json
│ │ ├── blog.json
│ │ └── careers.json
│ └── lib/
├── canvas.config.json
├── package.json
├── tailwind.config.js
└── tsconfig.jsonWhy this matters: Because this is a standard React and TypeScript project, LLMs and modern coding assistants have deep native comprehension of the structure right out of the box—no legacy CMS paradigms required.
Step 2: Zero-Config Development with Canvas Workbench
Frontend developers need fast feedback loops with hot module reloading (HMR) without depending on a running Drupal backend or maintaining heavy Storybook configurations.
2.1 Launch Canvas Workbench
Execute:
npx canvas-workbenchThis starts a lightweight Vite dev server:
VITE v7.3.2 ready in 223 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help2.2 Features of Canvas Workbench
Open http://localhost:5173/ in your browser:
- Component Previews: Automatically discovers all components inside
src/components/and renders them with their defined variants (e.g., Default, Acid background, Ink background, Chalk). - Page Previews: Renders full Canvas pages and layouts assembled from your components (e.g., full homepage previews) using your
src/pages/*.jsonlayout definitions. - No Configuration Overhead: Unlike Storybook, you don't need to write
.stories.jsxfiles or mock complex CMS contexts. Previews are derived directly from your component files andmocks.json.
Step 3: Accelerating Development with AI Coding Agents
The project template includes pre-configured AI Agent skills (located under .agents/skills/), allowing agents (like Claude Code, Codex, or custom CLI tools) to build Canvas components autonomously.
3.1 Prompting the Coding Agent
Run your preferred AI agent CLI (e.g., pi, claude, or Cursor):
~/Projects/my-canvas-project (main)
> pi
Build a content template for my articles.3.2 Automated Agent Execution Flow
View source diagram
[Agent Reads Prompt]
│
▼
[Loads skill: canvas-content-templates:1]
│
▼
[Inspects Design System & Existing Components]
│
▼
[Generates React TSX / JSX + component.yml schema]
│
▼
[Executes Local Validation via Workbench & ESLint]
│
▼
[Outputs Validated Template ready for Preview]The agent automatically:
- Accesses component definitions in
src/components/. - Assembles full layouts matching your typography, spacing, and brand guidelines.
- Tests its output against Canvas Workbench.
- Verifies syntax and schema compliance using ESLint and Canvas validation rules.
You can instantly review the generated article template live in Workbench under http://localhost:5173/content-template/node.article.full.
Step 4: Component Anatomy & Syncing with Drupal
Drupal Canvas components bridge React with Drupal through a declarative schema file (component.yml), mirroring the mental model of Drupal’s Single Directory Components (SDC).
4.1 Component Schema (section.component.yml)
name: Section
machineName: section
status: true
required: []
props:
properties:
backgroundColor:
type: string
enum:
- chalk
- paper
- acid
- blue
meta:enum:
chalk: Chalk
paper: Paper
acid: Acid
blue: Blue
title: Background color
default: chalk
slots:
content:
title: Content4.2 Component Implementation (section.tsx)
import React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { FormattedText } from '@drupal-canvas/react';
const sectionVariants = cva('w-full px-6 py-12 transition-colors duration-200', {
variants: {
backgroundColor: {
chalk: 'bg-neutral-100 text-neutral-900',
paper: 'bg-white text-neutral-900 border-y border-neutral-200',
acid: 'bg-lime-400 text-black',
blue: 'bg-blue-600 text-white',
},
},
defaultVariants: {
backgroundColor: 'chalk',
},
});
interface SectionProps extends VariantProps<typeof sectionVariants> {
backgroundColor?: 'chalk' | 'paper' | 'acid' | 'blue';
children?: React.ReactNode;
}
export const Section: React.FC<SectionProps> = ({
backgroundColor = 'chalk',
children,
}) => {
return (
<section className={sectionVariants({ backgroundColor })}>
<div className="max-w-7xl mx-auto">{children}</div>
</section>
);
};4.3 Pushing Components to Drupal Canvas
Once components and page layouts are defined locally, push them directly to your Drupal instance using the Canvas CLI:
npx canvas pushTerminal Execution:
~/Projects/my-canvas-project [main]
> npx canvas push
Drupal Canvas push
Plan
Components: 19 create
Pages: 7 create
Push these changes to https://canvas-env.ddev.site?
✔ Yes
Pushing components...
Pushed 19 components successfully.
Pushed 7 pages successfully.4.4 The Visual Editor in Drupal
Navigate to your Drupal admin interface. Under the Canvas Visual Editor:
- Marketers see your custom React components in the component tray.
- Selecting a component reveals form controls automatically generated from the
propsin yourcomponent.yml(e.g., a dropdown selector forBackground colorwith options: Chalk, Paper, Acid, Blue). - Content authors drag, drop, and nest components into slots visually.
4.5 Bi-Directional Synchronization (pull)
If editors adjust layouts, templates, or create new landing pages inside the Drupal UI, developers can pull those changes back down into Git:
npx canvas pullThis synchronizes remote changes directly into your local src/pages/*.json files.
Step 5: Incorporating Third-Party npm Packages
Because components run in a standard React environment, you have unhindered access to the entire npm package ecosystem.
5.1 Example: Adding Animated Metrics with react-countup
Install the package using your package manager:
npm install react-countup5.2 Implement Dynamic Counter in a Component
Update your pricing or statistics component (e.g., src/components/pricing-table/pricing-table.tsx):
import React, { useState } from 'react';
import CountUp from 'react-countup';
import { cn } from '@drupal-canvas/react';
export interface PricingCardProps {
planName: string;
price: number;
description: string;
}
export const PricingCard: React.FC<PricingCardProps> = ({ planName, price, description }) => {
return (
<div className="border p-6 rounded-xl flex flex-col justify-between shadow-sm bg-white">
<div>
<h3 className="text-lg font-bold uppercase tracking-wider">{planName}</h3>
<p className="text-sm text-neutral-500 mt-2">{description}</p>
</div>
<div className="mt-6">
<div className="text-4xl font-extrabold tracking-tight flex items-baseline">
<span>$</span>
{/* Animated counter from npm package */}
<CountUp end={price} duration={1.5} separator="," />
<span className="text-sm font-normal text-neutral-500 ml-1">/mo</span>
</div>
</div>
<button className="mt-6 w-full py-2 bg-black text-white font-medium rounded hover:bg-neutral-800 transition">
Choose {planName}
</button>
</div>
);
};5.3 Verify and Deploy
- Open Canvas Workbench (
npx canvas-workbench) to immediately see the counter animation run locally. - Push to Drupal:
Shell npx canvas push - Open Drupal Canvas: The counter renders with the full client-side React animation embedded seamlessly in the live site and preview frames.
Summary Comparison: Traditional Drupal vs. Drupal Canvas
| Feature | Traditional Drupal Frontend | Drupal Canvas Code Components |
|---|---|---|
| Component Stack | Twig, PHP theme engines, YAML libraries | React, TypeScript, Tailwind CSS |
| Frontend Setup | Requires local Drupal, web server, DB | Standalone Node.js / Vite environment |
| Component Previews | Storybook (manual configuration) | Canvas Workbench (zero-config, automatic) |
| AI Coding Agents | Difficult due to custom Drupal Twig hooks | Native; leverages LLM strength in React/TS |
| npm Ecosystem | Complex asset compilation & bundling | Native standard npm install |
| Editor Experience | Form-based node edits or Layout Builder | Real-time, drag-and-drop Visual Canvas |
| Syncing Mechanism | Database exports, Features, Config Sync | Git-friendly canvas push / canvas pull |
“Yeah — very, very exciting. Shout-out to the Canvas team. That’s sort of step one of two, because JavaScript frameworks are great, but very often they need a content backend.”
“Drupal can provide organizations the best of both worlds: editors get a great user experience to create pages and content, and frontend developers get tools like you just saw.”
“Quick aside: this year we’ve had Drupal Pivot, where we brought together agency owners to talk about the future of Drupal. One thing I heard loud and clear is that they wanted more headless support in Drupal. I think they’re going to love this new feature. Let’s take a look.”