✨feature: Initial commit
This commit is contained in:
67
windows/README-Windows.md
Normal file
67
windows/README-Windows.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Easy WordPress Bootstrap (Herd + DBngin) — Windows Edition
|
||||
|
||||
This kit lets Windows devs spin up a new local WordPress project using **PowerShell only**.
|
||||
|
||||
## Includes
|
||||
|
||||
- `wp-bootstrap.ps1` — main PowerShell script
|
||||
- `bootstrap.bat` — one-click launcher
|
||||
- `plugins.json` — minimal default plugin list (use file from repo root)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **PHP** installed and in PATH
|
||||
- **MySQL client** (`mysql.exe`) in PATH (DBngin/MySQL installed and running)
|
||||
- **Git** installed (for cloning the starter theme)
|
||||
- **WP-CLI**: either installed globally as `wp`, **or** put `wp-cli.phar` next to this script and call with:
|
||||
- `-WpCliPath "php .\wp-cli.phar"`
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Right-click **PowerShell** → *Run as Administrator* (first run only):
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
```
|
||||
|
||||
2. Open a normal PowerShell in this folder and run:
|
||||
|
||||
```powershell
|
||||
.\wp-bootstrap.ps1 -ProjectName "Client Site"
|
||||
```
|
||||
|
||||
or double-click `bootstrap.bat` and enter the project name when prompted.
|
||||
|
||||
### Optional parameters
|
||||
|
||||
- `-AdminUser` (default: `vdidev`)
|
||||
- `-AdminEmail` (default: `dev@vincentdesign.ca`)
|
||||
- `-ThemeStarterRepo` (default: VDI starter theme)
|
||||
- `-HerdWorkspace` (default: `"$HOME\Herd"`)
|
||||
- `-LocalTld` (default: `test`)
|
||||
- `-MysqlHost` / `-MysqlPort` / `-MysqlRootUser` / `-MysqlRootPass`
|
||||
- `-WpCliPath` (set to `"php .\wp-cli.phar"` if not installed globally)
|
||||
|
||||
## What it does
|
||||
|
||||
- Creates project folder under your Herd workspace
|
||||
- Downloads WordPress core
|
||||
- Creates database + user with random password
|
||||
- Generates `wp-config.php`, shuffles salts
|
||||
- Installs WordPress and sets the site/home URLs
|
||||
- Creates **Home** and **News** pages, sets **front page**/**posts page**
|
||||
- Sets permalinks to `/%postname%/` and flushes
|
||||
- Clones the starter theme, strips history, re-initializes a clean repo, and activates it
|
||||
- Installs and (optionally) activates plugins from `plugins.json`
|
||||
- Prints and saves a summary (`bootstrap-summary.txt`)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **WP-CLI not found**: pass `-WpCliPath "php .\wp-cli.phar"` (place `wp-cli.phar` beside this script).
|
||||
- **MySQL not found**: ensure `mysql.exe` is in PATH. With DBngin, add the MySQL bin folder to PATH.
|
||||
- **Access denied creating DB**: verify `-MysqlRootUser`/`-MysqlRootPass`, or create a dev-only MySQL user with `CREATE` privileges.
|
||||
- **Herd not serving**: Add/link the folder in Herd and browse to `http://<slug>.test` (or your chosen TLD).
|
||||
|
||||
## Philosophy
|
||||
|
||||
DIY-first: keep `plugins.json` minimal. Only add big off‑the‑shelf stacks (e.g., ecomm) when warranted.
|
||||
4
windows/bootstrap.bat
Normal file
4
windows/bootstrap.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
REM One-click launcher for the Windows PowerShell bootstrap.
|
||||
REM Usage: bootstrap "Client Site Name"
|
||||
PowerShell -ExecutionPolicy Bypass -File "%~dp0wp-bootstrap.ps1" -ProjectName "%*"
|
||||
169
windows/wp-bootstrap.ps1
Normal file
169
windows/wp-bootstrap.ps1
Normal file
@@ -0,0 +1,169 @@
|
||||
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)][string]$ProjectName,
|
||||
[string]$AdminUser = "vdidev",
|
||||
[string]$AdminEmail = "dev@vincentdesign.ca",
|
||||
[string]$ThemeStarterRepo = "https://github.com/vincent-design-inc/starter-theme-3.git",
|
||||
[string]$HerdWorkspace = "$HOME\Herd",
|
||||
[string]$LocalTld = "test",
|
||||
[string]$MysqlHost = "127.0.0.1",
|
||||
[string]$MysqlPort = "3306",
|
||||
[string]$MysqlRootUser = "root",
|
||||
[string]$MysqlRootPass = "",
|
||||
# If WP-CLI isn't globally installed, set this to 'php .\wp-cli.phar'
|
||||
[string]$WpCliPath = "wp"
|
||||
)
|
||||
|
||||
function Slugify([string]$s) { ($s.ToLower() -replace '[^a-z0-9]+','-').Trim('-') }
|
||||
|
||||
function RandPass() {
|
||||
$bytes = New-Object 'System.Byte[]' 18
|
||||
(New-Object System.Security.Cryptography.RNGCryptoServiceProvider).GetBytes($bytes)
|
||||
[Convert]::ToBase64String($bytes) -replace '[^a-zA-Z0-9]','' | ForEach-Object { $_.Substring(0,24) }
|
||||
}
|
||||
|
||||
function Invoke-WP {
|
||||
param([string[]]$Args)
|
||||
# Support 'wp' OR 'php .\wp-cli.phar'
|
||||
if ($WpCliPath -match '\s') {
|
||||
$parts = $WpCliPath -split '\s+'
|
||||
& $parts[0] $parts[1..($parts.Count-1)] $Args 2>&1 | ForEach-Object { "$_" }
|
||||
} else {
|
||||
& $WpCliPath $Args 2>&1 | ForEach-Object { "$_" }
|
||||
}
|
||||
if ($LASTEXITCODE -ne 0) { throw "WP-CLI command failed: $($Args -join ' ')" }
|
||||
}
|
||||
|
||||
function WP([string]$line) {
|
||||
# Convenience to pass a single-line string; splits on spaces
|
||||
$args = @()
|
||||
$token = ""
|
||||
$inQuote = $false
|
||||
foreach ($c in $line.ToCharArray()) {
|
||||
if ($c -eq '"') { $inQuote = -not $inQuote; continue }
|
||||
if (-not $inQuote -and [char]::IsWhiteSpace($c)) {
|
||||
if ($token.Length -gt 0) { $args += $token; $token = "" }
|
||||
} else { $token += $c }
|
||||
}
|
||||
if ($token.Length -gt 0) { $args += $token }
|
||||
Invoke-WP $args
|
||||
}
|
||||
|
||||
# === Start ===
|
||||
$Slug = Slugify $ProjectName
|
||||
$ProjectDir = Join-Path $HerdWorkspace $Slug
|
||||
$LocalUrl = "http://$Slug.$LocalTld"
|
||||
|
||||
$DbName = "vdi_$Slug"
|
||||
$DbUser = $DbName
|
||||
$DbPass = RandPass
|
||||
$AdminPass = RandPass
|
||||
|
||||
Write-Host "Creating project at $ProjectDir..."
|
||||
New-Item -ItemType Directory -Force -Path $ProjectDir | Out-Null
|
||||
Set-Location $ProjectDir
|
||||
|
||||
# --- WordPress Core ---
|
||||
Write-Host "Downloading WordPress..."
|
||||
Invoke-WP @("core","download","--force")
|
||||
|
||||
# --- Database setup ---
|
||||
Write-Host "Creating MySQL DB and user..."
|
||||
$mysqlArgs = @("-h", $MysqlHost, "-P", $MysqlPort, "-u", $MysqlRootUser)
|
||||
if ($MysqlRootPass -ne "") { $mysqlArgs += "-p$MysqlRootPass" }
|
||||
$sql = @"
|
||||
CREATE DATABASE IF NOT EXISTS `$DbName` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE USER IF NOT EXISTS '$DbUser'@'%' IDENTIFIED BY '$DbPass';
|
||||
GRANT ALL PRIVILEGES ON `$DbName`.* TO '$DbUser'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
"@
|
||||
try {
|
||||
$sql | & mysql.exe @mysqlArgs
|
||||
} catch {
|
||||
throw "MySQL client not found or connection failed. Ensure mysql.exe is in PATH and DBngin/MySQL is running."
|
||||
}
|
||||
|
||||
# --- Config + Install ---
|
||||
Invoke-WP @("config","create","--dbname=$DbName","--dbuser=$DbUser","--dbpass=$DbPass","--dbhost=$MysqlHost`:$MysqlPort","--force")
|
||||
Invoke-WP @("config","shuffle-salts")
|
||||
Invoke-WP @("core","install","--url=$LocalUrl","--title=$ProjectName","--admin_user=$AdminUser","--admin_password=$AdminPass","--admin_email=$AdminEmail")
|
||||
Invoke-WP @("option","update","siteurl",$LocalUrl)
|
||||
Invoke-WP @("option","update","home",$LocalUrl)
|
||||
|
||||
# --- Pages & Reading ---
|
||||
Write-Host "Creating Home/News pages and setting permalinks..."
|
||||
$homeId = (Invoke-WP @("post","create","--post_type=page","--post_status=publish","--post_title=Home","--porcelain") | Select-Object -Last 1).Trim()
|
||||
$newsId = (Invoke-WP @("post","create","--post_type=page","--post_status=publish","--post_title=News","--porcelain") | Select-Object -Last 1).Trim()
|
||||
Invoke-WP @("option","update","show_on_front","page")
|
||||
Invoke-WP @("option","update","page_on_front",$homeId)
|
||||
Invoke-WP @("option","update","page_for_posts",$newsId)
|
||||
Invoke-WP @("rewrite","structure","/%postname%/")
|
||||
Invoke-WP @("rewrite","flush","--hard")
|
||||
|
||||
# --- Theme ---
|
||||
Write-Host "Cloning starter theme..."
|
||||
$tmp = ".starter-tmp"
|
||||
if (Test-Path $tmp) { Remove-Item -Recurse -Force $tmp }
|
||||
git clone --depth=1 $ThemeStarterRepo $tmp | Out-Null
|
||||
|
||||
$ThemeDir = "wp-content\themes\$Slug-theme"
|
||||
if (Test-Path $ThemeDir) { Remove-Item -Recurse -Force $ThemeDir }
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path $ThemeDir) | Out-Null
|
||||
Move-Item $tmp $ThemeDir
|
||||
if (Test-Path "$ThemeDir\.git") { Remove-Item -Recurse -Force "$ThemeDir\.git" }
|
||||
|
||||
Invoke-WP @("theme","activate","$Slug-theme")
|
||||
|
||||
Push-Location $ThemeDir
|
||||
git init -b main | Out-Null
|
||||
git add -A
|
||||
git commit -m "feat: bootstrap ${ProjectName} theme from starter" | Out-Null
|
||||
Pop-Location
|
||||
|
||||
# --- Plugins ---
|
||||
if (Test-Path "plugins.json") {
|
||||
try {
|
||||
$plugins = Get-Content "plugins.json" | ConvertFrom-Json
|
||||
foreach ($plugin in $plugins) {
|
||||
if ($plugin.zip) {
|
||||
$args = @("plugin","install",$plugin.zip,"--force")
|
||||
if ($plugin.activate -eq $true) { $args += "--activate" }
|
||||
Invoke-WP $args
|
||||
} elseif ($plugin.slug) {
|
||||
$args = @("plugin","install",$plugin.slug,"--force")
|
||||
if ($plugin.version) { $args += "--version=$($plugin.version)" }
|
||||
if ($plugin.activate -eq $true) { $args += "--activate" }
|
||||
Invoke-WP $args
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Error reading plugins.json: $_"
|
||||
}
|
||||
}
|
||||
|
||||
# --- Summary ---
|
||||
$Summary = @"
|
||||
VDI WP Bootstrap — Summary
|
||||
===========================
|
||||
|
||||
Project: $ProjectName
|
||||
Slug: $Slug
|
||||
Folder: $ProjectDir
|
||||
Local URL: $LocalUrl
|
||||
|
||||
DB Host: $MysqlHost
|
||||
DB Port: $MysqlPort
|
||||
DB Name: $DbName
|
||||
DB User: $DbUser
|
||||
DB Pass: $DbPass
|
||||
|
||||
WP Admin User: $AdminUser
|
||||
WP Admin Pass: $AdminPass
|
||||
WP Admin Email: $AdminEmail
|
||||
|
||||
Theme Dir: $ThemeDir
|
||||
"@
|
||||
$SummaryFile = Join-Path $ProjectDir "bootstrap-summary.txt"
|
||||
$Summary | Out-File -FilePath $SummaryFile -Encoding utf8
|
||||
Write-Host $Summary
|
||||
Write-Host "Saved summary to $SummaryFile"
|
||||
Reference in New Issue
Block a user