demo-site-management
Manages the Umbraco.AI demo site for development. Handles starting with DemoSite-Claude profile, port discovery via named pipes, and OpenAPI client generation. Use when starting, stopping, or checking the demo site, or when generating OpenAPI clients for frontend development.
SKILL.md
| Name | demo-site-management |
| Description | Manages the Umbraco.AI demo site for development. Handles starting with DemoSite-Claude profile, port discovery via named pipes, and OpenAPI client generation. Use when starting, stopping, or checking the demo site, or when generating OpenAPI clients for frontend development. |
name: demo-site-management description: Manages the Umbraco.AI demo site for development. Handles starting with DemoSite-Claude profile, port discovery via named pipes, and OpenAPI client generation. Use when starting, stopping, or checking the demo site, or when generating OpenAPI clients for frontend development. argument-hint: [start|stop|generate-client|status|restart|open] allowed-tools: Bash, Read, TaskOutput, TaskStop
Demo Site Management
Manage the Umbraco.AI demo site with automatic port discovery via named pipes.
Command: $ARGUMENTS
Execute the requested demo site operation.
Available commands
- start: Start demo site with DemoSite-Claude profile on dynamic port
- stop: Stop the running demo site
- generate-client: Generate OpenAPI clients (starts site if needed)
- status: Check if site is running and show port/pipe info
- restart: Stop and restart the demo site
- open: Open the demo site in default browser (discovers port automatically)
Current Environment
- Working directory: !
pwd - Git branch: !
git branch --show-current 2>/dev/null || echo "not in git repo" - Background tasks: !
echo "Check with /tasks command for active background tasks"
Implementation Guide
For "start"
- Check if already running using multi-method detection:
- Try querying site address endpoint via named pipe (see "Query site address via named pipe" section)
- Check if background tasks exist with "DemoSite" in description
- If running, report and exit
- If not running, start in background:
cd demo/Umbraco.AI.DemoSite && dotnet run --launch-profile DemoSite-Claude - Wait 15-20 seconds for startup
- Query site address endpoint via named pipe to get port and pipe name (see "Query site address via named pipe" section)
- Report:
- Task ID for later stopping (save this for future commands)
- Port number (from site address endpoint)
- Pipe name (format: umbraco.demosite.{branch-or-worktree})
- Site URL
For "stop"
-
Find background tasks related to demo site:
- Look for tasks with "DemoSite" or "demo-site" in name
- Extract task ID from task list
-
If task found:
- Use TaskStop with the task ID to stop gracefully
- Wait 2-3 seconds for cleanup
-
If no task found:
- Report that no running demo site was found
- Suggest checking with
/demo-site-management status
-
Verify shutdown:
- Try connecting to the last known port (should fail)
- Check if background task is gone
-
Report results:
- Success: "Demo site stopped (task ID: {id})"
- Failure: "Could not find running demo site"
- Note: Pipes are automatically cleaned up when process exits
For "generate-client"
- Check if site is running:
- Try querying site address endpoint via named pipe (see "Query site address via named pipe" section)
- Check if any background bash tasks are related to DemoSite
- If not running, report error with suggestion: "Demo site not running. Start it with
/demo-site-management start" - Run:
npm run generate-client(runs all three packages concurrently) - Monitor output for:
- "Using named pipe: umbraco.demosite.{identifier}" (should appear 3 times)
- "✓ TypeScript client generated successfully" (should appear 3 times)
- No errors (EPIPE, connection refused, etc.)
- Report summary:
- Success/failure for each package (core, prompt, agent)
- Pipe name used
- Whether concurrent connections worked (no errors)
For "status"
Use multi-method detection to determine site status:
-
Query site address endpoint: Try querying via named pipe (see "Query site address via named pipe" section)
- If successful, site is running and you have port info
- If fails, continue to other methods
-
Check background tasks: Look for tasks with "DemoSite" or "demo-site" in name/output
- If found, extract task ID
-
Determine git context:
- Run
git rev-parse --git-dirto check if worktree - If worktree, extract name from
.git/worktrees/{name} - Otherwise use
git branch --show-current - If no git, identifier is "default"
- Run
-
Report comprehensive status:
- Running: yes/no (based on site address endpoint response)
- Task ID: if background task found
- Port: from site address endpoint
- Pipe name:
umbraco.demosite.{identifier} - Git context: branch name, worktree name, or "not in git repo"
- Suggestion: How to start if not running, or how to connect if running
For "restart"
Execute stop operation, wait 3 seconds, then execute start operation.
For "open"
- Check if demo site is running and get port info:
- Query site address endpoint via named pipe (see "Query site address via named pipe" section)
- If fails, report error: "Demo site not running. Start it with
/demo-site-management start"
- Launch default browser with discovered URL:
- Windows:
powershell.exe -Command "Start-Process 'https://127.0.0.1:<port>'" - Linux:
xdg-open https://127.0.0.1:<port> - macOS:
open https://127.0.0.1:<port>
- Windows:
- Report:
- Browser launched
- URL opened
- Note about certificate warning (self-signed HTTPS)
- Credentials reminder: admin@example.com / password1234
Query Site Address via Named Pipe
The demo site exposes a /site-address endpoint that returns port and pipe information as JSON.
Query it via HTTP over named pipes without needing to know the port:
Using Node.js (recommended, cross-platform):
import http from "http";
import { execSync } from "child_process";
// Get pipe name from git context
function getIdentifier() {
try {
const gitDir = execSync("git rev-parse --git-dir", { encoding: "utf-8" }).trim();
if (gitDir.includes("worktrees")) {
return gitDir.split(/[\\\/]/).find((p, i, arr) => arr[i - 1] === "worktrees") || "default";
}
return execSync("git branch --show-current", { encoding: "utf-8" }).trim() || "default";
} catch {
return "default";
}
}
const identifier = getIdentifier().replace(/[^a-zA-Z0-9\-_.]/g, "") || "default";
const pipeName = `umbraco.demosite.${identifier}`;
const socketPath = process.platform === "win32" ? `\\\\.\\pipe\\${pipeName}` : `/tmp/${pipeName}`;
const address = await new Promise((resolve, reject) => {
http.get({ socketPath, path: "/site-address" }, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => (res.statusCode === 200 ? resolve(body) : reject(new Error(`HTTP ${res.statusCode}`))));
}).on("error", reject);
});
// address = "https://127.0.0.1:44355"
Using curl (PowerShell on Windows):
$identifier = (git branch --show-current).Trim() -replace '[^a-zA-Z0-9\-_]', ''
$pipeName = "umbraco.demosite.$identifier"
curl.exe --unix-socket "//./pipe/$pipeName" http://localhost/site-address
Response format: Plain text HTTPS address
https://127.0.0.1:44355
Detection Helper Commands
Use these commands for reliable cross-platform detection:
Check for background tasks:
# Look for tasks with DemoSite in output (path varies by platform)
# Use /tasks command or check TaskOutput for running demo site tasks
Determine git identifier:
# Get worktree or branch name
git_dir=$(git rev-parse --git-dir 2>/dev/null)
if [[ "$git_dir" == *"worktrees"* ]]; then
echo "worktree: $(basename $(dirname $git_dir))"
else
echo "branch: $(git branch --show-current 2>/dev/null || echo 'not-in-git')"
fi
Port Discovery Details
The demo site uses HTTP over named pipes for automatic port discovery:
- Pipe naming:
umbraco.demosite.<identifier> - Identifier logic:
- Worktree: extracted from
.git/worktrees/<name> - Main repo: current branch name
- No git:
default
- Worktree: extracted from
- Site address endpoint:
/site-address(returns HTTPS address as plain text) - HTTP transport: Kestrel listens on both named pipe and HTTP/HTTPS
- Concurrent support: Multiple clients can connect simultaneously
- Implementation:
demo/Umbraco.AI.DemoSite/Composers/NamedPipeListenerComposer.cs
Common Issues
Pipe not found
- Demo site not running or still starting up
- Solution: Wait 15-20 seconds after start, or check status with
/demo-site-management status
Connection refused
- Pipe doesn't exist or connection failed
- Check that site is running:
/demo-site-management status - Verify pipe name matches git context (branch/worktree)
Multiple instances conflict
- Each worktree/branch gets unique pipe name
- Main branch:
umbraco.demosite.<branch-name> - Worktree:
umbraco.demosite.<worktree-name> - No git:
umbraco.demosite.default
Success Criteria
After start: Report task ID, pipe name, port, and URL After stop: Confirm process stopped successfully After generate-client: Show success for all three packages (core, prompt, agent) After status: Show running state, port, and pipe connection details