Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ai/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# AI Contribution Guide

- Follow the Drupal 10+ best practices documented in `README.md`, especially sections 2 (Site building) and 3 (Theming, templates).
- Keep generated guidance tool-agnostic whenever possible; mention specific CLIs (drush, ddev, composer, git) only when necessary.
- Prefer concise, actionable bullet points over long prose for skills, rules, and commands.
- When writing validation scripts, fail fast if required tools (e.g., `drush`) are missing and provide clear messaging.
- Do not introduce Drupal 7.x-only guidance.
12 changes: 12 additions & 0 deletions ai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# AI Resources for Drupal Best Practices

This folder contains AI-friendly assets derived from `README.md` (Sections 2 and 3) to help coding assistants apply Drupal 10+ best practices.

- `AGENTS.md`: contributor guidance for AI-generated content.
- `skills/claude-code-skills.md`: per-subsection skills aligned to site building and theming.
- `rules/best-practice-rules.md`: tool-agnostic rules for any CLI or IDE integration.
- `commands/commands.md`: slash-command triggers that map directly to best-practice sections.
- `scripts/validate-site-building.sh`: drush-based checks for section 2 topics (nodes, blocks, taxonomy, etc.).
- `scripts/validate-theming.sh`: drush-based checks for section 3 theming guidelines.

Ensure the project uses Drupal 10+ conventions; Drupal 7.x-only rules are intentionally omitted.
14 changes: 14 additions & 0 deletions ai/commands/commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# AI Command Triggers for Drupal Best Practices

Use these slash commands (or similar triggers) to request focused guidance mapped to `README.md` subsections.

- `/drupal-best-practices-nodes` → 2. Site building > 2.1 Nodes
- `/drupal-best-practices-blocks` → 2. Site building > 2.2 Blocks
- `/drupal-best-practices-taxonomy` → 2. Site building > 2.3 Taxonomy
- `/drupal-best-practices-content-entities` → 2. Site building > 2.4 Other content entities
- `/drupal-best-practices-fields` → 2. Site building > 2.5 Fields
- `/drupal-best-practices-views` → 2. Site building > 2.6 Views
- `/drupal-best-practices-forms` → 2. Site building > 2.7 Forms
- `/drupal-best-practices-editors` → 2. Site building > 2.8 Text formats and editors
- `/drupal-best-practices-users` → 2. Site building > 2.10 Users, roles & permissions
- `/drupal-best-practices-theming` → 3. Theming, templates
20 changes: 20 additions & 0 deletions ai/rules/best-practice-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Tool-Agnostic Rules for Drupal 10+ Best Practices

Use these rules across AI coding helpers, CLIs, and IDE automations. They mirror `README.md` sections 2 and 3.

## Site building (Section 2)
- Machine names for bundles, fields, blocks, and views must be singular, human-meaningful, and free of suffix clutter (e.g., drop `_1`).
- Prefer custom entities or block types over overloading nodes; create new bundles only for distinct display/logic needs.
- Provide descriptions for content types, fields, and Views; document access via permissions rather than roles.
- Reuse fields only when identical across bundles; set deterministic upload directories and avoid `gif` unless required.
- Views should use content-based rows with view modes, explicit titles, tags, and non-AJAX defaults; disable unused displays.
- Standardize on a single HTML format with CKEditor; keep admins aligned with author-capable formats and avoid insecure content via UI.
- Model roles by persona with concise machine names; each module must declare its own permissions and expose dashboards tailored to roles.

## Theming, templates (Section 3)
- Use one-word machine names for themes without base-theme suffixes or the word `theme`; prefer Classy base or cloned contrib themes.
- Follow Atomic design, SCSS, and common breakpoints; avoid panels-family modules.
- Favor twig templates and preprocess functions for structure and classes; include key pages (404/403/maintenance/login).
- Avoid styling based on path aliases or non-semantic classes; use functional prefixes (`twig-`, `js-`) and mixins instead of utility elements.
- Override only necessary CSS/JS, comment mixins/functions, and organize templates by module/entity with minimal folder sprawl.
- Support modern browsers per Drupal 10+ guidance; keep admin theme overrides minimal and core-focused.
96 changes: 96 additions & 0 deletions ai/scripts/validate-site-building.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -euo pipefail

# Validate Drupal 10+ site-building best practices for section 2.
# Usage: ./validate-site-building.sh [section]
# Sections: nodes blocks taxonomy entities fields views forms editors users

section="${1:-all}"
project_root="${PROJECT_ROOT:-$(pwd)}"
config_dir="${CONFIG_DIR:-${project_root}/config/sync}"

if ! command -v drush >/dev/null 2>&1; then
echo "[WARN] drush not found. Install drush or set PATH so checks can run." >&2
exit 1
fi

run_drush() {
local cmd="$1"
echo "[INFO] drush ${cmd}" >&2
drush ${cmd}
}

check_nodes() {
echo "[CHECK] 2.1 Nodes: singular names, minimal bundles, consistent view modes"
run_drush "eval 'print json_encode(\\Drupal\\node\\Entity\\NodeType::loadMultiple());'" \
| jq 'keys[]' >/dev/null
}

check_blocks() {
echo "[CHECK] 2.2 Blocks: custom block types via code and clean machine names"
run_drush "eval 'print json_encode(\\Drupal\\block_content\\Entity\\BlockContentType::loadMultiple());'" \
| jq 'keys[]' >/dev/null
}

check_taxonomy() {
echo "[CHECK] 2.3 Taxonomy: singular vocabularies and purpose beyond filtering"
run_drush "eval 'print json_encode(\\Drupal\\taxonomy\\Entity\\Vocabulary::loadMultiple());'" \
| jq 'keys[]' >/dev/null
}

check_entities() {
echo "[CHECK] 2.4 Other content entities: paragraphs/media revisions and generic image styles"
run_drush "eval 'print json_encode(\\Drupal\\image\\Entity\\ImageStyle::loadMultiple());'" \
| jq 'keys[]' >/dev/null
}

check_fields() {
echo "[CHECK] 2.5 Fields: naming patterns and descriptions"
run_drush "eval 'print json_encode(array_keys(\\Drupal\\field\\Entity\\FieldStorageConfig::loadMultiple()));'" \
| jq '[]' >/dev/null
}

check_views() {
echo "[CHECK] 2.6 Views: clean machine names, per-display instances, permissions"
run_drush "views:list" >/dev/null
}

check_forms() {
echo "[CHECK] 2.7 Forms: prefer Webform over core Contact for complex needs"
run_drush "pm:list webform" >/dev/null
Comment on lines +58 to +60

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid unsupported argument to pm:list in forms check

The forms validation uses drush pm:list webform, but pm:list (pml) does not take module names as positional arguments—it only accepts options like --type or --status. Passing webform causes Drush to exit with a “too many arguments” error, and with set -e the entire site-building validation halts whenever the forms check (or all) is selected.

Useful? React with 👍 / 👎.

}

check_editors() {
echo "[CHECK] 2.8 Text formats and editors: single HTML format with CKEditor"
run_drush "eval 'print json_encode(\\Drupal\\filter\\Entity\\FilterFormat::loadMultiple());'" \
| jq 'keys[]' >/dev/null
}

check_users() {
echo "[CHECK] 2.10 Users: persona-based roles and module-defined permissions"
run_drush "role:list" >/dev/null
}

case "${section}" in
all)
check_nodes
check_blocks
check_taxonomy
check_entities
check_fields
check_views
check_forms
check_editors
check_users
;;
nodes) check_nodes ;;
blocks) check_blocks ;;
taxonomy) check_taxonomy ;;
entities) check_entities ;;
fields) check_fields ;;
views) check_views ;;
forms) check_forms ;;
editors) check_editors ;;
users) check_users ;;
*) echo "Unknown section: ${section}" >&2; exit 1 ;;
esac
55 changes: 55 additions & 0 deletions ai/scripts/validate-theming.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -euo pipefail

# Validate Drupal 10+ theming best practices for section 3.
# Usage: ./validate-theming.sh [check]
# Checks: themes css twig assets

check="${1:-all}"

if ! command -v drush >/dev/null 2>&1; then
echo "[WARN] drush not found. Install drush or set PATH so checks can run." >&2
exit 1
fi

run_drush() {
local cmd="$1"
echo "[INFO] drush ${cmd}" >&2
drush ${cmd}
}

check_themes() {
echo "[CHECK] 3 Theming: machine names, base theme choice, and breakpoints"
run_drush "theme:list" >/dev/null
}

check_css() {
echo "[CHECK] 3 Theming: SCSS usage, Atomic structure, and limited overrides"
find themes -maxdepth 2 -type f \( -name '*.scss' -o -name '*.sass' \) >/dev/null
}

check_twig() {
echo "[CHECK] 3 Theming: preprocess coverage and template organization"
run_drush "ev 'print json_encode(array_keys(\\Drupal\\theme_handler\\ThemeHandler::defaultThemeList()));'" \
| jq 'keys[]' >/dev/null
Comment on lines +31 to +34

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use existing ThemeHandler namespace in twig check

The twig validation runs drush ev against \Drupal\theme_handler\ThemeHandler::defaultThemeList(), but Drupal core exposes the theme handler as \Drupal\Core\Extension\ThemeHandler (usually accessed via the theme_handler service) and there is no \Drupal\theme_handler\ThemeHandler class. As written, drush ev will fatally error with “Class … not found” whenever the twig check (or all) is executed, stopping the script before any theming validation runs.

Useful? React with 👍 / 👎.

}

check_assets() {
echo "[CHECK] 3 Theming: browser support and utility-first frameworks used selectively"
run_drush "ev 'print json_encode(\\Drupal\\core\\Asset\\LibraryDiscovery::getInfo());'" \
| jq 'keys[]' >/dev/null
Comment on lines +37 to +40

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fix LibraryDiscovery namespace casing in assets check

The assets check calls \Drupal\core\Asset\LibraryDiscovery::getInfo(), but the class lives under \Drupal\Core\Asset\LibraryDiscovery. Because Composer’s PSR‑4 autoloader is case sensitive, the lowercase core prefix will not resolve on a typical Linux install, causing drush ev to throw a class-not-found error and abort the script whenever the assets check runs.

Useful? React with 👍 / 👎.

}

case "${check}" in
all)
check_themes
check_css
check_twig
check_assets
;;
themes) check_themes ;;
css) check_css ;;
twig) check_twig ;;
assets) check_assets ;;
*) echo "Unknown check: ${check}" >&2; exit 1 ;;
esac
55 changes: 55 additions & 0 deletions ai/skills/claude-code-skills.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Claude Code Skills for Drupal 10+ Best Practices

These skills mirror the repository's best practices so Claude-based tools can deliver focused help per subsection.

## 2. Site building

### Skill: 2.1 Nodes
- Enforce singular machine names for node bundles and fields; avoid conflicts or ambiguous prefixes.
- Recommend custom entities or block types instead of using nodes for dynamic blocks.
- Limit new bundles to cases with distinct displays or behavior; align view modes across types and document content type purpose.

### Skill: 2.2 Blocks
- Generate custom block types or plugins with concise machine names (no theme/region hints and no `block_` prefix).
- Treat block fields and view modes like other content entities; prefer code-generated block types for stability.
- Avoid hardcoding UUID-based blocks; use plugins for static blocks.

### Skill: 2.3 Taxonomy
- Use singular vocabulary names and reserve taxonomies for categorized pages rather than simple filters.
- Prefer list fields for filtering-only needs and consider node references when authorization, fields, or displays are required.

### Skill: 2.4 Other content entities
- Apply node rules to paragraphs, media, comments, etc.; watch translation/revision behavior (especially paragraphs).
- Name image styles generically (e.g., `large_wide`) instead of dimension-specific machine names.

### Skill: 2.5 Fields
- Advocate clear, reusable machine names: `field_[content_type]_[short_name]` for specific fields and generic prefixes for shared ones.
- Require field descriptions, meaningful upload directories (avoid date-based defaults), and removal of `gif` unless necessary.
- Encourage consistent prefixes when projects mandate them and reuse fields only when truly identical across bundles.

### Skill: 2.6 Views
- Normalize machine names (remove `_1` suffixes) and create one View per display when possible.
- Use `Show: Content` with view modes, provide titles, descriptions, tags, access by permission, and no default AJAX.
- Disable unused Views, supply "No results" text, and avoid blanket custom CSS classes.

### Skill: 2.7 Forms
- Recommend Webform for custom forms; use core Contact form only for minimal needs without stored submissions.

### Skill: 2.8 Text formats and editors
- Standardize on one HTML editor format with CKEditor, aligned buttons and allowed tags; avoid insecure content via UI.
- Prevent role-based format hopping and keep admins aligned with authors' editable formats.

### Skill: 2.10 Users, roles & permissions
- Model roles by persona, avoid overpowered authenticated roles, and keep machine names short.
- Ensure each module declares its own permissions with verb-led names; prefer Masquerade for permission testing.
- Provide custom admin dashboards and limit duplicate admin accounts.

## 3. Theming, templates

### Skill: 3 Theming fundamentals
- Use one-word theme machine names without `theme` or base-theme suffixes; prefer Classy base theme or cloned contrib themes without inheritance.
- Align CSS with Atomic design, SCSS, and consistent breakpoints; avoid panels family modules.
- Rely on preprocess functions and targeted twig templates (including 404/403/maintenance/login) instead of DB theme settings for teams.
- Avoid path-alias-based styling and non-semantic CSS classes; use functional prefixes (`twig-`, `js-`) and mixins over utility elements.
- Override only necessary CSS/JS, favor utility-first frameworks selectively, comment mixins/functions, and organize templates by module/entity.
- Support modern browser guidance (Drupal 10+ drops IE11) and keep admin theme mostly core with light overrides.