diff --git a/CHANGELOG.md b/CHANGELOG.md index 77ae6f8..6c4188d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed +- **The content-creation guides**, now three posts on wpvilla.in: [creating pages from block markup](https://wpvilla.in/create-wordpress-pages-block-markup-wp-cli-trellis-vm-production/), [block patterns as PHP files](https://wpvilla.in/wordpress-block-pattern-php-files-headers-escaping-images/) and [pattern layout rules](https://wpvilla.in/wordpress-block-pattern-layout-alignfull-grid-spacing-rules/). `PAGE-CREATION.md`, `PATTERN-REQUIREMENTS.md` and the folder README are gone; the scripts and the example stay. - **The migration guides**, now four posts on wpvilla.in: [migrating a site to Trellis and Bedrock](https://wpvilla.in/migrate-wordpress-to-trellis-bedrock-step-by-step/), [testing before the DNS cutover](https://wpvilla.in/trellis-migration-test-etc-hosts-letsencrypt-dns-cutover/), [migrating several sites onto one server](https://wpvilla.in/migrate-multiple-wordpress-sites-one-trellis-server/) and [wp search-replace for domain and path changes](https://wpvilla.in/wp-search-replace-wordpress-url-domain-https-bedrock-paths/). `wp-cli/migration/` is gone, and the README, `CLAUDE.md` and `wp-cli/README.md` no longer point at it. - **The documentation feature.** The guides are moving to [wpvilla.in](https://wpvilla.in/), so wp-ops no longer searches or links documentation. - `wp-ops docs` is gone, along with the "the documentation mentions it" hint in `search`. diff --git a/CLAUDE.md b/CLAUDE.md index 92a4e50..5200efe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -218,7 +218,7 @@ ssh web@example.com "cd /srv/www/example.com/current && \ wp search-replace 'http://example.test' 'https://example.com' --all-tables --precise --path=web/wp" ``` -**See also:** `wp-cli/content-creation/PAGE-CREATION.md` section "CRITICAL: URL Sanitization Before Production" for detailed workflows. +**See also:** [Creating WordPress pages from block markup with WP-CLI on Trellis](https://wpvilla.in/create-wordpress-pages-block-markup-wp-cli-trellis-vm-production/), section "The part that bites: local URLs in the database". ## Important Considerations diff --git a/README.md b/README.md index 5eca301..5325eb5 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ sites are run with: | **Backups** | Timestamped database and uploads backups from any environment | [→](trellis/backup/README.md) | | **Monitoring** | AI-crawler traffic, error surfacing, traffic by country, cron-scheduled reports | [→](trellis/monitoring/README.md) | | **Security** | Malware scanners with checksum verification, fail2ban, manual IP blocking, AbuseIPDB lookup | [scanners](wp-cli/security/README.md) · [server](trellis/security/README.md) | -| **Content & SEO** | Page creation, block pattern validation, redirect/schema/orphan-page audits | [content](wp-cli/content-creation/README.md) · [SEO](wp-cli/seo/README.md) | +| **Content & SEO** | Page creation, block pattern validation, redirect/schema/orphan-page audits | [SEO](wp-cli/seo/README.md) | | **Nginx** | WebP/AVIF serving, browser caching and redirect templates for Trellis `nginx-includes/` | [images](docs/nginx/image-optimization/README.md) · [caching](docs/nginx/browser-caching/README.md) · [redirects](docs/nginx/redirects/README.md) | | **Bedrock** | Testing unreleased packages via Composer `path` repos, standard `wp-cli.yml` | [packages](docs/bedrock/local-package-development/README.md) · [wp-cli.yml](docs/bedrock/wp-cli-config/README.md) | | **Troubleshooting** | PHP-FPM, MariaDB, OOM and mail diagnostics | [→](docs/troubleshooting/README.md) | diff --git a/wp-cli/README.md b/wp-cli/README.md index 9ac2a02..53c3379 100644 --- a/wp-cli/README.md +++ b/wp-cli/README.md @@ -46,127 +46,13 @@ trellis vm shell --workdir /srv/www/example.com/current -- wp post list --path=w **Location:** `content-creation/` -Tools and documentation for creating WordPress pages and Gutenberg block patterns in Trellis/Bedrock environments. +Scripts for creating and publishing pages and posts from block markup: `page-creation.sh`, `import-page-draft.sh`, `publish-post.sh`, `verify-post.sh`, and the `wp imagewize pattern-validate` command. Each explains itself with `wp-ops --help`. -### Features - -- **Local Development Workflow** - Trellis VM-based page creation -- **Production Deployment** - Automated and manual deployment methods -- **URL Sanitization** - Critical for avoiding mixed content warnings -- **Block Pattern Standards** - Comprehensive requirements based on 141+ production patterns -- **Automation Scripts** - Bash scripts for deployment - -### Documentation - -| File | Purpose | -|------|---------| -| `README.md` | Navigation guide to appropriate documentation | -| `PAGE-CREATION.md` | Complete page creation workflow (1,000+ lines) | -| `PATTERN-REQUIREMENTS.md` | Block pattern specification (1,150+ lines) | -| `page-creation.sh` | Automated production deployment script | -| `examples/example-page-content.html` | Sample Gutenberg block markup | - -### Key Topics - -**PAGE-CREATION.md** covers: -- Local development workflow with Trellis VM -- Production deployment (automated script and manual methods) -- **CRITICAL: URL Sanitization** before production deployment - - Pattern URLs get hardcoded into database - - Development URLs (`.test`) must be replaced with production URLs (`.com`) - - Verification and search-replace workflows -- Adding patterns to existing pages (3 methods with examples) -- Common issues and troubleshooting -- Best practices for security, performance, and SEO - -**PATTERN-REQUIREMENTS.md** covers: -- Pattern header requirements (Title, Slug, Description, Categories) -- Metadata attribute structure -- Structural patterns (full-width, grids, constrained layouts) -- Spacing and styling standards (theme variable usage mandatory) -- Image handling (avoiding hardcoded media IDs) -- Typography and responsive design -- Accessibility and semantic HTML -- PHP in patterns (security, escaping, limitations) -- Internationalization (i18n) -- **17 Common Mistakes** with explanations - -### Usage Examples - -#### Create Page Locally - -```bash -# SSH into Trellis VM -trellis vm shell - -# Navigate to WordPress directory -cd /srv/www/example.com/current - -# Create page with pattern -CONTENT='' -wp post create --post_title="About Us" \ - --post_content="$CONTENT" \ - --post_status=publish \ - --path=web/wp -``` - -#### Deploy to Production (Automated) - -```bash -# Edit page-creation.sh with your details -./content-creation/page-creation.sh -``` - -#### Verify URLs After Deployment - -```bash -# Check for development URLs in production -ssh web@example.com "cd /srv/www/example.com/current && \ - wp db query \"SELECT COUNT(*) FROM wp_posts WHERE post_content LIKE '%.test%';\" --path=web/wp" - -# If found, run search-replace -ssh web@example.com "cd /srv/www/example.com/current && \ - wp search-replace 'http://example.test' 'https://example.com' --all-tables --precise --path=web/wp" -``` - -### Common Workflows - -#### Adding Pattern to Existing Page - -**Method 1: Direct Content Update** -```bash -# Get existing content -EXISTING=$(wp post get 100 --field=content --path=web/wp) - -# Add pattern -NEW_CONTENT=" -$EXISTING" - -# Update post -wp post update 100 --post_content="$NEW_CONTENT" --path=web/wp -``` - -**Method 2: Using Heredoc** -```bash -wp post update 100 --post_content="$(cat <<'EOF' - - -EOF -)" --path=web/wp -``` - -**Method 3: Python Escaping (Complex Content)** -```python -import subprocess -content = """ - -

Content with "quotes" and 'apostrophes'

-""" - -subprocess.run(['wp', 'post', 'update', '100', f'--post_content={content}', '--path=web/wp']) -``` +The guides are on the blog: -**See also:** [content-creation/README.md](content-creation/README.md) and subdirectory documentation. +- [Creating WordPress pages from block markup with WP-CLI on Trellis](https://wpvilla.in/create-wordpress-pages-block-markup-wp-cli-trellis-vm-production/) +- [Writing block patterns as PHP files](https://wpvilla.in/wordpress-block-pattern-php-files-headers-escaping-images/) +- [Block pattern layout rules](https://wpvilla.in/wordpress-block-pattern-layout-alignfull-grid-spacing-rules/) --- @@ -403,7 +289,7 @@ cd /srv/www/example.com/current 1. **Always test locally first** - Use Trellis development environment 2. **Sanitize URLs before production** - Check for hardcoded development URLs -3. **Follow pattern standards** - Use PATTERN-REQUIREMENTS.md as checklist +3. **Follow pattern standards** - Run `wp imagewize pattern-validate` on the patterns directory 4. **Version control patterns** - Commit pattern files to theme repository 5. **Validate block markup** - Test in WordPress editor before automation diff --git a/wp-cli/content-creation/PAGE-CREATION.md b/wp-cli/content-creation/PAGE-CREATION.md deleted file mode 100644 index fec5fb6..0000000 --- a/wp-cli/content-creation/PAGE-CREATION.md +++ /dev/null @@ -1,1068 +0,0 @@ -# WordPress Page Creation Guide - Trellis/Bedrock - -Complete guide for creating WordPress pages on Trellis VM (local development) and production servers using WP-CLI and Gutenberg blocks. - -**Last Updated:** November 25, 2025 -**Environment:** Trellis VM (Lima-based) with Bedrock/WordPress -**Compatibility:** Trellis 1.x, Bedrock, WordPress 6.x+ - ---- - -## Table of Contents - -1. [Prerequisites](#prerequisites) -2. [Local Development (Trellis VM)](#local-development-trellis-vm) -3. [Production Deployment](#production-deployment) -4. [Content Preparation](#content-preparation) -5. [Automated Script Details](#automated-script-details) -6. [Common Issues & Solutions](#common-issues--solutions) -7. [Best Practices](#best-practices) -8. [Examples](#examples) -9. [Adding Patterns to Existing Pages](#adding-patterns-to-existing-pages) - ---- - -## Prerequisites - -### Required Tools -- **Trellis CLI** - For VM access -- **WP-CLI** - WordPress command-line interface (available in VM) -- **Text Editor** - For preparing block content - -### Required Access -- **Local:** Trellis VM running at project location -- **Production:** SSH access to production server -- **Permissions:** WordPress admin or WP-CLI access - -### Project Structure -``` -~/code/example.com/ -├── site/ # Bedrock WordPress installation -│ └── web/app/ -│ ├── themes/your-theme/ # Custom Sage theme -│ └── plugins/your-patterns-plugin/ # Block patterns plugin (optional) -└── trellis/ # Trellis configuration -``` - -**Note:** Replace `example.com` with your actual domain throughout this guide. - ---- - -## Local Development (Trellis VM) - -### Step 1: Prepare Block Content - -Create an HTML file with Gutenberg block markup: - -```bash -# Create your content file (can be anywhere, will be copied to site directory) -nano about-page-content.html -``` - -**Tip:** See [examples/example-page-content.html](examples/example-page-content.html) in this directory for a complete example using WordPress Gutenberg blocks. - -**Content Structure:** -- Use WordPress Gutenberg block comments (``) -- Follow your theme's block patterns for consistency (if using a patterns plugin) -- Include proper spacing variables (`var:preset|spacing|*`) -- Use your theme's color palette (check `theme.json` for available colors) - -**Example Block Pattern:** -```html - -
- -

Your Heading

- -
- -``` - -### Step 2: Check for Conflicting Slugs - -Before creating the page, verify the desired slug is available: - -```bash -cd ~/code/example.com/trellis -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp post list --name=about --post_type=any --path=web/wp \ - --fields=ID,post_type,post_title,post_name,post_status -``` - -**Note:** Replace `example.com` with your actual domain name. - -**Common Conflicts:** -- **Attachments** with the same slug (e.g., `about` from uploaded images) -- **Draft pages** that were previously created -- **Trashed posts** that haven't been permanently deleted - -**Resolution:** -```bash -# Delete conflicting attachments/posts (use actual IDs from above command) -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp post delete 2366 1366 --force --path=web/wp -``` - -### Step 3: Copy Content File to Accessible Location - -The Trellis VM can access files in the synced project directory: - -```bash -# Copy content to site directory (accessible by VM at /srv/www/example.com/current/) -cp about-page-content.html ~/code/example.com/site/about-page-content.html -``` - -**Why this step?** -- Lima (Trellis VM) syncs your project directory (e.g., `~/code/example.com/`) to `/srv/www/example.com/current/` inside the VM -- Files outside this directory are not accessible by the VM -- Automatic real-time sync means no manual file transfer needed - -### Step 4: Create the Page via WP-CLI - -Use WP-CLI to create the page from the VM: - -```bash -cd ~/code/example.com/trellis - -# Method: Read file in VM and create page -trellis vm shell --workdir /srv/www/example.com/current -- bash -c ' -CONTENT=$(cat /srv/www/example.com/current/site/about-page-content.html) -wp post create \ - --post_type=page \ - --post_title="About" \ - --post_name="about" \ - --post_status=publish \ - --post_content="$CONTENT" \ - --path=web/wp -' -``` - -**Command Breakdown:** -- `trellis vm shell` - Access Trellis VM -- `--workdir` - Set working directory in VM -- `bash -c` - Execute bash commands in VM -- `CONTENT=$(cat ...)` - Read file content into variable -- `wp post create` - Create new WordPress post/page -- `--post_type=page` - Create a page (not post) -- `--post_status=publish` - Publish immediately -- `--path=web/wp` - WordPress installation path in Bedrock - -**Expected Output:** -``` -Success: Created post 12306. -``` - -### Step 5: Verify Page Creation - -```bash -# Check page details (replace 12306 with your actual page ID) -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp post get 12306 --path=web/wp \ - --fields=ID,post_title,post_name,post_status,post_type - -# Verify content was saved correctly (search for a unique phrase from your content) -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp post get 12306 --path=web/wp --field=post_content | grep -o "Your Unique Phrase" -``` - -### Step 6: Update Slug (If Needed) - -If WordPress created the page with an auto-incremented slug (e.g., `about-2`): - -```bash -# Update to correct slug after removing conflicts -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp post update 12306 --post_name=about --path=web/wp -``` - -### Step 7: Flush Cache & Test - -```bash -# Flush WordPress cache -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp cache flush --path=web/wp - -# Test page in browser (replace example.test with your local domain) -open https://example.test/about/ -``` - -### Step 8: Clean Up - -```bash -# Remove temporary content file -rm ~/code/example.com/site/about-page-content.html -``` - ---- - -## Production Deployment - -### CRITICAL: URL Sanitization Before Production - -**IMPORTANT**: When deploying content created locally to production, always check for and fix local development URLs. - -**Why this is necessary:** -- PHP pattern files use `get_template_directory_uri()` which returns environment-specific URLs -- When patterns are inserted into pages/posts, these URLs get **hardcoded in the database** -- Content created locally will contain `http://demo.imagewize.test` or `http://example.test` URLs -- Must be replaced with production URLs before going live to avoid mixed content warnings - -**Pre-Deployment URL Audit:** -```bash -# STEP 1: Check if any local dev URLs exist in production database -ssh web@example.com "cd /srv/www/example.com/current && \ - wp db query \"SELECT ID, post_title, post_name FROM wp_posts \ - WHERE post_content LIKE '%example.test%' OR post_content LIKE '%.test%';\" \ - --path=web/wp" - -# For multisite (e.g., demo.example.com): -ssh web@demo.example.com "cd /srv/www/demo.example.com/current && \ - wp db query \"SELECT ID, post_title, post_name FROM wp_posts \ - WHERE post_content LIKE '%demo.example.test%';\" \ - --path=web/wp --url=https://demo.example.com" -``` - -**If Dev URLs Found - Fix Before Going Live:** -```bash -# STEP 2: Backup database before making changes -ssh web@example.com "cd /srv/www/example.com/current && \ - wp db export /tmp/backup_before_url_fix_\$(date +%Y%m%d_%H%M%S).sql.gz --path=web/wp" - -# STEP 3: Replace dev URLs with production URLs -ssh web@example.com "cd /srv/www/example.com/current && \ - wp search-replace 'http://example.test' 'https://example.com' \ - --all-tables --precise --path=web/wp" - -# For multisite: -ssh web@demo.example.com "cd /srv/www/demo.example.com/current && \ - wp search-replace 'http://demo.example.test' 'https://demo.example.com' \ - --all-tables --precise --path=web/wp --url=https://demo.example.com" - -# STEP 4: Flush cache -ssh web@example.com "cd /srv/www/example.com/current && wp cache flush --path=web/wp" -``` - -**STEP 5: Verify in Browser** -- Open browser console (F12) -- Check for mixed content warnings (HTTP resources on HTTPS page) -- Look for any requests to `.test` domains -- Hard refresh (Cmd+Shift+R) to clear browser cache - ---- - -### Option 1: Automated Script (Recommended) - -Use the provided [page-creation.sh](page-creation.sh) script for automated deployment: - -**Features:** -- Automated file transfer via SCP -- Conflict detection and resolution -- Interactive prompts for safety -- Automatic cleanup -- Comprehensive verification - -**Usage:** -```bash -# Basic usage -./page-creation.sh about-page-content.html "About" "about" - -# The script will: -# 1. Copy the HTML file to production server -# 2. Check for existing pages/attachments with the same slug -# 3. Prompt for deletion if conflicts exist -# 4. Create the page with WP-CLI -# 5. Verify creation and display page URL -# 6. Clean up temporary files -``` - -**Script Configuration:** -Edit these variables in the script to match your server: -```bash -SERVER_USER="web" -SERVER_HOST="example.com" -SERVER_PATH="/srv/www/example.com/current" -WP_PATH="web/wp" -``` - -**Example Output:** -``` -[INFO] Starting page creation process for: About (slug: about) -[INFO] Step 1: Copying content file to production server... -[INFO] ✓ File copied successfully to /tmp/about-page-content.html -[INFO] Step 2: Checking for existing content with slug 'about'... -[INFO] ✓ No conflicting content found -[INFO] Step 3: Creating page 'About'... -[INFO] ✓ Page created successfully with ID: 12345 -[INFO] Step 4: Verifying page creation... -[INFO] ✓ Page verification successful -[INFO] Step 5: Cleaning up temporary files... -[INFO] ✓ Cleanup complete - -================================================ -Page created successfully! -Page ID: 12345 -URL: https://example.com/about/ -Admin URL: https://example.com/wp/wp-admin/post.php?post=12345&action=edit -================================================ -``` - -### Option 2: Manual Production Deployment - -**Step 1: Prepare Content** -```bash -# Copy content file to server-accessible location -# Replace web@example.com with your actual server user and domain -scp about-page-content.html web@example.com:/tmp/ -``` - -**Step 2: Create Page** -```bash -# SSH to production (replace with your actual server) -ssh web@example.com -cd /srv/www/example.com/current - -# Create page -CONTENT=$(cat /tmp/about-page-content.html) -wp post create \ - --post_type=page \ - --post_title="About" \ - --post_name="about" \ - --post_status=publish \ - --post_content="$CONTENT" \ - --path=web/wp - -# Clean up -rm /tmp/about-page-content.html -``` - -**Step 3: Verify** -```bash -# Check page was created -wp post list --post_type=page --name=about --path=web/wp \ - --fields=ID,post_title,post_name,post_status - -# Flush cache -wp cache flush --path=web/wp - -# Test in browser (replace with your actual domain) -curl -I https://example.com/about/ -``` - -### Option 2: Export/Import via Database - -**Step 1: Export Page from Development** -```bash -# Export specific page -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp post list --post_type=page --name=about --path=web/wp \ - --format=json > about-page-export.json -``` - -**Step 2: Recreate on Production** -```bash -# Read JSON and create matching page on production -ssh web@example.com "cd /srv/www/example.com/current && \ - wp post create --post_type=page --post_title='About' \ - --post_name='about' --post_status=publish \ - --post_content='' --path=web/wp" -``` - -### Option 3: WordPress Export/Import (WXR) - -**For multiple pages or complex content:** - -```bash -# Local: Export page (replace 12306 with your actual page ID) -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp export --path=web/wp --post__in=12306 --dir=/tmp - -# Copy to production -scp web@example.com:/tmp/export.xml /tmp/ -ssh web@example.com -wp import /tmp/export.xml --path=/srv/www/example.com/current/web/wp --authors=skip -``` - ---- - -## Content Preparation - -### Using Block Patterns Plugin (Optional) - -If your project includes a custom block patterns plugin: - -**Location:** `~/code/example.com/site/web/app/plugins/your-patterns-plugin/patterns/` - -**Common Pattern Types:** -- Hero sections with buttons -- Feature grids and layouts -- Testimonials and reviews -- Team member grids -- Pricing tables -- Contact information blocks -- Call-to-action sections - -**Pattern Structure:** -```php -return array( - 'title' => 'Pattern Name', - 'content' => '...' -); -``` - -**Note:** Pattern availability depends on your specific theme and plugins. - -### Block Content Guidelines - -**1. No Fixed Font Sizes** -```html - -

Heading

- - -

Heading

-``` - -**2. Use Theme Color Palette** -```html - -textColor="primary" -backgroundColor="base" - - -style="color:#ff6b35" -``` - -**3. Use Spacing Variables** -```html - -style="padding-top:var(--wp--preset--spacing--60)" - - -style="padding-top:60px" -``` - -**4. Responsive Design** -- Use `alignfull` for full-width sections -- Use `alignwide` for constrained wide sections -- Rely on theme's responsive breakpoints - -### SEO Considerations - -**Page Title:** -- Keep under 60 characters -- Include primary keyword -- Consider your SEO plugin's title suffix (e.g., "| Your Site Name") - -**Meta Description:** -- Maximum 155 characters -- Set via your SEO plugin's meta box (e.g., The SEO Framework, Yoast, Rank Math) -- Focus on your unique value proposition - -**Heading Structure:** -- One H1 per page (page title) -- Use H2 for main sections -- Use H3 for subsections -- Maintain proper hierarchy - ---- - -## Automated Script Details - -The [page-creation.sh](page-creation.sh) script provides a streamlined workflow with built-in safety checks. - -### Script Workflow - -1. **Argument Validation** - - Requires exactly 3 arguments: content file, page title, page slug - - Validates content file exists locally - - Provides usage examples if arguments are missing - -2. **File Transfer** - - Uses SCP to copy HTML content to `/tmp/` on production server - - Verifies successful transfer before proceeding - - Exits with error if transfer fails - -3. **Conflict Detection** - - Checks for existing posts/pages/attachments with the same slug - - Displays details of conflicting content in table format - - Prompts for confirmation before deletion - - Supports deleting multiple conflicting items - -4. **Page Creation** - - Reads content file on remote server - - Creates page with specified title, slug, and published status - - Returns page ID for verification - - Handles errors gracefully - -5. **Verification** - - Retrieves page details via WP-CLI - - Displays JSON formatted page information - - Shows page URL and admin edit URL - -6. **Cleanup** - - Removes temporary content file from server - - Runs regardless of success/failure (when reached) - -### Script Customization - -**Server Configuration:** -```bash -SERVER_USER="web" # SSH user for production server -SERVER_HOST="example.com" # Production server hostname -SERVER_PATH="/srv/www/example.com/current" # Bedrock root path -WP_PATH="web/wp" # WordPress installation path (Bedrock structure) -``` - -**Color Output:** -- Green `[INFO]` - Successful operations -- Yellow `[WARN]` - Warnings (conflicts found, etc.) -- Red `[ERROR]` - Errors requiring attention - -### Security Considerations - -- Script uses `set -e` to exit immediately on any command failure -- Requires explicit "yes" confirmation for destructive operations -- Uses `--force` flag when deleting to permanently remove content -- Cleans up temporary files even on failure -- Content files stored in `/tmp/` with unique names - -### Requirements - -- **SSH access** to production server with key-based authentication -- **SCP** enabled on production server -- **WP-CLI** installed on production server -- **Python 3** for JSON formatting (verification step) -- **Bash** shell (tested with bash 4.0+) - -## Common Issues & Solutions - -### Issue 1: Slug Already Exists - -**Symptom:** Page created with slug `about-2` instead of `about` - -**Cause:** Another post/attachment already uses the `about` slug - -**Solution:** -```bash -# Find conflicting posts -wp post list --name=about --post_type=any --path=web/wp - -# Delete conflicts -wp post delete --force --path=web/wp - -# Update page slug -wp post update --post_name=about --path=web/wp -``` - -### Issue 2: Content Not Displaying - -**Symptom:** Page shows blank or incorrect content - -**Causes:** -1. Cache not flushed -2. File content not properly escaped -3. Block markup errors - -**Solutions:** -```bash -# Flush all caches -wp cache flush --path=web/wp - -# Check content was saved -wp post get --path=web/wp --field=post_content | head -20 - -# Validate block markup -wp block validate --path=web/wp -``` - -### Issue 3: Cannot Run WP-CLI from Host - -**Symptom:** `Error: Can't read wp-config.php file` - -**Cause:** Local MariaDB/MySQL running on port 3306 conflicts with VM - -**Solution:** Always run WP-CLI commands from within Trellis VM: -```bash -# ✅ CORRECT: Run in VM -trellis vm shell --workdir /srv/www/example.com/current -- wp - -# ❌ WRONG: Run on host -wp --path=~/code/example.com/site/web/wp -``` - -### Issue 4: File Sync Issues - -**Symptom:** Changes not appearing in VM - -**Cause:** Lima file sync delay or WordPress cache - -**Solutions:** -```bash -# Check if file exists in VM -trellis vm shell -- ls -la /srv/www/example.com/current/site/ - -# Flush WordPress cache -trellis vm shell --workdir /srv/www/example.com/current -- \ - wp cache flush --path=web/wp - -# Hard refresh browser (Cmd+Shift+R on Mac, Ctrl+Shift+R on Linux/Windows) -``` - -### Issue 5: Command Substitution Not Working - -**Symptom:** Content shows literal `$(cat ...)` instead of file contents - -**Cause:** Shell escaping issues with nested quotes - -**Solution:** Use proper quoting in bash: -```bash -# ✅ CORRECT: Single quotes for outer bash -c, double for inner -bash -c 'CONTENT=$(cat file.html) && wp post create --post_content="$CONTENT"' - -# ❌ WRONG: Double quotes everywhere -bash -c "CONTENT=$(cat file.html) && wp post create --post_content=\"$CONTENT\"" -``` - ---- - -## Best Practices - -### Development Workflow - -1. **Always work locally first** - - Test on Trellis VM (e.g., `https://example.test`) - - Verify content displays correctly - - Check responsive design at different viewports - -2. **Version control content files** - - Store block content in version control - - Use descriptive filenames (`about-page-content.html`) - - Document any custom blocks or patterns used - -3. **Use patterns for consistency** - - Leverage your theme's block patterns (if available) - - Maintain consistent spacing and colors from your theme - - Reuse existing blocks when possible - -4. **Test before production** - - Verify all links work - - Check images display correctly - - Test contact forms/CTAs - - Validate schema markup - -### Security Best Practices - -1. **Avoid inline scripts** - - Don't include `