diff --git a/ai/AGENTS.md b/ai/AGENTS.md new file mode 100644 index 0000000..b114812 --- /dev/null +++ b/ai/AGENTS.md @@ -0,0 +1,9 @@ +# AI contribution guide + +These instructions summarize the Drupal 10+ best practices from `README.md` for any AI-assisted changes inside the `ai/` folder. + +- Prioritize the guidance from **2. Site building** and **3. Theming, templates**. Avoid any Drupal 7.x-only rules. +- Use clear machine names and avoid multi-word theme names; keep everything human-readable and concise. +- Keep recommendations aligned with current Drupal core tooling (composer, drush, ddev) and avoid deprecated workflows. +- Ensure scripts and prompts reinforce configuration over content, avoid hardcoded UUIDs, and respect configuration sync. +- Keep the output concise and actionable so it can be applied from CLI tools or code editors. diff --git a/ai/README.md b/ai/README.md new file mode 100644 index 0000000..0b0a338 --- /dev/null +++ b/ai/README.md @@ -0,0 +1,16 @@ +# AI Helpers for Drupal Best Practices + +This folder provides AI-friendly outputs derived from `README.md` sections **2. Site building** and **3. Theming, templates** for Drupal 10+ projects. + +- `AGENTS.md` – scope rules for AI-written assets in this folder. +- `claude-code-skills.md` – index pointing to per-subsection Claude skills. +- `claude-skills/` – Claude-ready skills with `SKILL.md`, examples, scripts, and references per subsection. +- `rules.md` – generic rules for any CLI/editor AI. +- `commands.md` – slash commands mapping to the relevant README sections. +- `scripts/*.sh` – drush-based validators for subsections (nodes, blocks, taxonomy, fields, views, text formats, theming). + +Run validators from a bootstrapped Drupal site, e.g. + +```bash +./ai/scripts/validate-nodes.sh +``` diff --git a/ai/claude-code-skills.md b/ai/claude-code-skills.md new file mode 100644 index 0000000..b883dd6 --- /dev/null +++ b/ai/claude-code-skills.md @@ -0,0 +1,16 @@ +# Claude Skills Index + +Claude skills for Drupal 10+ best practices now live in dedicated folders under `ai/claude-skills/`, following Anthropics' recommended SKILL structure. + +## Available skills +- `nodes/` – README §2.1 Nodes +- `blocks/` – README §2.2 Blocks +- `taxonomy/` – README §2.3 Taxonomy +- `other-content-entities/` – README §2.4 Other content entities +- `fields/` – README §2.5 Fields +- `views/` – README §2.6 Views +- `forms/` – README §2.7 Forms +- `text-formats-editors/` – README §2.8 Text formats and editors +- `theming/` – README §3 Theming, templates + +Each skill folder contains a `SKILL.md` with metadata, plus `examples/`, `scripts/`, and `reference/` helpers that map directly to the corresponding best-practice validator scripts in `ai/scripts/`. diff --git a/ai/claude-skills/blocks/SKILL.md b/ai/claude-skills/blocks/SKILL.md new file mode 100644 index 0000000..d726ba4 --- /dev/null +++ b/ai/claude-skills/blocks/SKILL.md @@ -0,0 +1,38 @@ +--- +id: drupal-blocks +title: Drupal Blocks and Block Types +summary: Create reusable custom blocks and plugins with disciplined naming and configuration. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - blocks +source: README.md §2.2 Blocks +--- + +## Description +Guide Claude to design custom block types and plugins that are portable, reusable, and consistently named across environments. + +## Usage +- Request machine name and admin label suggestions that omit regions and `block_` prefixes. +- Ask for field plans that mirror node/paragraph standards when blocks need structured data. +- Have Claude propose view mode reuse and caching expectations for each block display. + +## Guardrails +- Prefer block types or plugins committed to code; avoid UUID-specific content blocks. +- Keep machine names short, region-agnostic, and human-readable. +- Treat block fields and view modes like node bundles for documentation and reuse. + +## Validation +```bash +./ai/scripts/validate-blocks.sh +``` +Run from a bootstrapped site to flag naming and descriptive gaps. + +## References +- Drupal Best Practices README §2.2 Blocks. +- Separate content from placement; regions and layouts are runtime concerns. diff --git a/ai/claude-skills/blocks/examples/prompt.md b/ai/claude-skills/blocks/examples/prompt.md new file mode 100644 index 0000000..09fbd04 --- /dev/null +++ b/ai/claude-skills/blocks/examples/prompt.md @@ -0,0 +1 @@ +Request: "Outline a reusable `testimonial` custom block type with a concise machine name, fields, recommended view modes, and caching notes." diff --git a/ai/claude-skills/blocks/reference/README.md b/ai/claude-skills/blocks/reference/README.md new file mode 100644 index 0000000..5d1efad --- /dev/null +++ b/ai/claude-skills/blocks/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- No region names or `block_` prefixes in machine names. +- Store reusable block types or plugins in code; avoid UUID-tied instances. +- Document intended view modes and caching expectations. diff --git a/ai/claude-skills/blocks/scripts/README.md b/ai/claude-skills/blocks/scripts/README.md new file mode 100644 index 0000000..f41a9cd --- /dev/null +++ b/ai/claude-skills/blocks/scripts/README.md @@ -0,0 +1 @@ +Use `./ai/scripts/validate-blocks.sh` to verify naming, descriptions, and block reuse guidance after updates. diff --git a/ai/claude-skills/fields/SKILL.md b/ai/claude-skills/fields/SKILL.md new file mode 100644 index 0000000..cf0bc2c --- /dev/null +++ b/ai/claude-skills/fields/SKILL.md @@ -0,0 +1,37 @@ +--- +id: drupal-fields +title: Drupal Fields +summary: Name, describe, and reuse fields with clear ownership and scope. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - fields +source: README.md §2.5 Fields +--- + +## Description +Help Claude create field plans with consistent machine names, descriptions, and reuse rules that respect configuration sync. + +## Usage +- Ask for machine names using `field_[bundle]_[short]` for specific fields and generic names for shared fields. +- Request field descriptions, widget/formatter choices, and file directory guidance. +- Have Claude flag when reuse is unsafe due to differing semantics. + +## Guardrails +- Provide descriptions for every field and avoid ambiguous reuse. +- Use meaningful file directories; avoid GIF formats unless required. +- Keep machine names concise and predictable for bundle-specific fields. + +## Validation +```bash +./ai/scripts/validate-fields.sh +``` + +## References +- Drupal Best Practices README §2.5 Fields. +- Share fields only when semantics and configuration truly align. diff --git a/ai/claude-skills/fields/examples/prompt.md b/ai/claude-skills/fields/examples/prompt.md new file mode 100644 index 0000000..6fcf8f9 --- /dev/null +++ b/ai/claude-skills/fields/examples/prompt.md @@ -0,0 +1 @@ +Request: "List fields for a `event` bundle with machine names, descriptions, directory guidance for uploads, and whether each field can be safely reused elsewhere." diff --git a/ai/claude-skills/fields/reference/README.md b/ai/claude-skills/fields/reference/README.md new file mode 100644 index 0000000..0ae7025 --- /dev/null +++ b/ai/claude-skills/fields/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- `field_[bundle]_[short]` for bundle-specific fields; keep shared fields generic. +- Always document field intent and widget/formatter choices. +- Avoid GIF uploads unless necessary and set meaningful directories. diff --git a/ai/claude-skills/fields/scripts/README.md b/ai/claude-skills/fields/scripts/README.md new file mode 100644 index 0000000..9861ff7 --- /dev/null +++ b/ai/claude-skills/fields/scripts/README.md @@ -0,0 +1 @@ +Use `./ai/scripts/validate-fields.sh` after adding or adjusting fields to enforce naming, descriptions, and reuse rules. diff --git a/ai/claude-skills/forms/SKILL.md b/ai/claude-skills/forms/SKILL.md new file mode 100644 index 0000000..c4f79ed --- /dev/null +++ b/ai/claude-skills/forms/SKILL.md @@ -0,0 +1,35 @@ +--- +id: drupal-forms +title: Drupal Forms +summary: Choose the right form tooling and document when to use Webform versus core Contact. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - forms +source: README.md §2.7 Forms +--- + +## Description +Guide Claude to default to Webform for custom forms, reserving core Contact only for simple, single-form cases. + +## Usage +- Ask for justification when suggesting core Contact instead of Webform. +- Request exportable configuration and access/handler recommendations. +- Have Claude propose spam mitigation and confirmation patterns aligned with Webform. + +## Guardrails +- Prefer Webform for complex or multiple forms; use core Contact only for simple single forms. +- Keep configuration exportable and avoid content-only forms. +- Document access, handlers, and submission storage expectations. + +## Validation +Review form choices against project requirements; rerun relevant validators (fields, views) if forms expose entities. + +## References +- Drupal Best Practices README §2.7 Forms. +- Webform is the default choice for bespoke forms in Drupal 10+. diff --git a/ai/claude-skills/forms/examples/prompt.md b/ai/claude-skills/forms/examples/prompt.md new file mode 100644 index 0000000..1b0b68b --- /dev/null +++ b/ai/claude-skills/forms/examples/prompt.md @@ -0,0 +1 @@ +Request: "Recommend whether to use Webform or core Contact for a newsletter signup; include reasons, access settings, and exportable configuration notes." diff --git a/ai/claude-skills/forms/reference/README.md b/ai/claude-skills/forms/reference/README.md new file mode 100644 index 0000000..a399050 --- /dev/null +++ b/ai/claude-skills/forms/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- Default to Webform; core Contact is only for simple single forms. +- Keep submissions/export configuration in code where possible. +- Document access, handlers, spam protection, and confirmations. diff --git a/ai/claude-skills/forms/scripts/README.md b/ai/claude-skills/forms/scripts/README.md new file mode 100644 index 0000000..d89409f --- /dev/null +++ b/ai/claude-skills/forms/scripts/README.md @@ -0,0 +1 @@ +No dedicated validator; align choices with README §2.7 and re-use entity validators when forms expose entities or fields. diff --git a/ai/claude-skills/nodes/SKILL.md b/ai/claude-skills/nodes/SKILL.md new file mode 100644 index 0000000..5dcb73f --- /dev/null +++ b/ai/claude-skills/nodes/SKILL.md @@ -0,0 +1,40 @@ +--- +id: drupal-nodes +title: Drupal Node Bundles +summary: Model and maintain node bundles using Drupal 10 site-building conventions. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - nodes + - content-modeling +source: README.md §2.1 Nodes +--- + +## Description +Apply consistent naming, reuse, and revision policies when creating and maintaining node bundles. Favor reusable view modes, keep bundle purposes clear, and document them for downstream editors and themers. + +## Usage +- Prompt Claude to propose bundle names, machine names, descriptions, and required fields before creating a type. +- Ask for revision and translation guidance only when the workflow requires it. +- Request view mode plans that avoid redundant displays and encourage reuse across bundles. + +## Guardrails +- Machine names are singular, concise, and avoid special characters. +- New bundle creation is justified by display or behavior differences; avoid one-off bundles. +- Avoid hardcoding UUIDs or content IDs in configuration or code. + +## Validation +Run the subsection validator from a bootstrapped Drupal site to spot naming and configuration issues: + +```bash +./ai/scripts/validate-nodes.sh +``` + +## References +- Drupal Best Practices README §2.1 Nodes. +- Reuse the “Full” and “Teaser” view modes unless a new, documented display is needed. diff --git a/ai/claude-skills/nodes/examples/prompt.md b/ai/claude-skills/nodes/examples/prompt.md new file mode 100644 index 0000000..4c4f465 --- /dev/null +++ b/ai/claude-skills/nodes/examples/prompt.md @@ -0,0 +1 @@ +Request: "Draft a `article` node bundle plan with machine name suggestions, required fields, and view mode reuse. Highlight when revisions and translations should be enabled." diff --git a/ai/claude-skills/nodes/reference/README.md b/ai/claude-skills/nodes/reference/README.md new file mode 100644 index 0000000..ddd08fe --- /dev/null +++ b/ai/claude-skills/nodes/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- Singular, human-friendly bundle names and machine names. +- Create bundles only when display or functionality diverges. +- Document bundle purpose and default view modes. diff --git a/ai/claude-skills/nodes/scripts/README.md b/ai/claude-skills/nodes/scripts/README.md new file mode 100644 index 0000000..7582fb3 --- /dev/null +++ b/ai/claude-skills/nodes/scripts/README.md @@ -0,0 +1 @@ +Use `./ai/scripts/validate-nodes.sh` after adding or updating node bundles to catch naming and configuration drift. diff --git a/ai/claude-skills/other-content-entities/SKILL.md b/ai/claude-skills/other-content-entities/SKILL.md new file mode 100644 index 0000000..1f4c3ca --- /dev/null +++ b/ai/claude-skills/other-content-entities/SKILL.md @@ -0,0 +1,37 @@ +--- +id: drupal-other-content-entities +title: Other Content Entities +summary: Apply node standards to media, paragraphs, comments, and similar entities. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - media + - paragraphs + - comments +source: README.md §2.4 Other content entities +--- + +## Description +Extend node-oriented conventions to media, paragraphs, comments, and related entities while accounting for translation and display nuances. + +## Usage +- Ask Claude to mirror node naming, documentation, and view mode reuse when modeling non-node entities. +- Request guidance on translation handling, especially for paragraphs. +- Have Claude suggest image style names that describe intent instead of dimensions. + +## Guardrails +- Keep machine names concise and reusable across bundles. +- Ensure translation workflows are explicit for nested entities like paragraphs. +- Prefer descriptive image style names (goal-based, not pixel-based) and avoid GIF unless required. + +## Validation +Refer to scripts aligned with the specific entity (e.g., fields, views, blocks) after applying changes. + +## References +- Drupal Best Practices README §2.4 Other content entities. +- Apply node naming, descriptions, and view mode reuse patterns consistently. diff --git a/ai/claude-skills/other-content-entities/examples/prompt.md b/ai/claude-skills/other-content-entities/examples/prompt.md new file mode 100644 index 0000000..53dcabd --- /dev/null +++ b/ai/claude-skills/other-content-entities/examples/prompt.md @@ -0,0 +1 @@ +Request: "Define a media `image` bundle with node-style naming, recommended view modes, translation handling, and image style naming focused on intent." diff --git a/ai/claude-skills/other-content-entities/reference/README.md b/ai/claude-skills/other-content-entities/reference/README.md new file mode 100644 index 0000000..16f12bb --- /dev/null +++ b/ai/claude-skills/other-content-entities/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- Mirror node naming and documentation on media, paragraphs, and comments. +- Spell out translation strategy for nested entities. +- Name image styles by intent, not dimensions; avoid GIF unless required. diff --git a/ai/claude-skills/other-content-entities/scripts/README.md b/ai/claude-skills/other-content-entities/scripts/README.md new file mode 100644 index 0000000..a37af50 --- /dev/null +++ b/ai/claude-skills/other-content-entities/scripts/README.md @@ -0,0 +1 @@ +Use the relevant validators (fields, views, blocks) after updating non-node entities to keep naming and display guidance consistent. diff --git a/ai/claude-skills/taxonomy/SKILL.md b/ai/claude-skills/taxonomy/SKILL.md new file mode 100644 index 0000000..f9ff5e9 --- /dev/null +++ b/ai/claude-skills/taxonomy/SKILL.md @@ -0,0 +1,37 @@ +--- +id: drupal-taxonomy +title: Drupal Taxonomy +summary: Model vocabularies and terms responsibly for categorization and landing pages. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - taxonomy +source: README.md §2.3 Taxonomy +--- + +## Description +Use taxonomy for categorization and curated landing pages while keeping names singular and purpose-driven. + +## Usage +- Ask Claude whether taxonomy or another entity type (e.g., entity reference) fits the requirement. +- Request vocabulary naming and description guidance to keep purpose clear. +- Have Claude outline display patterns that avoid overloading taxonomy when richer entities are needed. + +## Guardrails +- Singular vocabulary names and concise machine names. +- Use taxonomy for categorization and term pages, not simple filters when entity references suffice. +- Consider permissions, fields, and translation needs before defaulting to taxonomy. + +## Validation +```bash +./ai/scripts/validate-taxonomy.sh +``` + +## References +- Drupal Best Practices README §2.3 Taxonomy. +- Prefer entity references when authorization, fields, or displays exceed taxonomy needs. diff --git a/ai/claude-skills/taxonomy/examples/prompt.md b/ai/claude-skills/taxonomy/examples/prompt.md new file mode 100644 index 0000000..66018e9 --- /dev/null +++ b/ai/claude-skills/taxonomy/examples/prompt.md @@ -0,0 +1 @@ +Request: "Propose a `topics` vocabulary with singular machine name suggestions, purpose description, and guidance on when to use entity references instead." diff --git a/ai/claude-skills/taxonomy/reference/README.md b/ai/claude-skills/taxonomy/reference/README.md new file mode 100644 index 0000000..5a27ce5 --- /dev/null +++ b/ai/claude-skills/taxonomy/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- Vocabulary names are singular and descriptive. +- Use taxonomy for categorization/landing pages; use entity references when richer modeling is needed. +- Document access, translation, and field expectations. diff --git a/ai/claude-skills/taxonomy/scripts/README.md b/ai/claude-skills/taxonomy/scripts/README.md new file mode 100644 index 0000000..e2aa760 --- /dev/null +++ b/ai/claude-skills/taxonomy/scripts/README.md @@ -0,0 +1 @@ +Use `./ai/scripts/validate-taxonomy.sh` to confirm naming, descriptions, and appropriate taxonomy usage. diff --git a/ai/claude-skills/text-formats-editors/SKILL.md b/ai/claude-skills/text-formats-editors/SKILL.md new file mode 100644 index 0000000..94d6bf0 --- /dev/null +++ b/ai/claude-skills/text-formats-editors/SKILL.md @@ -0,0 +1,38 @@ +--- +id: drupal-text-formats-editors +title: Text Formats and Editors +summary: Standardize HTML formats and editor settings for safe, consistent authoring. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - text-formats + - ckeditor +source: README.md §2.8 Text formats and editors +--- + +## Description +Help Claude align text formats, allowed tags, and CKEditor button sets so authors share a consistent, secure HTML format. + +## Usage +- Ask for a single standardized HTML format with matching CKEditor settings and allowed HTML tags. +- Request button set recommendations that mirror allowed tags and remove insecure options. +- Have Claude plan format access to avoid authors switching between overlapping formats. + +## Guardrails +- Keep insecure content out of WYSIWYG; align editor buttons with allowed tags. +- Limit format switching by mirroring access controls and keeping formats minimal. +- Prefer one HTML format for most authors; ensure admin formats align with policy. + +## Validation +```bash +./ai/scripts/validate-text-formats.sh +``` + +## References +- Drupal Best Practices README §2.8 Text formats and editors. +- Standardize on CKEditor for Drupal 10+. diff --git a/ai/claude-skills/text-formats-editors/examples/prompt.md b/ai/claude-skills/text-formats-editors/examples/prompt.md new file mode 100644 index 0000000..fcb2e70 --- /dev/null +++ b/ai/claude-skills/text-formats-editors/examples/prompt.md @@ -0,0 +1 @@ +Request: "Design a single HTML text format for authors with CKEditor settings aligned to allowed tags; include access rules to limit format switching." diff --git a/ai/claude-skills/text-formats-editors/reference/README.md b/ai/claude-skills/text-formats-editors/reference/README.md new file mode 100644 index 0000000..ae0fe0c --- /dev/null +++ b/ai/claude-skills/text-formats-editors/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- Standardize on a single HTML format with matching CKEditor configuration. +- Align editor buttons with allowed tags; remove insecure options. +- Limit format switching by aligning permissions and keeping formats minimal. diff --git a/ai/claude-skills/text-formats-editors/scripts/README.md b/ai/claude-skills/text-formats-editors/scripts/README.md new file mode 100644 index 0000000..eb47de6 --- /dev/null +++ b/ai/claude-skills/text-formats-editors/scripts/README.md @@ -0,0 +1 @@ +Use `./ai/scripts/validate-text-formats.sh` to confirm allowed tags, button sets, and access alignment. diff --git a/ai/claude-skills/theming/SKILL.md b/ai/claude-skills/theming/SKILL.md new file mode 100644 index 0000000..8e2a7ee --- /dev/null +++ b/ai/claude-skills/theming/SKILL.md @@ -0,0 +1,38 @@ +--- +id: drupal-theming +title: Drupal Theming and Templates +summary: Build Drupal themes with clean machine names, Twig-first templates, and atomic SCSS structure. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - theming + - twig + - scss +source: README.md §3 Theming, templates +--- + +## Description +Guide Claude to create themes that favor Twig, preprocess logic, and atomic SCSS structure while keeping overrides minimal and purposeful. + +## Usage +- Ask for one-word machine names without `theme` or base-theme prefixes. +- Request guidance on using Classy as a base theme and limiting overrides to documented needs (404/403/maintenance/login, etc.). +- Have Claude propose SCSS structure by responsibility (variables, mixins, entities, components) and class naming (`twig-`, `js-`). + +## Guardrails +- Avoid path-based styling; add classes in preprocess, not templates. +- Prefer Twig templates with minimal logic; do not overuse theme overrides. +- Use semantic class prefixes and comment mixins/functions; keep SCSS split by responsibility. + +## Validation +```bash +./ai/scripts/validate-theming.sh +``` + +## References +- Drupal Best Practices README §3 Theming, templates. +- Use Classy as a base theme; keep machine names one word and human-readable. diff --git a/ai/claude-skills/theming/examples/prompt.md b/ai/claude-skills/theming/examples/prompt.md new file mode 100644 index 0000000..231cbe3 --- /dev/null +++ b/ai/claude-skills/theming/examples/prompt.md @@ -0,0 +1 @@ +Request: "Plan a one-word machine name theme that extends Classy, lists essential Twig overrides (404/403/maintenance/login), and proposes SCSS folders with `twig-`/`js-` class prefixes." diff --git a/ai/claude-skills/theming/reference/README.md b/ai/claude-skills/theming/reference/README.md new file mode 100644 index 0000000..5527ada --- /dev/null +++ b/ai/claude-skills/theming/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- One-word machine names; avoid `theme` or base-theme prefixes. +- Prefer Twig templates and preprocess for classes; minimize overrides. +- SCSS split by responsibility, with semantic `twig-` and behavior `js-` class prefixes. diff --git a/ai/claude-skills/theming/scripts/README.md b/ai/claude-skills/theming/scripts/README.md new file mode 100644 index 0000000..fc06331 --- /dev/null +++ b/ai/claude-skills/theming/scripts/README.md @@ -0,0 +1 @@ +Use `./ai/scripts/validate-theming.sh` to review theme naming, base theme selection, and essential template coverage. diff --git a/ai/claude-skills/views/SKILL.md b/ai/claude-skills/views/SKILL.md new file mode 100644 index 0000000..af0cda9 --- /dev/null +++ b/ai/claude-skills/views/SKILL.md @@ -0,0 +1,37 @@ +--- +id: drupal-views +title: Drupal Views +summary: Build Views with intentional naming, access, and display planning. +version: 0.2.0 +created: 2024-03-01 +updated: 2025-03-06 +maintainers: + - Drupal Best Practices Maintainers +tags: + - drupal + - site-building + - views +source: README.md §2.6 Views +--- + +## Description +Ensure Views have clear machine names, titles, tags, and display-level documentation while enforcing access and render strategies. + +## Usage +- Ask Claude to normalize machine names (remove `_1` suffixes) and provide admin descriptions. +- Request per-display titles, access rules, and No Results messages. +- Have Claude recommend rendering entities via view modes and separating displays when behavior diverges. + +## Guardrails +- Require permission-based access on each display. +- Avoid blanket CSS classes and default Ajax unless justified. +- Prefer separate Views per display and reuse view modes instead of field rendering when possible. + +## Validation +```bash +./ai/scripts/validate-views.sh +``` + +## References +- Drupal Best Practices README §2.6 Views. +- Render entities through view modes to keep templating consistent. diff --git a/ai/claude-skills/views/examples/prompt.md b/ai/claude-skills/views/examples/prompt.md new file mode 100644 index 0000000..6119365 --- /dev/null +++ b/ai/claude-skills/views/examples/prompt.md @@ -0,0 +1 @@ +Request: "Design a View for `article` teasers with normalized machine names, per-display titles, access controls, and a No Results message that uses the `teaser` view mode." diff --git a/ai/claude-skills/views/reference/README.md b/ai/claude-skills/views/reference/README.md new file mode 100644 index 0000000..c39912e --- /dev/null +++ b/ai/claude-skills/views/reference/README.md @@ -0,0 +1,4 @@ +Key reminders: +- Normalize machine names (no `_1` suffix) and add tags/admin descriptions. +- Configure per-display access, titles, and No Results messaging. +- Render via view modes; avoid unnecessary Ajax or blanket CSS classes. diff --git a/ai/claude-skills/views/scripts/README.md b/ai/claude-skills/views/scripts/README.md new file mode 100644 index 0000000..d2eb059 --- /dev/null +++ b/ai/claude-skills/views/scripts/README.md @@ -0,0 +1 @@ +Use `./ai/scripts/validate-views.sh` to confirm naming, access, and display documentation for each View. diff --git a/ai/commands.md b/ai/commands.md new file mode 100644 index 0000000..1b2a5c4 --- /dev/null +++ b/ai/commands.md @@ -0,0 +1,13 @@ +# AI Commands for Drupal Best Practices + +Use these slash commands in chat-based tools to pull focused guidance from README sections 2 and 3. + +- `/drupal-best-practices-nodes` → Section 2.1 Nodes: singular bundles, minimal revisions, generic view modes, human-readable machine names. +- `/drupal-best-practices-blocks` → Section 2.2 Blocks: code-driven block types/plugins, clean machine names, no UUID-bound blocks. +- `/drupal-best-practices-taxonomy` → Section 2.3 Taxonomy: singular vocabularies, use for categorization pages, prefer lists or references for filtering/authorization needs. +- `/drupal-best-practices-entities` → Section 2.4 Other content entities: reuse node conventions for media/paragraphs/comments; translation awareness. +- `/drupal-best-practices-fields` → Section 2.5 Fields: `field_[bundle]_[short]` naming, descriptions, reuse rules, image directory conventions, avoid `gif`. +- `/drupal-best-practices-views` → Section 2.6 Views: display-per-view, admin metadata, view modes, permission access, no default Ajax, empty-state text. +- `/drupal-best-practices-forms` → Section 2.7 Forms: default to Webform, reserve core Contact for single lightweight forms. +- `/drupal-best-practices-text-formats` → Section 2.8 Text formats and editors: single HTML format, CKEditor, aligned buttons/tags, limited switching. +- `/drupal-best-practices-theming` → Section 3 Theming, templates: one-word theme names, twig-first, preprocess classes, minimal overrides, SCSS with shared breakpoints, semantic class prefixes. diff --git a/ai/rules.md b/ai/rules.md new file mode 100644 index 0000000..75b10cb --- /dev/null +++ b/ai/rules.md @@ -0,0 +1,11 @@ +# AI-Agnostic Rules for Drupal Best Practices + +Apply these Drupal 10+ rules across any CLI/editor tooling. They mirror README sections 2 and 3. + +- **Machine names:** Use single words without prefixes or suffixes tied to regions/themes; avoid collisions and keep them human-readable. +- **Content modeling (2.1–2.5):** Favor fewer bundles, singular labels, documented descriptions, and reusable fields with clear `field_[bundle]_[short]` naming. Treat blocks, taxonomies, media, and paragraphs with the same discipline and avoid hardcoded UUID content. +- **Views (2.6):** One view per display when possible, explicit admin metadata, permission-based access, entity view mode rendering, non-Ajax by default, and clear empty states. +- **Forms (2.7):** Default to Webform; core Contact only for trivial single-form needs. +- **Text formats (2.8):** Standardize on one HTML format using CKEditor; align toolbar buttons with allowed tags and restrict switching formats. +- **Theming (3):** One-word theme machine names without `theme` suffixes or base-theme coupling, atomic/twig-first approach, preprocess for classes, minimal overrides, SCSS with shared breakpoints, semantic class prefixes (`twig-`, `js-`), and avoid styling by path aliases. +- **Tooling:** Prefer composer, drush, and ddev for automation; keep guidance compatible with config synchronization and current Drupal core support. diff --git a/ai/scripts/validate-blocks.sh b/ai/scripts/validate-blocks.sh new file mode 100755 index 0000000..06a838a --- /dev/null +++ b/ai/scripts/validate-blocks.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Validate README section 2.2 Blocks rules. + +command -v drush >/dev/null 2>&1 || { echo "drush is required" >&2; exit 1; } + +drush php:eval ' +use Drupal\block_content\Entity\BlockContentType; +$fail = 0; +$storage = \Drupal::entityTypeManager()->getStorage("block_content_type"); +foreach ($storage->loadMultiple() as $type) { + $id = $type->id(); + $desc = trim((string) $type->getDescription()); + if (preg_match("/\s/", $id) || preg_match("/[^a-z0-9_]/", $id) || preg_match("/[A-Z]/", $id)) { + echo "[blocks] Machine name needs cleanup: $id\n"; + $fail = 1; + } + if (strpos($id, 'block_') === 0) { + echo "[blocks] Remove redundant block_ prefix from $id\n"; + $fail = 1; + } + if ($desc === '') { + echo "[blocks] Missing description for $id\n"; + $fail = 1; + } +} +if ($fail) { + exit(1); +} +' diff --git a/ai/scripts/validate-fields.sh b/ai/scripts/validate-fields.sh new file mode 100755 index 0000000..a30d0a9 --- /dev/null +++ b/ai/scripts/validate-fields.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Validate README section 2.5 Fields rules. + +command -v drush >/dev/null 2>&1 || { echo "drush is required" >&2; exit 1; } + +drush php:eval ' +use Drupal\field\Entity\FieldStorageConfig; +$fail = 0; +$storage = \Drupal::entityTypeManager()->getStorage("field_storage_config"); +foreach ($storage->loadMultiple() as $field) { + $id = $field->getName(); + $desc = trim((string) $field->getDescription()); + if (strpos($id, "field_") !== 0) { + echo "[fields] Field name should start with field_: $id\n"; + $fail = 1; + } + if (preg_match("/\s/", $id) || preg_match("/[^a-z0-9_]/", $id) || preg_match("/[A-Z]/", $id)) { + echo "[fields] Machine name needs cleanup: $id\n"; + $fail = 1; + } + if ($desc === '') { + echo "[fields] Missing description for $id\n"; + $fail = 1; + } +} +if ($fail) { + exit(1); +} +' diff --git a/ai/scripts/validate-nodes.sh b/ai/scripts/validate-nodes.sh new file mode 100755 index 0000000..206acae --- /dev/null +++ b/ai/scripts/validate-nodes.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Validate README section 2.1 Nodes rules against a Drupal 10+ site. +# Requires: drush, Drupal bootstrap. + +command -v drush >/dev/null 2>&1 || { echo "drush is required" >&2; exit 1; } + +drush php:eval ' +use Drupal\node\Entity\NodeType; +$fail = 0; +$storage = \Drupal::entityTypeManager()->getStorage("node_type"); +foreach ($storage->loadMultiple() as $type) { + $id = $type->id(); + $label = $type->label(); + $desc = trim((string) $type->getDescription()); + if (preg_match("/\s/", $id) || preg_match("/[^a-z0-9_]/", $id) || preg_match("/[A-Z]/", $id)) { + echo "[nodes] Machine name needs cleanup: $id\n"; + $fail = 1; + } + if (preg_match("/s$/", $label)) { + echo "[nodes] Label looks plural; prefer singular: $label ($id)\n"; + $fail = 1; + } + if ($desc === '') { + echo "[nodes] Missing description for $id\n"; + $fail = 1; + } + if ($type->isNewRevision()) { + echo "[nodes] Revisions enabled by default; confirm workflow need: $id\n"; + } +} +if ($fail) { + exit(1); +} +' diff --git a/ai/scripts/validate-taxonomy.sh b/ai/scripts/validate-taxonomy.sh new file mode 100755 index 0000000..2296c98 --- /dev/null +++ b/ai/scripts/validate-taxonomy.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Validate README section 2.3 Taxonomy rules. + +command -v drush >/dev/null 2>&1 || { echo "drush is required" >&2; exit 1; } + +drush php:eval ' +use Drupal\taxonomy\Entity\Vocabulary; +$fail = 0; +$storage = \Drupal::entityTypeManager()->getStorage("taxonomy_vocabulary"); +foreach ($storage->loadMultiple() as $vocab) { + $id = $vocab->id(); + $label = $vocab->label(); + if (preg_match("/\s/", $id) || preg_match("/[^a-z0-9_]/", $id) || preg_match("/[A-Z]/", $id)) { + echo "[taxonomy] Machine name needs cleanup: $id\n"; + $fail = 1; + } + if (preg_match("/s$/", $label)) { + echo "[taxonomy] Label looks plural; prefer singular: $label ($id)\n"; + $fail = 1; + } +} +if ($fail) { + exit(1); +} +' diff --git a/ai/scripts/validate-text-formats.sh b/ai/scripts/validate-text-formats.sh new file mode 100755 index 0000000..ecf21fb --- /dev/null +++ b/ai/scripts/validate-text-formats.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Validate README section 2.8 Text formats and editors rules. + +command -v drush >/dev/null 2>&1 || { echo "drush is required" >&2; exit 1; } + +drush php:eval ' +use Drupal\filter\Entity\FilterFormat; +$formats = FilterFormat::loadMultiple(); +if (count($formats) > 2) { + echo "[text formats] More than one HTML-capable format detected; aim for a single HTML format.\n"; +} +foreach ($formats as $format) { + $name = $format->id(); + $filters = $format->filters(); + if (strpos($name, "html") !== false && empty($format->getRoles())) { + echo "[text formats] Ensure access to $name is scoped to roles, not open to all.\n"; + } + if ($filters->has('filter_html')) { + $allowed = $filters->get('filter_html')->getConfiguration()['allowed_html'] ?? ''; + if ($allowed === '') { + echo "[text formats] Allowed HTML empty for $name; align toolbar buttons with allowed tags.\n"; + } + } +} +' diff --git a/ai/scripts/validate-theming.sh b/ai/scripts/validate-theming.sh new file mode 100755 index 0000000..5ff769e --- /dev/null +++ b/ai/scripts/validate-theming.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Validate README section 3 Theming rules. + +command -v drush >/dev/null 2>&1 || { echo "drush is required" >&2; exit 1; } + +drush php:eval ' +use Drupal\system\Entity\Theme; +$fail = 0; +$themes = Theme::loadMultiple(); +foreach ($themes as $theme) { + $id = $theme->id(); + if (preg_match("/\s/", $id) || preg_match("/[^a-z0-9_]/", $id) || preg_match("/[A-Z]/", $id)) { + echo "[theming] Theme machine name should be one word lowercase: $id\n"; + $fail = 1; + } + if (strpos($id, 'theme') !== false) { + echo "[theming] Remove redundant 'theme' substring from $id\n"; + $fail = 1; + } + $base = $theme->getBaseTheme(); + if ($base && strpos($id, $base) !== false) { + echo "[theming] Subtheme machine name should not include base theme ($base): $id\n"; + $fail = 1; + } +} +if ($fail) { + exit(1); +} +' diff --git a/ai/scripts/validate-views.sh b/ai/scripts/validate-views.sh new file mode 100755 index 0000000..098ff8e --- /dev/null +++ b/ai/scripts/validate-views.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Validate README section 2.6 Views rules. + +command -v drush >/dev/null 2>&1 || { echo "drush is required" >&2; exit 1; } + +drush php:eval ' +use Drupal\views\Views; +$fail = 0; +$storage = \Drupal::entityTypeManager()->getStorage("view"); +foreach ($storage->loadMultiple() as $view) { + $id = $view->id(); + $human = $view->label(); + if (preg_match("/\s/", $id) || preg_match("/[^a-z0-9_]/", $id) || preg_match("/[A-Z]/", $id)) { + echo "[views] Machine name needs cleanup: $id\n"; + $fail = 1; + } + if ($human === $id || $human === '') { + echo "[views] Missing descriptive label for $id\n"; + $fail = 1; + } + foreach ($view->get('display') as $display_id => $display) { + if (substr($display_id, -2) === '_1') { + echo "[views] Rename default _1 display id in $id ($display_id)\n"; + $fail = 1; + } + if (empty($display['display_title'])) { + echo "[views] Missing display title for $id::$display_id\n"; + $fail = 1; + } + } +} +if ($fail) { + exit(1); +} +'