| name | Infrastructure |
| description | This skill activates when users discuss WordPress.com platform specifics, hosting differences, deployment workflows, server configuration, or infrastructure decisions. Provides guidance on WordPress.com vs self-hosted infrastructure and platform-specific patterns. |
WordPress Infrastructure
Navigate WordPress.com platform specifics, hosting options, and deployment workflows.
When This Activates
- "WordPress.com", "self-hosted", "hosting", "deployment"
- "SFTP", "SSH", "platform restrictions", "CDN"
- "staging", "production", "environment", "server"
- User asks about WordPress hosting differences
- Discussing infrastructure or deployment
WordPress.com vs Self-Hosted
Feature Comparison
| Feature | WordPress.com | Self-Hosted |
|---|
| Root Access | ❌ No | ✅ Yes |
| SSH/SFTP | ⚠️ SFTP only | ✅ Full SSH |
| Plugin Install | ⚠️ Limited (Business+) | ✅ Any plugin |
| Theme Upload | ✅ Yes (Premium+) | ✅ Yes |
| Server Config | ❌ No control | ✅ Full control |
| .htaccess | ❌ No access | ✅ Yes |
| wp-config.php | ⚠️ Platform managed | ✅ Full control |
| CDN | ✅ Built-in | ⚠️ Configure manually |
| Security | ✅ Platform managed | ⚠️ Your responsibility |
| Updates | ✅ Automatic | ⚠️ Manual (or auto) |
| CSP Headers | ❌ Platform controlled | ✅ Full control |
| Cost | $25+/mo | $5-50/mo |
When to Choose Which
WordPress.com (Managed):
- Simple blogs, portfolios
- No technical team
- Want automatic updates/security
- Standard WordPress features sufficient
Self-Hosted:
- Need custom plugins/themes
- Require server-level control
- Advanced features (3D, custom CDNs)
- Full CSP/header control
SkyyRose Reality: Requires self-hosted for 3D viewers, custom CSP
WordPress.com Platform Specifics
REST API Access
const WP_COM_API_BASE = 'https://skyyrose.co/index.php?rest_route=';
const response = await fetch(`${WP_COM_API_BASE}/wp/v2/posts`);
const products = await fetch(`${WP_COM_API_BASE}/wc/v3/products`, {
headers: {
'Authorization': `Basic ${btoa(`${consumerKey}:${consumerSecret}`)}`,
},
});
SFTP Deployment
lftp -c "
set sftp:auto-confirm yes
open -u USERNAME,PASSWORD sftp://sftp.wp.com:22
mirror --reverse --delete --verbose \
local-theme-dir/ \
/htdocs/wp-content/themes/theme-name/
bye
"
Platform Restrictions
Cache Management
const url = 'https://skyyrose.co/products/?nocache=1';
const url = 'https://skyyrose.co/products/?v=' + Date.now();
Self-Hosted WordPress Infrastructure
Recommended Stack
Option 1: Traditional (LAMP/LEMP)
Linux (Ubuntu 22.04 LTS)
Nginx or Apache
MySQL 8.0 or MariaDB 10.6
PHP 8.1+ (with OPcache, APCu)
Option 2: Modern (Containerized)
version: '3.8'
services:
wordpress:
image: wordpress:6.4-php8.2-fpm-alpine
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: skyyrose
WORDPRESS_DB_USER: skyy
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
volumes:
- ./wordpress:/var/www/html
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: skyyrose
MYSQL_USER: skyy
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./wordpress:/var/www/html
depends_on:
-
Nginx Configuration
server {
listen 80;
server_name skyyrose.co;
root /var/www/html;
index index.php;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# CSP header (full control on self-hosted)
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' 'unsafe-inline' https://cdn.babylonjs.com https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' data: https://fonts.gstatic.com;
img-src 'self' data: https: blob:;
connect-src 'self' https://api.skyyrose.co;
frame-src 'self';
object-src 'none';
" always;
# Gzip compression
gzip on;
gzip_types text/css application/javascript image/svg+xml;
# PHP handling
location ~ \.php$ {
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Static assets cache
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Block access to sensitive files
location ~ /\.(git|env|htaccess) {
deny all;
}
}
Deployment Workflows
CI/CD with GitHub Actions
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Create theme ZIP
run: |
cd wordpress-theme/skyyrose-2025
zip -r ../../skyyrose-2025.zip . \
-x "*.git*" "node_modules/*" ".env*" "*.log"
- name: Deploy via SFTP
uses: SamKirkland/FTP-Deploy-Action@4.3.0
with:
server: ${{ secrets.SFTP_HOST }}
username: ${{ secrets.SFTP_USERNAME }}
password: ${{ secrets.SFTP_PASSWORD }}
protocol: sftp
port: 22
local-dir: ./wordpress-theme/skyyrose-2025/
server-dir: /htdocs/wp-content/themes/skyyrose-2025/
Manual Deployment Script
#!/bin/bash
set -e
THEME_NAME="skyyrose-2025"
THEME_DIR="wordpress-theme/${THEME_NAME}"
DEPLOY_DIR="/tmp/${THEME_NAME}-deploy"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
ZIP_NAME="${THEME_NAME}-${TIMESTAMP}.zip"
echo "=== WordPress Theme Deployment ==="
echo "Theme: ${THEME_NAME}"
echo "Timestamp: ${TIMESTAMP}"
echo
rm -rf "$DEPLOY_DIR"
mkdir -p "$DEPLOY_DIR"
echo "Copying theme files..."
rsync -av --progress \
--exclude=".git*" \
--exclude="node_modules" \
--exclude=".env*" \
--exclude="*.log" \
--exclude="*.map" \
"$THEME_DIR/" "$DEPLOY_DIR/"
echo "Building assets..."
cd "$DEPLOY_DIR"
npm ci --production
npm run build
rm -rf node_modules package*.json
echo
/tmp
zip -r
lftp -c
Staging Environment
Setup Staging Site
mysqldump -u prod_user -p prod_db > staging_backup.sql
mysql -u staging_user -p staging_db < staging_backup.sql
wp search-replace 'https://skyyrose.co' 'https://staging.skyyrose.co' --all-tables
rsync -avz prod_server:/var/www/html/wp-content/uploads/ \
staging_server:/var/www/html/wp-content/uploads/
define('WP_ENVIRONMENT_TYPE', 'staging');
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
Prevent Indexing on Staging
if (defined('WP_ENVIRONMENT_TYPE') && WP_ENVIRONMENT_TYPE === 'staging') {
add_filter('pre_option_blog_public', '__return_zero');
add_action('wp_head', function() {
echo '<meta name="robots" content="noindex,nofollow">';
}, 1);
add_filter('robots_txt', function($output) {
return "User-agent: *\nDisallow: /\n";
});
}
Environment Management
if (file_exists(__DIR__ . '/.env')) {
$env = parse_ini_file(__DIR__ . '/.env');
define('WP_ENVIRONMENT_TYPE', $env['ENVIRONMENT'] ?? 'production');
}
switch (WP_ENVIRONMENT_TYPE) {
case 'local':
case 'development':
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', true);
define('SCRIPT_DEBUG', true);
break;
case 'staging':
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
break;
case 'production':
(, );
(, );
(, );
(, );
;
}
= [
=> [
=> ,
=> ,
=> ,
=> ,
],
=> [
=> ,
=> ,
=> (),
=> (),
],
=> [
=> ,
=> ,
=> (),
=> (),
],
];
= [WP_ENVIRONMENT_TYPE] ?? [];
(, []);
(, []);
(, []);
(, []);
CDN Configuration
Cloudflare Setup
function skyyrose_cdn_url($url) {
if (defined('WP_ENVIRONMENT_TYPE') && WP_ENVIRONMENT_TYPE === 'production') {
$cdn_url = 'https://cdn.skyyrose.co';
$site_url = 'https://skyyrose.co';
if (preg_match('/\.(jpg|jpeg|png|gif|css|js|svg|woff2)$/', $url)) {
return str_replace($site_url, $cdn_url, $url);
}
}
return $url;
}
add_filter('wp_get_attachment_url', 'skyyrose_cdn_url');
add_filter('wp_get_attachment_image_src', 'skyyrose_cdn_url');
Monitoring & Logging
function skyyrose_log_error($message, $context = []) {
if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
$log_message = sprintf(
'[%s] %s | Context: %s',
date('Y-m-d H:i:s'),
$message,
wp_json_encode($context)
);
error_log($log_message);
if (WP_ENVIRONMENT_TYPE === 'production') {
}
}
}
try {
$result = risky_operation();
} catch (Exception $e) {
skyyrose_log_error('Risky operation failed', [
'error' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
]);
}
Backup Strategy
BACKUP_DIR="/backups/skyyrose"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
RETENTION_DAYS=30
mysqldump -u $DB_USER -p$DB_PASS skyyrose_prod | \
gzip > "$BACKUP_DIR/db-$TIMESTAMP.sql.gz"
tar -czf "$BACKUP_DIR/files-$TIMESTAMP.tar.gz" \
/var/www/html/wp-content/uploads \
/var/www/html/wp-content/themes/skyyrose-2025
aws s3 cp "$BACKUP_DIR/db-$TIMESTAMP.sql.gz" \
s3://skyyrose-backups/database/
aws s3 cp "$BACKUP_DIR/files-$TIMESTAMP.tar.gz" \
s3://skyyrose-backups/files/
find "$BACKUP_DIR" -name "*.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup complete: $TIMESTAMP"
SkyyRose Infrastructure Decision
Current: WordPress.com (restricted)
Required: Self-hosted for:
- Custom CSP headers (3D CDNs)
- Server-level control
- Advanced Elementor features
- Full plugin flexibility
Migration Path: See wordpress-theme/ACTUAL-FIX.md
When User Asks About Infrastructure
- Identify requirements: What features needed?
- Platform choice: WordPress.com vs self-hosted?
- Hosting recommendation: Based on scale and budget
- Deployment workflow: CI/CD vs manual?
- Environment setup: Local, staging, production
- Monitoring: Logging, backups, alerts
Always consider trade-offs: convenience vs. control, cost vs. features.