| Server IP : 3.147.158.171 / Your IP : 216.73.216.88 Web Server : Apache/2.4.67 (Amazon Linux) OpenSSL/3.5.5 System : Linux ip-172-31-2-178.us-east-2.compute.internal 6.1.172-216.329.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Wed May 20 06:31:34 UTC 2026 x86_64 User : ec2-user ( 1000) PHP Version : 8.4.21 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /tsai/repo/.claude/skills/create-site-from-doc/ |
Upload File : |
---
name: create-site-from-doc
description: Provision a new site end-to-end from a /docs/{slug}.md site doc — runs create-{env}-site.json on the production server, creates one character per author, and creates each category in WordPress.
argument-hint: <env> <slug> [favicon-bg] [favicon-fg] [favicon-char]
---
# Create Site From Doc
Provision a new WordPress + chatbot site on a production server, then populate it with the authors (as characters) and categories defined in a site doc previously generated by `/create-site-doc`.
**Arguments:** $ARGUMENTS
Parse as:
- `env` — first token: `tsai` or `scike`
- `slug` — second token; must match the doc filename at `/Users/jturman/development/john/docs/{slug}.md`
- `favicon-bg` (optional) — color value (e.g. `azure`, `violet`, `green`)
- `favicon-fg` (optional) — color value (e.g. `white`, `black`)
- `favicon-char` (optional) — single character; defaults to uppercase first letter of slug
If `env` or `slug` is missing, ask the user before proceeding.
---
## Environment constants
| env | SSH host | Repo path | Domain | Site dir | TSAI_ENV |
|-----|----------|-----------|--------|----------|----------|
| `tsai` | `ssh -i ~/.ssh/tsai.pem ec2-user@3.147.158.171` | `/tsai/repo` | `turmansolutions.ai` | `/tsai/repo/sites/{slug}` | `production` |
| `scike` | `ssh -i ~/.ssh/tsai.pem ec2-user@scike.ai` | `/data/tsai` | `scike.ai` | `/data/tsai/sites/scike-{slug}` | `scike_ai` |
---
## Step 1 — Load and parse the site doc
Read `/Users/jturman/development/john/docs/{slug}.md`.
Extract:
- **Site name** — the H1 heading (`# {Site Name}`).
- **Slug check** — confirm `**Slug:** {slug}` matches the argument. If not, stop and report mismatch.
- **Authors** — every `### {Author Name}` heading under `## Authors`, paired with its following paragraph(s) (the "You are a…" description).
- **Categories** — every `- **{Name}** — {rationale}` line under `## Categories`.
If the file is missing, the slug doesn't match, or authors/categories are empty, stop and tell the user to run `/create-site-doc {slug}` first.
---
## Step 2 — Confirm the plan once
Print a single summary to the user. Compute favicon defaults: char defaults to the slug's first letter uppercased; bg defaults to `azure`; fg defaults to `white` (override if user passed them).
```
Provisioning plan
─────────────────
Site: {Site Name} ({slug}) on {env}
WP domain: https://{slug}.{domain}
CB domain: https://chat-{slug}.{domain}
Favicon: char={X} bg={…} fg={…}
Authors: {N} — {comma-separated names}
Categories: {M} — {comma-separated names}
```
Wait for explicit user confirmation (e.g. "go", "yes", "proceed"). After confirmation, do not prompt again — run Steps 3, 4, 5, 6 straight through.
---
## Step 3 — Provision the site
SSH to the env's server and invoke `run_build.py` with the env's site-creation config. Use the project's venv per established convention.
Single-quote-escape `{site name}` for the shell (replace `'` with `'"'"'`). Build the favicon flag string only for args the user supplied (omit otherwise so the JSON config's defaults apply):
```bash
ssh -i ~/.ssh/tsai.pem ec2-user@{host} \
"cd {repo}/builder/backend && ./venv/bin/python run_build.py \
--config configs/create-{env}-site.json \
--slug '{slug}' \
--site-name '{escaped_site_name}'"
```
(Favicon params are not yet wired through `run_build.py` CLI args; rely on the JSON config's defaults for now and document the limitation in the report if the user passed favicon args.)
Stream output. If the SSH command exits non-zero, **stop**. The site-create JSON config has `stop_on_failure: true`, so partial state will be left for the user to inspect/clean up. Do not proceed to character or category creation.
Capture the `PASSWORD_RESET_URL=…` line from the output for the final report.
---
## Step 4 — Create each character
For every `(name, description)` from the doc, run `create_character.py` over SSH — same invocation shape used by `/create-character` Step 5, but with the description from the doc passed through verbatim (no name proposal, no description expansion — the doc is already approved).
For each author, before running, escape single quotes in both name and description with `'"'"'`.
```bash
ssh -i ~/.ssh/tsai.pem ec2-user@{host} \
"cd {repo}/api && source venv/bin/activate && \
python3 create_character.py '{escaped_name}' '{slug}' \
--env {tsai_env} \
--description '{escaped_description}' \
--articles-per-day 0 \
--comments-per-day 0 \
--provider Claude \
--model-name claude-sonnet-4-6"
```
Run **serially**, not in parallel — `create_character.py` writes to Drupal and triggers index rebuilds, so concurrent runs can race.
Track per-author outcome: parse the script's output for the `storageId` and WP user id on success, or capture the error on failure. **Continue on individual failures** — one bad character should not block the rest — but log failures into a list for the final report.
---
## Step 5 — Create each category
For every `(name, rationale)` from the doc, run `wp term create` against the new site directory on the same server. Escape single quotes with `'"'"'` in both fields.
```bash
ssh -i ~/.ssh/tsai.pem ec2-user@{host} \
"wp term create category '{escaped_name}' \
--description='{escaped_rationale}' \
--path={site_dir}"
```
Where `{site_dir}` is `/tsai/repo/sites/{slug}` (tsai) or `/data/tsai/sites/scike-{slug}` (scike).
Continue on individual failures; collect failures for the final report.
---
## Step 6 — Report
Print a summary:
```
✓ Site live: https://{slug}.{domain}
✓ Admin URL: https://{slug}.{domain}/wp-admin/
Admin user: admin
Admin pass: 33Friday@33 (from create-{env}-site.json)
Password reset (one-time): {PASSWORD_RESET_URL from Step 3}
✓ Chatbot: https://chat-{slug}.{domain}
Characters: {created}/{total}
• {name} — storageId {id}
• {name} — storageId {id}
…
Failures: {name} — {error} (only if any)
Categories: {created}/{total}
Failures: {name} — {error} (only if any)
Next steps:
- Configure article/comment schedules via the Creator app or /schedule-characters
- Visit the admin URL above to verify content, then change the admin password
```
If favicon params were passed but ignored in Step 3, note that explicitly in the report.