Search by

protonsystems / demo-content

proton.systems

Reusable deterministic demo-content generation for paragraph-heavy Drupal projects.

Package info

gitlab.com/Proton.Systems/drupal/demo-content

Issues

Type:drupal-module

pkg:composer/protonsystems/demo-content

Statistics

Installs: 18

Dependents: 0

Suggesters: 0

Stars: 0

v1.1.2 2026-09-14 21:34 UTC

This package is auto-updated.

Last update: 2026-09-15 02:34:34 UTC


README

Reusable Drupal module for generating deterministic demo content on paragraph-heavy sites.

Purpose

The module is intended to be reused across Drupal 10 and Drupal 11 projects by installing it as a Composer package and enabling it in the target site.

What it does

  • creates a deterministic node for a chosen content type;
  • discovers the main paragraph field automatically;
  • creates one instance of every allowed top-level paragraph bundle;
  • recurses into nested paragraph fields;
  • creates or reuses referenced media, nodes, terms, and other entities;
  • skips problematic computed/internal fields such as node menu_link;
  • creates the site's standard boilerplate pages (Home, Privacy Policy, Legal Notice, Contact) with real placeholder copy, a recommended URL alias, and Home set as the front page;
  • tracks every entity it generates so it can all be deleted again with one command.

Requirements

  • PHP 8.3+
  • Drupal 10 or 11
  • Paragraphs
  • Drush 12+

Commands

drush demo-content:coverage-node <bundle> (alias: demo:coverage-node)

Creates one coverage node for the requested node bundle. The command requires a paragraph field on that bundle, either auto-detected or supplied explicitly. It creates one top-level instance of every allowed paragraph bundle and then recurses into nested paragraph/reference fields.

drush demo-content:coverage-node page
drush demo-content:coverage-node page --replace

Options:

  • --title=<text>: use a custom node title instead of the generated default
  • --paragraph-field=<machine_name>: override paragraph field auto-detection
  • --nested-repeat=<n>: repeat single-bundle nested paragraph/reference lists; defaults to 2
  • --replace: delete an existing node with the same bundle/title before creating the new coverage node

Examples:

drush demo-content:coverage-node page --title="Paragraph coverage page"
drush demo-content:coverage-node page --paragraph-field=field_paragraphs
drush demo-content:coverage-node page --nested-repeat=3
drush demo-content:coverage-node page --replace

drush demo-content:coverage-all (alias: demo:coverage-all)

Creates one demo node for every requested node bundle. If --bundles is not provided, the module runs across all available node bundles in stable sorted order. Bundles without a paragraph field are still created; those nodes are logged as created without paragraph coverage.

drush demo-content:coverage-all
drush demo-content:coverage-all --bundles=page,project --replace

Options:

  • --bundles=<bundle1,bundle2>: comma-separated node bundles; defaults to all node bundles
  • --nested-repeat=<n>: repeat single-bundle nested paragraph/reference lists; defaults to 2
  • --replace: delete an existing generated node with the same bundle/title before recreating it

Examples:

drush demo-content:coverage-all --bundles=page,project
drush demo-content:coverage-all --bundles=page,project --nested-repeat=3 --replace

drush demo-content:create-standard-pages (alias: demo:standard-pages)

Creates the site's standard boilerplate pages — Home, Privacy Policy, Legal Notice, Contact — as page nodes (or another bundle via --bundle), each with real placeholder copy (not synthetic coverage data), a recommended URL alias, and Home set as the site's front page.

drush demo-content:create-standard-pages
drush demo-content:create-standard-pages --pages=privacy_policy,legal_notice
drush demo-content:create-standard-pages --replace

Recommended/default URLs: /home (also set as front page), /privacy-policy, /legal-notice, /contact.

Options:

  • --bundle=<machine_name>: node bundle to use; defaults to page
  • --pages=<id1,id2>: comma-separated subset of home, privacy_policy, legal_notice, contact; defaults to all four
  • --replace: delete an existing page with the same title before creating it
  • --no-front: don't set Home as the site front page

Node IDs are never forced — Drupal assigns them automatically. On a fresh install with an empty node table, Home (created first) naturally becomes node 1.

Language: pages are currently created in English only. A --langcode option (so a German-default site can get Impressum instead of Legal Notice, for example) is planned but not yet implemented — see STANDARD_PAGES in DemoContentGenerator for the extension point.

drush demo-content:purge (alias: demo:purge)

Deletes every entity this module has generated — across every past command invocation, not just the most recent one. This covers top-level nodes, nested paragraphs, and any referenced media/taxonomy/nodes/other entities created along the way, plus any path aliases created by demo-content:create-standard-pages.

drush demo-content:purge
drush demo-content:purge --dry-run

Options:

  • --dry-run: report what would be deleted without deleting anything
  • --no-legacy-scan: skip the title-pattern sweep described below

Generated entities are tracked in Drupal State as they're created, so purge doesn't need to guess what's demo content — with one exception: content created by a module version before this tracking existed has no State record. To handle that, purge also sweeps for nodes titled with the Demo coverage: prefix that demo-content:coverage-node/coverage-all use by default (not the paragraphs/media/other entities those runs also created, since only that node title prefix is distinctive enough to be a safe, generic content signal). A node created with a custom --title bypasses this sweep; going forward, any run of this module tracks entities exactly, regardless of title.

Installation

composer require protonsystems/demo-content
drush en demo_content

Extension points

The generic engine lives in a service, while project-specific customizations can be added via alter and presave hooks documented in demo_content.api.php.

Releasing A New Version On Packagist

Packagist publishes versions of protonsystems/demo-content from git tags. Do not add a version field to composer.json; create and push a new release tag instead.

For the first public release, submit the public Git repository URL to Packagist. If you want automatic updates from GitLab, configure the Packagist integration in GitLab under Settings > Integrations using your Packagist username and API token.

Prepare the release commit on main:

git checkout main
git pull origin main
composer validate --no-check-publish --strict
git status
git add <files>
git commit -m "Release v1.0.0"
git push origin main

Create and push an annotated tag for the release:

git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0

Use semantic version tags such as v1.0.0. After the tag is pushed, Packagist should detect the new version automatically. If it does not appear, open the package page in Packagist and trigger a manual update.