Create LightSpeed WordPress block theme starter scaffold#1
Conversation
Agent-Logs-Url: https://github.com/lightspeedwp/ls-starter-theme/sessions/6a4253bf-b774-4e6a-ade7-a37816c06ed7 Co-authored-by: ashleyshaw <1805352+ashleyshaw@users.noreply.github.com>
Agent-Logs-Url: https://github.com/lightspeedwp/ls-starter-theme/sessions/6a4253bf-b774-4e6a-ade7-a37816c06ed7 Co-authored-by: ashleyshaw <1805352+ashleyshaw@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Creates a reusable LightSpeed WordPress block theme starter repository, including a minimal block theme skeleton plus validation/linting tooling and AI-assistance scaffolding (Copilot instructions, prompts, agents, tasks, reports) intended to be used as a GitHub template.
Changes:
- Adds a baseline block theme (theme.json, templates/parts, style variations, assets/inc/patterns scaffolding).
- Introduces Node/Composer tooling (
theme-utils.mjs, npm scripts, PHPCS) and lint-staged hooks. - Adds GitHub automation and AI workflow structure (.github workflows, instructions, prompts, tasks/reports, agent personas/skills).
Reviewed changes
Copilot reviewed 47 out of 62 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| theme.json | Base theme.json tokens/settings + template part registration |
| theme-utils.mjs | Node utility for schema validation, theme consistency checks, and PHP scans |
| templates/index.html | Default index block template using header/footer template parts and Query loop |
| parts/header.html | Starter header template part (site title + navigation) |
| parts/footer.html | Starter footer template part |
| styles/light.json | Light style variation starter |
| styles/dark.json | Dark style variation starter |
| styles/blocks/.gitkeep | Placeholder for per-block style JSON organization |
| styles/sections/.gitkeep | Placeholder for per-section style JSON organization |
| style.css | Theme header metadata (placeholders) |
| readme.txt | Distribution placeholder readme.txt |
| functions.php | Minimal theme setup/enqueue scaffold |
| inc/.gitkeep | Placeholder for optional PHP includes |
| patterns/.gitkeep | Placeholder for block patterns |
| assets/fonts/.gitkeep | Placeholder for font assets |
| assets/icons/.gitkeep | Placeholder for icons |
| assets/logos/.gitkeep | Placeholder for logos |
| assets/images/.gitkeep | Placeholder for images |
| assets/css/.gitkeep | Placeholder for CSS assets |
| assets/js/.gitkeep | Placeholder for JS assets |
| package.json | npm scripts + dev deps for schema/validation utilities |
| package-lock.json | Locked npm dependency tree for CI reproducibility |
| composer.json | PHP tooling dependencies and scripts (PHPCS/WPCS/PHPCompatibility) |
| .nvmrc | Node version pinning for local/CI |
| .lintstagedrc.json | Pre-commit checks for JSON schema + PHP lint/PHPCS |
| .gitignore | Ignore rules for Node/Composer/dev artifacts |
| .gitattributes | Line-ending normalization + export-ignore rules |
| .editorconfig | Editor settings per file type |
| .coderabbit.yml | CodeRabbit review configuration with path-specific instructions |
| CODEOWNERS | Code ownership rules (currently placeholder-based) |
| README.md | Main developer README for the starter repo |
| CHANGELOG.md | Keep a Changelog/SemVer scaffold |
| AGENTS.md | Primary AI/developer guidance and repo conventions |
| CLAUDE.md | Pointer to AGENTS.md for AI agent guidance |
| docs/README.md | End-user documentation guidance |
| docs/.gitkeep | Placeholder for docs folder |
| .github/README.md | Explains .github folder purpose and contents |
| .github/copilot-instructions.md | Copilot context + command overview + file locations |
| .github/instructions/README.md | Index of instruction modules |
| .github/instructions/php.instructions.md | PHP-specific guidance (escaping/sanitization/translation) |
| .github/instructions/patterns.instructions.md | Pattern file guidance (headers/escaping/markup) |
| .github/instructions/templates.instructions.md | Template/part guidance (block markup/semantics/a11y) |
| .github/instructions/theme-json.instructions.md | theme.json/style variation guidance |
| .github/instructions/workflows.instructions.md | Workflow authoring/modification guidance |
| .github/prompts/README.md | Prompt file usage and listing |
| .github/prompts/audit-theme.prompt.md | Prompt to audit theme correctness/security/a11y/etc. |
| .github/prompts/cleanup.prompt.md | Prompt to identify cleanup opportunities and follow-ups |
| .github/prompts/new-pattern.prompt.md | Prompt to generate a new block pattern with best practices |
| .github/prompts/release.prompt.md | Prompt to prepare a versioned release |
| .github/reports/README.md | Report conventions (naming/location) |
| .github/reports/.gitkeep | Placeholder for reports folder |
| .github/tasks/README.md | Task list conventions (naming/status) |
| .github/tasks/task-list.md | Starter task checklist for setup/dev/quality |
| .github/tasks/.gitkeep | Placeholder for tasks folder |
| .github/workflows/ci.yml | CI job: npm install + schema/theme validation + JSON lint |
| .github/workflows/code-quality.yml | PHP lint/PHPCS + Node security/escaping scans |
| .github/workflows/release.yml | Tag-driven GitHub release creation with changelog extraction |
| .agents/README.md | Explains portable agent assets structure |
| .agents/skills/README.md | Index for reusable skills |
| .agents/skills/block-theme-audit/SKILL.md | Portable “block theme audit” skill definition |
| .agents/agents/README.md | Index for agent personas |
| .agents/agents/theme-architect.md | “Theme Architect” persona definition |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import { createRequire } from 'module'; | ||
|
|
||
| const require = createRequire( import.meta.url ); | ||
|
|
There was a problem hiding this comment.
createRequire is imported and require is created, but require is never used in this script. Removing the unused import/variable will keep the file lean and avoid implying CommonJS interop is needed.
| Version: 0.1.0 | ||
| Requires at least: 6.4 | ||
| Tested up to: 6.7 | ||
| Requires PHP: 8.1 |
There was a problem hiding this comment.
The theme header says Requires at least: 6.4, but theme.json/style variations are set to "version": 3 (typically WP 6.6+). Please align the minimum WordPress version with the theme.json version so users don’t install this on unsupported WP versions.
| "name": "{{THEME_SLUG}}", | ||
| "version": "0.1.0", |
There was a problem hiding this comment.
package.json "name" uses the placeholder "{{THEME_SLUG}}", which is not a valid npm package name (curly braces/uppercase) and will cause npm install/npm ci to fail. Consider using a valid default name in the template (and optionally document how to change it later), or switch to a placeholder format that remains npm-valid.
| let Ajv, addFormats; | ||
| try { |
There was a problem hiding this comment.
addFormats is declared but never used. If you don’t intend to support ajv-formats here, this variable can be removed.
| // Check for unreplaced placeholder tokens. | ||
| info( '\nChecking for unreplaced placeholder tokens…' ); | ||
| // Exclude generated lock files and dependency directories from placeholder scan. | ||
| const excludeDirs = [ 'node_modules', 'vendor' ]; | ||
| const excludeFiles = [ 'package-lock.json', 'composer.lock' ]; | ||
| const isExcluded = ( f ) => | ||
| excludeDirs.some( d => f.includes( `/${ d }/` ) || f.includes( `\\${ d }\\` ) ) || | ||
| excludeFiles.some( name => f.endsWith( `/${ name }` ) || f.endsWith( `\\${ name }` ) ); | ||
|
|
||
| const textFiles = [ | ||
| ...collectFiles( ROOT, '.css' ).filter( f => ! isExcluded( f ) ), | ||
| ...collectFiles( ROOT, '.php' ).filter( f => ! isExcluded( f ) ), | ||
| ...collectFiles( ROOT, '.json' ).filter( f => ! isExcluded( f ) ), | ||
| ...collectFiles( ROOT, '.html' ).filter( f => ! isExcluded( f ) ), | ||
| ...collectFiles( ROOT, '.md' ).filter( f => ! isExcluded( f ) ), | ||
| ...collectFiles( ROOT, '.txt' ).filter( f => ! isExcluded( f ) ), | ||
| ]; |
There was a problem hiding this comment.
validate-theme builds textFiles by calling collectFiles(ROOT, ext) multiple times and only filters out node_modules/ and vendor/ after the recursive walk. In CI, npm ci creates node_modules/, so this will still traverse a very large directory tree and can make validation slow/flaky. Consider teaching collectFiles to skip excluded directories during traversal (or do a single walk and filter by extension).
| @@ -0,0 +1,32 @@ | |||
| <!-- wp:template-part {"slug":"header","tagName":"header"} /--> | |||
There was a problem hiding this comment.
The template-part block sets tagName:"header", but parts/header.html already renders a <header> (via a Group with tagName:"header"). This will produce nested <header> landmarks (<header><header>…</header></header>), which is semantically incorrect and can confuse assistive tech. Consider making the template-part wrapper tagName:"div" (or removing the <header> tag from the part) so there’s only one header landmark.
| <!-- wp:paragraph {"fontSize":"small"} --> | ||
| <p class="has-small-font-size">© <!-- wp:site-title /--></p> | ||
| <!-- /wp:paragraph --> |
There was a problem hiding this comment.
The footer template nests a wp:site-title block comment inside a Paragraph block’s HTML (<p>© <!-- wp:site-title /--></p>). Gutenberg block parsing generally won’t treat nested block comments inside another block’s inner HTML as a real nested block, so the site title may not render as intended. Consider restructuring this as separate sibling blocks (e.g., a Group with a Paragraph and a Site Title block) or using a single block that can render the desired markup.
CODEOWNERS
Outdated
| # Default owner for all files | ||
| * @{{GITHUB_ORG}}/developers | ||
|
|
||
| # Theme core files | ||
| style.css @{{GITHUB_ORG}}/developers | ||
| theme.json @{{GITHUB_ORG}}/developers |
There was a problem hiding this comment.
CODEOWNERS entries use placeholders inside the owner handles (e.g. @{{GITHUB_ORG}}/developers). GitHub CODEOWNERS requires real GitHub usernames/teams, so these placeholders will be treated as invalid and won’t assign reviewers. Consider using a real default team for the template repo (or moving placeholders to comments and leaving valid fallback owners).
| </main> | ||
| <!-- /wp:group --> | ||
|
|
||
| <!-- wp:template-part {"slug":"footer","tagName":"footer"} /--> |
There was a problem hiding this comment.
The template-part block sets tagName:"footer", but parts/footer.html already renders a <footer> element. This will produce nested <footer> landmarks, which is semantically incorrect and can confuse assistive tech. Consider using a non-landmark wrapper for the template-part (e.g. tagName:"div") or removing the <footer> tag from the part.
Signed-off-by: Ash Shaw <ashley@lightspeedwp.agency>
Updated CODEOWNERS to assign ownership to @lightspeedwp/developers. Signed-off-by: Ash Shaw <ashley@lightspeedwp.agency>
Builds a lean, production-aware GitHub template repository for LightSpeed's custom WordPress block theme development, including AI workflow infrastructure.
Theme skeleton
style.css— block theme header with placeholder tokenstheme.jsonv3 — spacing scale, 6-colour palette, 6 font sizes, layout constraints, template part registrationfunctions.php— minimal setup (textdomain, block styles, editor styles, commented enqueue stubs)templates/index.html,parts/header.html,parts/footer.html— valid FSE markup with semantictagNameattributesstyles/light.json+styles/dark.json— starter style variationsfonts/,icons/,logos/,images/,css/,js/) with.gitkeepTooling
theme-utils.mjs— custom validation script with four commands:validate-schema— validatestheme.json+styles/**/*.jsonagainst WordPress schema (fetch with JSON-parse fallback); explicitly excludesassets/fonts/(binary, not JSON)validate-theme— checks required files, scans for unreplaced{{PLACEHOLDER}}tokens, validates text domain consistencyescape-patterns— scanspatterns/*.phpandinc/for unescapedecho, missing text domains, direct superglobal outputsecurity-scan— flagseval(), direct superglobal output, unprepared DB queriespackage.json—type: "module", minimal deps (ajv,glob), six npm scriptscomposer.json— PHPCS/PHPCBF with WordPress coding standards + PHPCompatibility.lintstagedrc.json— pre-commit schema validation fortheme.json+styles/**/*.jsononly (no font files).coderabbit.yml— per-path review instructions covering security, escaping, accessibility, theme.json consistencyAI workflow infrastructure
AGENTS.md— primary guidance: structure, theme-first approach, placeholder strategy, security/accessibility rules, full command reference, 16 agent rulesCLAUDE.md— points toAGENTS.md.github/copilot-instructions.md— Copilot-native entry point referencingAGENTS.mdand instruction files.github/instructions/— scoped instruction files for PHP, patterns, templates,theme.json, workflows.github/prompts/— four reusable prompt files:audit-theme,cleanup,new-pattern,release.github/reports/+.github/tasks/— READMEs defining naming conventions and agent update rules.agents/skills/block-theme-audit/SKILL.md— portable structured audit skill.agents/agents/theme-architect.md— specialist persona definitionGitHub Actions
ci.yml— Node install → schema validate → theme validate → lint JSONcode-quality.yml— PHP lint + PHPCS; security scan + escape checkrelease.yml— validates on tag push, extracts changelog entry, creates GitHub Releasepermissions: contents: read(or explicit write only where required)Placeholder strategy
Consistent
{{THEME_NAME}},{{THEME_SLUG}},{{TEXT_DOMAIN}}, etc. throughout.theme:validateflags all unreplaced tokens at setup time and excludes generated files (package-lock.json,composer.lock).Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
schemas.wp.org/home/REDACTED/work/_temp/ghcca-node/node/bin/node node theme-utils.mjs validate-schema(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
LightSpeed WordPress Block Theme Starter Repo — Generation Prompt
You are a senior WordPress block theme engineer, repository architect, and AI workflow designer.
Your task is to generate a lean, production-aware starter GitHub template repository for LightSpeed’s GitHub organisation for building custom WordPress block themes for client and commercial work.
This is not a WordPress.org submission starter.
Do not over-engineer it.
Stay close to WordPress block theme best practices, security, accessibility, maintainability, and theme development guidelines where sensible, but do not add unnecessary WordPress.org-only bureaucracy.
The repository must support both:
The repository should feel like a clean starter for developers and a structured workspace for AI agents.
Core Intent
Build a reusable starter repo that:
docs/folder for end-user documentationReference Material To Review First
Use these references as source material and inspiration before generating anything.
WordPress community-themes references
Ollie references
LightSpeed references
Changelog standards
Important Corrections And Constraints
There is a known mistake in the WordPress community-themes setup that references validating:
assets/fonts/*.jsonDo not copy that mistake.
Rules:
assets/fonts/contains binary font assets such as.woff2theme.jsonstyles/*.jsonstyles/blocks/styles/sections/If you include any other JSON validation targets, explain why.
Design Principles
theme.jsonover unnecessary PHPfunctions.phpminimalCODEOWNERSPlaceholder Strategy
Use clear placeholder tokens consistently throughout the repo instead of blank metadata values.
Use placeholders such as:
{{THEME_NAME}}{{THEME_SLUG}}{{TEXT_DOMAIN}}{{THEME_URI}}{{AUTHOR_NAME}}{{AUTHOR_URI}}{{THEME_DESCRIPTION}}{{REPO_NAME}}{{GITHUB_ORG}}Rules:
Repository Requirements
This starter repo must include:
theme-utils.mjs