wordpress-trade-site
Interactive guide to deploy a production-ready WordPress site for international trade businesses. Triggers on "build a trade website", "deploy wordpress trade site", "set up B2B website", or similar requests.
What this skill does
# WordPress Trade Site Builder
Deploy a production-ready WordPress trade site from scratch through 9 interactive phases. Based on the [wordpress-trade-starter](https://github.com/iPythoning/wordpress-trade-starter) template.
**Principle:** Automate everything possible. Only pause when user decisions or information are required. When errors occur, diagnose and fix them proactively — don't tell the user to go fix things themselves.
**Interaction:** Use `AskUserQuestion` for all user-facing questions. Report progress after each phase, then continue to the next.
**Data flow:** Information collected in each phase (business info, SSH details, domain, etc.) is reused in subsequent phases. Key data is labeled with variable names for reference.
---
## Phase 1: Collect Business Information
Before any technical work, understand the user's business needs.
AskUserQuestion (collect sequentially):
1. **Company name** — "What is your company name? (Both local language and English)"
- Example: TitanPuls Technology Co., Ltd.
- Record as `COMPANY_EN` (and `COMPANY_LOCAL` if provided)
2. **Main products** — "What products do you mainly sell? (Brief description)"
- Example: Semi-trailers, construction machinery
- Record as `PRODUCTS`
3. **Target markets** — "Which markets do you primarily target?" (multiSelect)
- Africa
- Middle East
- Southeast Asia
- Latin America
- Europe
- North America
- Record as `TARGET_MARKETS`
4. **Languages** — "Which languages should your website support?" (multiSelect, recommend based on target markets)
- English (Recommended)
- Chinese
- Russian
- Spanish
- French
- Arabic
- Record as `LANGUAGES`
5. **Contact info** — "How should customers reach you?"
- WhatsApp number (with country code)
- Business email
- Record as `WHATSAPP` and `EMAIL`
Summary confirmation: Display collected information and AskUserQuestion to confirm correctness.
---
## Phase 2: Server Preparation
### 2a. Server status
AskUserQuestion: "Do you already have a Linux server?"
- **I have a server** — Collect SSH details
- **I need guidance** — Recommend datacenter locations and providers based on `TARGET_MARKETS`
**Purchase guidance** (if needed):
Recommend based on target market:
| Target Market | Recommended DC | Recommended Providers |
|--------------|----------------|----------------------|
| Europe/Africa | Germany/Netherlands | Contabo, Hetzner |
| North America | US East/West Coast | DigitalOcean, Vultr |
| Southeast Asia | Singapore | Vultr, Alibaba Cloud |
| Middle East | Dubai/Bahrain | AWS, Alibaba Cloud |
| Latin America | US Miami | DigitalOcean |
Recommended specs: 2 cores / 2GB RAM / 40GB SSD ($10-20/month). Tell user to continue after purchase.
### 2b. SSH connection
AskUserQuestion: "Please provide your server SSH details:"
- IP address → `SERVER_IP`
- SSH port (default 22) → `SSH_PORT`
- Username (usually root) → `SSH_USER`
- Authentication: password or SSH key
Verify connection:
```bash
ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -p ${SSH_PORT} ${SSH_USER}@${SERVER_IP} "echo CONNECTION_OK && uname -a && free -m && df -h /"
```
- CONNECTION_OK → Continue
- Connection failed → Check IP/port/credentials, prompt user to correct
### 2c. Server initialization
Execute via SSH:
```bash
# System update
apt update && apt upgrade -y
# Set timezone
timedatectl set-timezone UTC
# Create swap (if RAM <= 2GB and no swap exists)
if [ $(free -m | awk '/^Mem:/{print $2}') -le 2048 ] && [ ! -f /swapfile ]; then
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
fi
# Firewall
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
# Essential tools
apt install -y curl git unzip htop
```
Verify: `ufw status` shows 22/80/443 open.
---
## Phase 3: Docker Deployment
### 3a. Install Docker
```bash
if ! command -v docker &>/dev/null; then
curl -fsSL https://get.docker.com | sh
systemctl enable docker && systemctl start docker
fi
docker compose version || apt-get install -y docker-compose-plugin
```
Verify: `docker compose version` outputs a version number.
### 3b. Clone template
```bash
cd /opt
git clone https://github.com/iPythoning/wordpress-trade-starter.git wordpress
cd /opt/wordpress
```
### 3c. Generate .env
AskUserQuestion: "Please provide the following:"
- Domain name (e.g. example.com) → `DOMAIN`
- MySQL root password (auto-generate recommended) → `MYSQL_ROOT_PASSWORD`
- MySQL user password (auto-generate recommended) → `MYSQL_PASSWORD`
If user chooses auto-generation:
```bash
MYSQL_ROOT_PASSWORD=$(openssl rand -base64 16)
MYSQL_PASSWORD=$(openssl rand -base64 16)
```
Write .env:
```bash
cat > /opt/wordpress/.env << EOF
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE=wordpress
MYSQL_USER=wordpress
MYSQL_PASSWORD=${MYSQL_PASSWORD}
DOMAIN=${DOMAIN}
EMAIL=${EMAIL}
EOF
```
**Important:** Display the generated passwords to the user and remind them to save securely.
### 3d. Configure Nginx
```bash
sed -i "s/YOUR_DOMAIN/${DOMAIN}/g" /opt/wordpress/nginx.conf
```
### 3e. Start containers
```bash
cd /opt/wordpress
docker compose up -d
```
Verify:
```bash
docker compose ps
# Confirm all three containers (db, wordpress, nginx) are running/healthy
```
Wait for WordPress to be ready:
```bash
for i in $(seq 1 30); do
curl -sf http://localhost > /dev/null 2>&1 && break
sleep 2
done
```
- All 3 containers running → Continue
- db unhealthy → Check `docker compose logs db`, common cause is password format issues
- wordpress not starting → Check `docker compose logs wordpress`
---
## Phase 4: SSL Certificate
### 4a. Choose method
AskUserQuestion: "Which SSL certificate method?"
- **Let's Encrypt (Recommended)** — Free, auto-renewal, requires domain A record pointing to server IP
- **Cloudflare Origin Certificate** — For users already using Cloudflare proxy
### 4b-A. Let's Encrypt
Prerequisite: Domain A records must point to `SERVER_IP`. If not configured, guide the user to add in their DNS panel:
- `DOMAIN` → A → `SERVER_IP`
- `www.DOMAIN` → A → `SERVER_IP`
```bash
# Stop nginx to free port 80
cd /opt/wordpress && docker compose stop nginx
apt install -y certbot
certbot certonly --standalone -d ${DOMAIN} -d www.${DOMAIN} --email ${EMAIL} --agree-tos --non-interactive
mkdir -p /opt/wordpress/ssl
cp /etc/letsencrypt/live/${DOMAIN}/fullchain.pem /opt/wordpress/ssl/
cp /etc/letsencrypt/live/${DOMAIN}/privkey.pem /opt/wordpress/ssl/
# Auto-renewal cron
(crontab -l 2>/dev/null; echo "0 3 * * * certbot renew --quiet --pre-hook 'cd /opt/wordpress && docker compose stop nginx' --post-hook 'cp /etc/letsencrypt/live/${DOMAIN}/fullchain.pem /opt/wordpress/ssl/ && cp /etc/letsencrypt/live/${DOMAIN}/privkey.pem /opt/wordpress/ssl/ && cd /opt/wordpress && docker compose start nginx'") | crontab -
# Restart nginx
docker compose start nginx
```
### 4b-B. Cloudflare Origin Certificate
Guide the user through Cloudflare Dashboard:
1. SSL/TLS → Origin Server → Create Certificate
2. Choose RSA, 15-year validity
3. Copy Certificate and Private Key
```bash
mkdir -p /opt/wordpress/ssl
# User pastes certificate content
cat > /opt/wordpress/ssl/fullchain.pem << 'EOF'
<user pastes certificate here>
EOF
cat > /opt/wordpress/ssl/privkey.pem << 'EOF'
<user pastes private key here>
EOF
```
### 4c. Verify HTTPS
```bash
docker compose restart nginx
curl -I https://${DOMAIN} 2>/dev/null | head -5
```
- HTTP/2 200 → Success
- Connection failed → Check DNS resolution, certificate paths, nginx logs
---
## Phase 5: WordPress Initialization
### 5a. Setup wizard
Tell the user to open `https://${DOMAIN}/wp-admin/install.php` in their browser and fill in:
- Site Title: `COMPANY_EN`
- Username: suggest avoiding "admin" (security)
- Password: strong password
- Email: `EMAIL`
AskUserQuestion: "Have you completed the WordPress setup wizard?"
### 5b. InstRelated in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.