Add constraints section documenting that the woocommerce plugin is read-only and that the Docker environment is not yet set up. Track composer.lock. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 KiB
WooCommerce Bootstrap
Author: Marco Grätsch Author URL: https://src.bundespruefstelle.ch/magdev Author Email: magdev3.0@gmail.com Repository URL: ssh://git@src.bundespruefstelle.ch:2022/magdev/wc-bootstrap.git Issues URL: ssh://git@src.bundespruefstelle.ch:2022/magdev/wc-bootstrap.git/issues
Project Overview
This child theme of wp-bootstrap (../wp-bootstrap/ or https://src.bundespruefstelle.ch/magdev/wp-bootstrap) extends wp-bootstrap and adds overrides for all theme files of the WooCommerce plugin (../../plugins/woocommerce/ or https://github.com/woocommerce/woocommerce.git). All theme files from the plugin are converted to Bootstrap 5 structures and styles.
Technical Stack
- Language: PHP 8.3.x
- Framework: Latest WordPress Theme API
- Template Engine: Twig 3.0 (via Composer)
- WordPress Base Theme: wp-bootstrap
- Frontend: Bootstrap 5 JavaScript & Vanilla JavaScript
- Styling: Bootstrap 5 & Custom CSS (if necessary)
- Dependency Management: Composer (PHP), npm (JS/CSS)
- Internationalization: WordPress i18n (.pot/.po/.mo files)
Security Best Practices
- All user inputs are sanitized (integers for quantities/prices)
- Nonce verification on form submissions
- Output escaping in templates (
esc_attr,esc_html,esc_js) - Direct file access prevention via
ABSPATHcheck - XSS-safe DOM construction in JavaScript (no
innerHTMLwith user data) json_encode|rawin JS context is correct (not XSS) -- Twig auto-escaping would break JSONstyles|rawin PDF exports is backend-generated static CSS, documented with comments
Translation Ready
All user-facing strings use:
__('Text to translate', 'wc-bootstrap')
_e('Text to translate', 'wc-bootstrap')
Text domain: wc-bootstrap
Text Domain Strategy
Option A -- Plugin domain (recommended when plugin provides Twig functions):
All strings in theme templates use the plugin's 'woocommerce' domain. This is necessary when the plugin registers __() / _n() as Twig functions with a default domain, because load_child_theme_textdomain() does not resolve at Twig render time.
Rule: Always use 'woocommerce' as the text domain in all Twig templates and PHP files.
Option B -- Theme domain (when theme handles its own Twig rendering):
Theme templates use the theme's own 'wc-bootstrap' domain. Ensure load_child_theme_textdomain() is called before Twig rendering.
Available Translations
en_US-- English (base language, .pot template)de_DE-- German (Germany, formal)de_CH-- German (Switzerland, formal)fr_FR-- French (France)
Translation file naming convention: wc-bootstrap-{locale}.po (e.g., wc-bootstrap-de_CH.po)
Compiled .mo files are built by the CI/CD pipeline during releases. For local development:
for po in languages/wc-bootstrap-*.po; do msgfmt -o "${po%.po}.mo" "$po"; done
Updating Translations (Fast JSON Workflow)
Step 1 -- Regenerate .pot files
wp-bootstrap (PHP sources only):
docker exec woocommerce-wordpress wp i18n make-pot \
/var/www/html/wp-content/themes/wp-bootstrap \
/var/www/html/wp-content/themes/wp-bootstrap/languages/wp-bootstrap.pot \
--allow-root
Child theme (PHP + Twig). Use a Twig extractor script that scans .html.twig files for __(), _e(), _n(), _x() calls, generates twig-extracted.pot, then merges with WP-CLI PHP extraction:
# Inside languages/ directory:
python3 twig-extractor.py # generates twig-extracted.pot
docker exec woocommerce-wordpress wp i18n make-pot \
/var/www/html/wp-content/themes/wc-bootstrap \
/var/www/html/wp-content/themes/wc-bootstrap/languages/php-extracted.pot \
--allow-root
msgcat --use-first php-extracted.pot twig-extracted.pot \
-o wc-bootstrap.pot
rm php-extracted.pot
Step 2 -- Merge new strings into all .po files
for locale in de_CH de_DE fr_FR; do
msgmerge --update --backup=none --no-fuzzy-matching \
wc-bootstrap-${locale}.po wc-bootstrap.pot
done
Step 3 -- Translate and apply
Extract untranslated strings per locale into JSON, translate (via AI or manual), then apply with languages/patch-po.py.
German variant derivation rules:
de_CHfromde_DE: replacesswhere Swiss German usesssinstead ofßde_DE_informalfromde_DE:Sie->du,Ihr->dein, etc.de_CH_informal: combine both transformations
Step 4 -- Validate and compile
for po in languages/wc-bootstrap-*.po; do msgfmt --statistics "$po" -o /dev/null; done
for po in languages/wc-bootstrap-*.po; do msgfmt -o "${po%.po}.mo" "$po"; done
Important Git Notes
- Default branch while development is
dev - Create releases from branch
mainafter merging branchdev - Tags should use format
vX.X.X(e.g.,v1.1.22), start with v0.1.0 - Use annotated tags (
-a) not lightweight tags - ALWAYS push tags to origin -- CI/CD triggers on tag push
- Commit messages should follow the established format with Claude Code attribution
.claude/settings.local.jsonchanges are typically local-only (stash before rebasing)
CRITICAL -- Release Workflow
On every new version, ALWAYS execute this complete workflow:
# 1. Commit changes to dev branch
git add <files>
git commit -m "Description of changes (vX.X.X)"
# 2. Merge dev to main
git checkout main
git merge dev --no-edit
# 3. Create annotated tag
git tag -a vX.X.X -m "Version X.X.X - Brief description"
# 4. Push everything to origin
git push origin dev main vX.X.X
# 5. Switch back to dev for continued development
git checkout dev
Never skip any of these steps. The release is not complete until all branches and the tag are pushed to origin.
CRITICAL -- Cross-Project Release Order
When a release touches both the plugin and the theme, ALWAYS release in this order:
- Theme first -- full release workflow (commit -> merge -> tag -> push)
- Plugin second -- update plugin's Dockerfile/config to reference the new theme version, then full release workflow
Reason: the plugin's build references the theme version. If the plugin is released first with a new theme version number, the CI build will attempt to download a theme release that does not yet exist and fail.
For AI Assistants
When starting a new session on this project:
- Read this CLAUDE.md file first
- Semantic versioning follows the
MAJOR.MINOR.BUGFIXpattern - Check git log for recent changes
- Verify you're on the
devbranch before making changes - Run
git submodule update --init --recursiveif lib/ is empty (only if submodules present) - Run
composer installif vendor/ is missing - Test changes before committing
- Follow commit message format with Claude Code attribution
- Update this session history section with learnings
- Never commit backup files (
*.po~,*.bak, etc.) - checkgit statusbefore committing - Follow markdown linting rules (see below)
Always refer to this document when starting work on this project.
Markdown Linting Rules
- MD031: Blank lines before and after fenced code blocks
- MD056: Table separators must have matching column counts
- MD009: No trailing spaces
- MD012: No multiple consecutive blank lines
- MD040: Fenced code blocks should have a language specified
- MD032: Lists surrounded by blank lines
- MD034: Bare URLs in angle brackets or markdown link syntax
- MD013: Disabled (line length)
- MD024:
siblings_onlymode
Known Pitfalls & Key Learnings
Recurring bugs and non-obvious behaviours discovered across sessions. Read this before starting any task.
Template Override Mechanism
- Plugin's
Templateclass uses TwigFilesystemLoader. Theinc/TemplateOverride.phphooksinitat priority 20 (after plugin init at 0) and usesprependPath()to give child theme templates priority. - Plugin templates in
../../plugins/woocommerce/templates/are overridden by matching files intemplates/.
Twig Compatibility
|valuesfilter does NOT exist in Twig 3.x -- use loop-based sum instead. Twig 4.x only.- Twig autoescape + WordPress escape filters = double encoding -- register all
esc_*filters with['is_safe' => ['html']]option in the plugin'sTemplate.php. wp i18n make-potdoes NOT scan Twig templates -- any string used exclusively in.html.twigfiles must be manually added to the.potfile.#, fuzzysilently skips translations at runtime -- always remove fuzzy flags after verifying translations.
Bootstrap 5 vs Plugin CSS Conflicts
- Plugin CSS may define its own grid systems that override Bootstrap's flexbox
row row-cols-*. Add theme CSS overrides as needed. - CSS dependency chain:
woocommerce-> child theme overrides. Ensures correct cascade. - jQuery
.show()/.hide()cannot override Bootstrap!important(d-none). Toggle both class and inline style. overflow: visible !importanton.wp-block-navigation__containeris essential for dropdowns inside block theme navigation.
Double Heading Prevention
- Parent theme (
wp-bootstrap) conditionally skips its<h1>whenpost.titleis empty. - Plugin passes empty
post.titleto parent theme's Twig system. - Child theme layout templates always render their own
<h1>withpage_titlecontext.
Theme Wrapping (_wrapped / _theme_wrapped)
_wrappedis set inbase.html.twigwhen_theme_wrappedis true (parent theme provides page shell).- Structural blocks (wrapper, breadcrumbs, sidebar,
<h1>) are suppressed when wrapped. - Functional blocks (
{% block scripts %}) must ALWAYS render -- they contain AJAX handlers, JS initialization etc.
Plugin JS Compatibility
- Theme must preserve plugin's JS-bound CSS class names (e.g., repeater fields, interactive widgets).
- Theme uses plugin's global JS objects for AJAX URLs, nonces, and i18n strings.
- Bootstrap 5
data-bs-toggleattributes replace plugin's custom dropdown mechanisms.
Security
- Security audit checklist (OWASP Top-10): open redirect validation,
|esc_url/|esc_attr/|esc_json all dynamic output,|wp_kses_postfor rich text, noinnerHTMLwith dynamic data.
Multi-Project Architecture
This child theme is part of a three-project ecosystem. Each project is a separate git repo with its own CLAUDE.md and should be worked on in separate Claude Code sessions.
Projects
| Project | Type | Location | Repository |
|---|---|---|---|
| woocommerce | Plugin (read-only) | wp-content/plugins/woocommerce/ |
https://github.com/woocommerce/woocommerce.git |
| wp-bootstrap | Parent Theme | wp-content/themes/wp-bootstrap/ |
https://src.bundespruefstelle.ch/magdev/wp-bootstrap |
| wc-bootstrap | Child Theme | wp-content/themes/wc-bootstrap/ |
ssh://git@src.bundespruefstelle.ch:2022/magdev/wc-bootstrap.git |
Dependency Chain
wp-bootstrap (parent theme, Bootstrap 5 FSE + Twig rendering)
+-- wc-bootstrap (child theme, overrides plugin Twig templates with Bootstrap 5)
+-- woocommerce (plugin, provides post types, logic, base Twig templates)
Important Constraints
- WooCommerce plugin is read-only. We have no control over its source code. All customizations happen in the child theme via template overrides and hooks.
- Docker environment is not yet set up. Commands referencing
docker exec(e.g., in the translation workflow) are not currently available. Local alternatives or manual steps must be used until the container is configured.
Cross-Project Workflow
- One session per project. Each session reads its own
CLAUDE.mdand stays within its own git repo. - Plugin changes first. When a change affects templates consumed by the theme, make the plugin change first, then switch to the theme session.
- Communicate changes explicitly. When switching sessions, describe what changed upstream (new variables, renamed classes, new templates, etc.).
- Shared Docker environment. All three projects will be bind-mounted into the same Docker container once it is set up, so changes will be visible live without rebuilds.
Template Contract (Plugin -> Theme)
The child theme overrides plugin Twig templates by prepending its own templates/ directory to the Twig FilesystemLoader via TemplateOverride class (hooks init priority 20, after plugin init at priority 0).
Twig Template Locations
- Plugin base templates:
wp-content/plugins/woocommerce/templates/ - Theme overrides:
wp-content/themes/wc-bootstrap/templates/(mirrors plugin structure) - Resolution order: Theme templates take priority over plugin templates (Twig
prependPath)
Theme Contract (Parent -> Child)
The child theme inherits from wp-bootstrap via WordPress Template: wp-bootstrap declaration.
- Bootstrap 5: CSS framework and JS loaded by parent theme
- Bootstrap Icons: Web font available via parent theme's SCSS build
- Twig rendering: Parent theme's
TwigServicehandles frontend rendering - Dark mode: Parent handles via
data-bs-themeattribute; child theme inherits - Style variations: Color palettes available from parent, bridged to Bootstrap CSS custom properties
Architecture Decisions
- Edit forms use 3+9 column layout:
col-lg-3sticky sidebar (progress indicator, section nav) +col-lg-9card-based sections. - Detail pages use 8+4 column layout with sticky sidebar.
- Cards use
<article class="card h-100">withstretched-link. - Form layout uses centered
col-lg-8 col-xl-7with card + shadow for auth forms. - Mobile patterns: offcanvas for search filters; navbar uses Bootstrap
offcanvas-lgresponsive pattern. - Email templates: use custom CSS class prefix (not Bootstrap) to avoid email client conflicts.
- PDF exports: inline styles aligned with Bootstrap color palette (no external CSS in PDF renderers).
Version History
Current version: v0.1.0