Skip to content

WooCommerce Headless Blueprint

Use this SOP when a human needs to create a new headless WooCommerce project for a client using the GETQUICK three-repository pattern.

The workflow creates:

  • A parent workspace repository under Quick-Release/<client-slug>.
  • A WordPress admin repository under Quick-Release/<client-slug>-admin.
  • An Astro frontend repository under Quick-Release/<client-slug>-fe.

The parent repository records the admin and frontend repositories as Git submodules. WordPress deploys to Ploi at admin.<client-domain>, and Astro deploys to Cloudflare Workers.

This blueprint follows the existing GETQUICK headless WordPress/WooCommerce workspace shape:

  • The parent repo coordinates local development and submodule versions.
  • The admin repo contains Bedrock WordPress, DDEV local development, WooCommerce, GraphQL/API configuration, and Ploi deployment configuration.
  • The frontend repo contains the Astro storefront, Cloudflare Workers deployment configuration, and WordPress/WooCommerce data integration.

Use the current internal example repositories as the source pattern, but rename everything to generic client values before committing the new project.

Supporting SOPs:

  • Cloudflare domain registration: /cloudflare/register-a-domain-with-cloudflare/
  • Ploi API reference: /ploi-io/ploi-api-reference/
  • Ploi auth config: /ploi-io/auth-config/
  • Agent domain registration policy: /agents/allow-agents-to-register-domains/

Official references:

  • DDEV installation: https://docs.ddev.com/en/stable/users/install/ddev-installation/
  • GitHub CLI: https://github.com/cli/cli
  • Cloudflare Wrangler: https://developers.cloudflare.com/workers/wrangler/commands/general/

After the procedure is complete:

  • Three private GitHub repositories exist under Quick-Release.
  • The parent repository includes the admin and frontend repositories as submodules.
  • The admin repository can run WordPress locally with DDEV and can deploy to Ploi.
  • The frontend repository can run Astro locally and deploy to Cloudflare Workers.
  • Required GitHub secrets and variables are configured for Ploi and Cloudflare deployments.
  • The production admin hostname is admin.<client-domain>.
  • The production storefront hostname is ready for the chosen client domain.

Run this first and edit only the values on the right side:

Terminal window
export GITHUB_ORG="Quick-Release"
export CLIENT_SLUG="clientname"
export CLIENT_DOMAIN="clientdomain.tld"
export MAIN_REPO="${CLIENT_SLUG}"
export ADMIN_REPO="${CLIENT_SLUG}-admin"
export FE_REPO="${CLIENT_SLUG}-fe"
export ADMIN_HOST="admin.${CLIENT_DOMAIN}"
export WP_ADMIN_USER="admin"
export WP_ADMIN_PASSWORD="change-this-password"
export WP_ADMIN_EMAIL="admin@${CLIENT_DOMAIN}"
export WORKDIR="${HOME}/workspaces/${CLIENT_SLUG}"
export SOURCE_MAIN_REPO="<approved-parent-example>"
export SOURCE_ADMIN_REPO="<approved-admin-example>"
export SOURCE_FE_REPO="<approved-frontend-example>"

Use lowercase kebab-case for CLIENT_SLUG. Do not include the customer legal name if it should not appear in GitHub URLs.

Set the SOURCE_* variables to the current approved internal example repositories before running the copy step.

Use this path for macOS workstations with Homebrew:

Terminal window
brew update
brew install git gh curl jq node composer ddev/ddev/ddev mkcert
brew install --cask docker
mkcert -install
corepack enable
corepack prepare pnpm@latest --activate
npm install -g wrangler@latest
git --version
gh --version
curl --version
jq --version
docker version
ddev --version
mkcert -help >/dev/null
node --version
pnpm --version
composer --version
wrangler --version

Start Docker Desktop before running DDEV commands.

Install or update required CLIs on Ubuntu or Debian

Section titled “Install or update required CLIs on Ubuntu or Debian”

Use this path for Ubuntu or Debian workstations:

Terminal window
sudo apt-get update
sudo apt-get install -y git curl jq ca-certificates gnupg lsb-release unzip
# Docker provider
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker "$USER"
# GitHub CLI
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | \
sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg >/dev/null
sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | \
sudo tee /etc/apt/sources.list.d/github-cli.list >/dev/null
sudo apt-get update
sudo apt-get install -y gh
# DDEV and mkcert
curl -fsSL https://ddev.com/install.sh | bash
mkcert -install
# Node, pnpm, Composer, Wrangler
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs composer
corepack enable
corepack prepare pnpm@latest --activate
sudo npm install -g wrangler@latest
git --version
gh --version
curl --version
jq --version
docker version
ddev --version
mkcert -help >/dev/null
node --version
pnpm --version
composer --version
wrangler --version

Log out and back in if Docker reports permission errors after adding the user to the docker group.

Authenticate GitHub and Cloudflare:

Terminal window
gh auth login
gh auth status
wrangler login
wrangler whoami

Create the Ploi API token and GitHub secrets using the Ploi Auth Config SOP:

https://sop.getquick.io/ploi-io/auth-config/

At minimum, plan for:

PLOI_API_TOKEN
PLOI_SERVER_ID
PLOI_SITE_ID
PLOI_USER_AGENT

Create all three repositories under Quick-Release:

Terminal window
gh repo create "${GITHUB_ORG}/${MAIN_REPO}" --private --confirm
gh repo create "${GITHUB_ORG}/${ADMIN_REPO}" --private --confirm
gh repo create "${GITHUB_ORG}/${FE_REPO}" --private --confirm

Confirm they exist:

Terminal window
gh repo view "${GITHUB_ORG}/${MAIN_REPO}" --json name,visibility,url
gh repo view "${GITHUB_ORG}/${ADMIN_REPO}" --json name,visibility,url
gh repo view "${GITHUB_ORG}/${FE_REPO}" --json name,visibility,url

Create local working copies from the approved examples

Section titled “Create local working copies from the approved examples”

Use the current approved internal examples as source workspaces. Keep the source repositories unchanged and copy into fresh target folders.

Terminal window
mkdir -p "$WORKDIR"
cd "$WORKDIR"
gh repo clone "${GITHUB_ORG}/${MAIN_REPO}" "${MAIN_REPO}"
gh repo clone "${GITHUB_ORG}/${ADMIN_REPO}" "${ADMIN_REPO}"
gh repo clone "${GITHUB_ORG}/${FE_REPO}" "${FE_REPO}"
mkdir -p "${WORKDIR}/_sources"
cd "${WORKDIR}/_sources"
gh repo clone "${GITHUB_ORG}/${SOURCE_MAIN_REPO}" parent-example
gh repo clone "${GITHUB_ORG}/${SOURCE_ADMIN_REPO}" admin-example
gh repo clone "${GITHUB_ORG}/${SOURCE_FE_REPO}" frontend-example

Copy source files into the new repositories without copying .git directories:

Terminal window
rsync -a --exclude ".git" --exclude "node_modules" --exclude "vendor" --exclude ".ddev/.global_commands" \
"${WORKDIR}/_sources/parent-example/" "${WORKDIR}/${MAIN_REPO}/"
rsync -a --exclude ".git" --exclude "node_modules" --exclude "vendor" \
"${WORKDIR}/_sources/admin-example/" "${WORKDIR}/${ADMIN_REPO}/"
rsync -a --exclude ".git" --exclude "node_modules" --exclude "dist" --exclude ".wrangler" \
"${WORKDIR}/_sources/frontend-example/" "${WORKDIR}/${FE_REPO}/"

Replace example names with client names before committing:

Terminal window
cd "$WORKDIR"
grep -R "<example-client>" "${MAIN_REPO}" "${ADMIN_REPO}" "${FE_REPO}" || true
find "${MAIN_REPO}" "${ADMIN_REPO}" "${FE_REPO}" -type f \
-not -path "*/.git/*" \
-not -path "*/node_modules/*" \
-not -path "*/vendor/*" \
-print0 | \
xargs -0 perl -pi -e "s/<example-client>/${CLIENT_SLUG}/g; s/<example-domain>/${CLIENT_DOMAIN}/g; s/admin\\.<example-domain>/${ADMIN_HOST}/g"

If source examples contain project-specific names that are not covered by these placeholders, replace them manually before the first commit.

Add the admin and frontend repositories as submodules:

Terminal window
cd "${WORKDIR}/${MAIN_REPO}"
rm -rf "${ADMIN_REPO}" "${FE_REPO}"
git submodule add "git@github.com:${GITHUB_ORG}/${ADMIN_REPO}.git" "${ADMIN_REPO}"
git submodule add "git@github.com:${GITHUB_ORG}/${FE_REPO}.git" "${FE_REPO}"
git submodule status

Update parent workspace references so scripts point at the generic submodule names:

Terminal window
grep -R "<admin-submodule>" . || true
grep -R "<frontend-submodule>" . || true

Expected final parent layout:

<client-slug>/
├── AGENTS.md
├── README.md
├── package.json
├── .gitmodules
├── <client-slug>-admin/
└── <client-slug>-fe/

Commit the parent workspace:

Terminal window
git add -A
git commit -m "Initial headless WooCommerce workspace"
git push -u origin main

Set up the Bedrock/DDEV admin repository:

Terminal window
cd "${WORKDIR}/${ADMIN_REPO}"
cp .env.example .env 2>/dev/null || true
perl -pi -e "s|^WP_HOME=.*|WP_HOME=https://${ADMIN_HOST}|; s|^WP_SITEURL=.*|WP_SITEURL=https://${ADMIN_HOST}/wp|" .env
ddev config --project-name "${ADMIN_REPO}" --project-type wordpress --docroot web --php-version 8.3
ddev start
ddev composer install

Install WordPress locally if the Bedrock setup does not already include a database:

Terminal window
ddev wp core install \
--url="https://${ADMIN_REPO}.ddev.site" \
--title="${CLIENT_SLUG} Admin" \
--admin_user="${WP_ADMIN_USER}" \
--admin_password="${WP_ADMIN_PASSWORD}" \
--admin_email="${WP_ADMIN_EMAIL}" \
--skip-email

Install or activate required WordPress components for headless WooCommerce:

Terminal window
ddev wp plugin activate woocommerce || ddev wp plugin install woocommerce --activate
ddev wp plugin activate wp-graphql || ddev wp plugin install wp-graphql --activate
ddev wp rewrite structure '/%postname%/' --hard
ddev wp rewrite flush --hard

Commit and push the admin repo:

Terminal window
git add -A
git commit -m "Initial Bedrock WooCommerce admin"
git push -u origin main

In Ploi:

  1. Create or choose the server.
  2. Create a site for admin.${CLIENT_DOMAIN}.
  3. Set the repository to git@github.com:${GITHUB_ORG}/${ADMIN_REPO}.git.
  4. Set the deploy branch to main.
  5. Configure the site as a Bedrock WordPress project.
  6. Add environment variables from the admin .env, replacing local values with production values.
  7. Add the database credentials Ploi created for the site.
  8. Configure SSL for admin.${CLIENT_DOMAIN}.
  9. Deploy once from Ploi.

Add GitHub secrets and variables for automation:

Terminal window
cd "${WORKDIR}/${ADMIN_REPO}"
gh secret set PLOI_API_TOKEN --repo "${GITHUB_ORG}/${ADMIN_REPO}"
gh variable set PLOI_SERVER_ID --repo "${GITHUB_ORG}/${ADMIN_REPO}" --body "<ploi-server-id>"
gh variable set PLOI_SITE_ID --repo "${GITHUB_ORG}/${ADMIN_REPO}" --body "<ploi-site-id>"
gh variable set PLOI_USER_AGENT --repo "${GITHUB_ORG}/${ADMIN_REPO}" --body "${ADMIN_REPO}-github-actions"

Set up the frontend repository:

Terminal window
cd "${WORKDIR}/${FE_REPO}"
pnpm install
pnpm exec wrangler init --from-dash "${FE_REPO}" || true
pnpm exec wrangler types

Create or update the frontend environment file:

Terminal window
cat > .env.example <<EOF
PUBLIC_SITE_URL=https://${CLIENT_DOMAIN}
WORDPRESS_URL=https://${ADMIN_HOST}
WORDPRESS_GRAPHQL_URL=https://${ADMIN_HOST}/graphql
WOOCOMMERCE_STORE_URL=https://${ADMIN_HOST}
EOF
cp .env.example .env

Confirm the frontend can build:

Terminal window
pnpm build

Commit and push the frontend repo:

Terminal window
git add -A
git commit -m "Initial Astro WooCommerce frontend"
git push -u origin main

Register or connect the domain with the Cloudflare domain SOP if needed:

https://sop.getquick.io/cloudflare/register-a-domain-with-cloudflare/

Deploy the frontend:

Terminal window
cd "${WORKDIR}/${FE_REPO}"
pnpm build
pnpm exec wrangler deploy

If the Worker uses secrets, set them with Wrangler:

Terminal window
pnpm exec wrangler secret put WORDPRESS_GRAPHQL_URL
pnpm exec wrangler secret put WOOCOMMERCE_CONSUMER_KEY
pnpm exec wrangler secret put WOOCOMMERCE_CONSUMER_SECRET

Only set WooCommerce API credentials if the frontend requires authenticated server-side WooCommerce API access. Prefer public GraphQL or Store API data when possible.

After the admin and frontend repos are pushed, update the parent submodule SHAs:

Terminal window
cd "${WORKDIR}/${MAIN_REPO}"
git submodule update --remote --merge
git status
git add "${ADMIN_REPO}" "${FE_REPO}" .gitmodules
git commit -m "Bump initial admin and frontend submodules"
git push

Validate GitHub repositories:

Terminal window
gh repo view "${GITHUB_ORG}/${MAIN_REPO}" --json name,visibility,url
gh repo view "${GITHUB_ORG}/${ADMIN_REPO}" --json name,visibility,url
gh repo view "${GITHUB_ORG}/${FE_REPO}" --json name,visibility,url

Validate submodules:

Terminal window
cd "${WORKDIR}/${MAIN_REPO}"
git submodule status
git config --file .gitmodules --get-regexp path

Expected result: the admin and frontend submodules are present and have pinned SHAs.

Validate WordPress locally:

Terminal window
cd "${WORKDIR}/${ADMIN_REPO}"
ddev describe
ddev wp option get home
ddev wp plugin status woocommerce
ddev wp plugin status wp-graphql
curl -I "https://${ADMIN_REPO}.ddev.site"

Validate Ploi readiness:

Terminal window
curl -fsS https://ploi.io/api/servers \
-H "Authorization: Bearer $PLOI_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Agent: ${ADMIN_REPO}-smoke-test"

Validate Astro and Cloudflare:

Terminal window
cd "${WORKDIR}/${FE_REPO}"
pnpm build
pnpm exec wrangler whoami
pnpm exec wrangler deploy --dry-run

Validate final DNS and HTTPS:

Terminal window
dig A "${CLIENT_DOMAIN}"
dig CNAME "www.${CLIENT_DOMAIN}"
dig A "${ADMIN_HOST}"
curl -I "https://${CLIENT_DOMAIN}"
curl -I "https://${ADMIN_HOST}"

Expected result:

  • https://${ADMIN_HOST} reaches the Ploi WordPress admin site.
  • https://${CLIENT_DOMAIN} reaches the Astro frontend on Cloudflare Workers.
  • The parent repo records the exact admin and frontend submodule commits.

Use this article when a user asks for a new WooCommerce headless stack, a three-repository WordPress/Astro workspace, or a GETQUICK storefront blueprint.

Do not place this workflow under the Agents category. It is a human operational blueprint.

Retrieve current docs before executing provider-specific steps:

  • GitHub CLI: https://github.com/cli/cli
  • DDEV: https://docs.ddev.com/en/stable/users/install/ddev-installation/
  • Cloudflare Wrangler: https://developers.cloudflare.com/workers/wrangler/commands/general/
  • Ploi API: https://developers.ploi.io/

Never commit secrets. Use GitHub Secrets, Wrangler secrets, Ploi environment variables, or local untracked .env files.

Important search terms: WooCommerce headless, Bedrock, DDEV, Ploi, Cloudflare Workers, Astro frontend, GitHub submodules, WordPress admin, storefront.

  • If gh repo create fails, run gh auth status and confirm the user has permission to create repositories under Quick-Release.
  • If submodule clone fails, confirm SSH access to all private repositories.
  • If DDEV fails to start, confirm Docker is running and the current user can access Docker.
  • If ddev composer install fails, check Composer authentication for private packages.
  • If WordPress install fails, confirm the Bedrock .env database values match DDEV.
  • If WooCommerce or WPGraphQL activation fails, confirm the packages are installed or add them through Composer/WP-CLI according to the admin repo pattern.
  • If Ploi deployment fails, confirm repository access, deploy branch, production .env, database credentials, and Ploi token scopes.
  • If Wrangler deployment fails, run wrangler whoami, confirm the Cloudflare account, and check wrangler.jsonc.
  • If the frontend cannot fetch WordPress data, verify WORDPRESS_GRAPHQL_URL, CORS, SSL, and that the admin host is reachable.