Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: docker-presentation-server description: > Deploy brand presentation HTML pages via Docker nginx, serve them for client review, and generate desktop screenshots using headless Chrome. Use when (1) user asks to 'deploy presentation', 'serve brand pages', 'start presentation server', (2) brand presentation HTML files exist and need to be viewable in a browser, (3) user asks for 'screenshots' of brand presentation pages, (4) any agent needs to capture visual snapshots of HTML presentation artifacts, (5) user mentions 'docker nginx' in context of serving presentation files. Handles container lifecycle, nginx config, container IP discovery (required for MCP Playwright inside Docker), and reliable host-side screenshot generation via google-chrome --headless.
Docker Presentation Server
Executor: Any Team Durham agentType: Infrastructure + Screenshot capturePrerequisite: Built presentation HTML pages (frombrand-presentation-builderskill)group_id:allura-team-durham
Purpose
Brand presentations must be viewable in a real browser for two reasons: (1) clients interact with them via URL, and (2) automated screenshots require a served URL. Docker nginx:alpine provides a lightweight, disposable web server that serves static HTML with zero config. Screen captures are the primary deliverable — they become the visual record of what the client saw and get published to Notion.
Container Deployment
Step 1: Verify Prerequisites
# Confirm presentation artifacts directory existsls clients/{client-slug}/presentation-artifacts/*.html# Confirm screenshots directory exists (create if missing)mkdir -p clients/{client-slug}/presentation-artifacts/screenshots
Step 2: Launch nginx Container
docker run -d \--name {client-slug}-brand-presentation \-p 8080:80 \-v "$(pwd)/clients/{client-slug}/presentation-artifacts:/usr/share/nginx/html:ro" \-v "$(pwd)/clients/{client-slug}/presentation-artifacts/screenshots:/usr/share/nginx/html/screenshots" \nginx:alpine
Why these volume mounts:
presentation-artifacts/→/usr/share/nginx/html(read-only): Serves all HTML, SVGsscreenshots/→ writable mount: Allows MCP Playwright screenshot saves (if used)- Port 8080: Standard presentation port, change if occupied (
docker psfirst)
If port 8080 is occupied:
# Find open portss -tlnp | grep -E '808[0-9]'# Or use alternate portdocker run -d --name {client-slug}-brand-presentation -p 8081:80 ...
Step 3: Verify Server Is Running
# Check container is updocker ps | grep presentation# Test with curlcurl -s -o /dev/null -w "%{http_code}" http://localhost:8080/brand-overview.html# Expected: 200
Step 4: Discover Container IP (for MCP Playwright)
MCP Playwright runs inside the Docker network and cannot resolve localhost:8080. The container IP is required.
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' {client-slug}-brand-presentation# Example output: 172.17.0.2
Use this IP when navigating MCP Playwright: http://172.17.0.2/brand-overview.html
Screenshot Generation
Recommended Method: Headless Google Chrome
Why Chrome over MCP Playwright: MCP Playwright saves files inside the container overlay filesystem — there is no reliable way to extract them to the host. Headless Chrome runs on the host and writes directly to the host filesystem.
google-chrome \--headless=new \--disable-gpu \--screenshot="clients/{client-slug}/presentation-artifacts/screenshots/01-brand-overview.png" \--window-size=1440,900 \http://localhost:8080/brand-overview.html
Screenshot Sequence
Generate one screenshot per presentation page. Use consistent naming:
| File | Page | URL | |
|---|---|---|---|
01-brand-overview.png | Brand Overview | /brand-overview.html | |
02-logo-chooser.png | Logo Chooser | /logo-chooser.html | |
03-color-system.png | Color System | /color-system.html | |
04-typography.png | Typography | /typography.html | |
05-applications.png | Applications | /applications.html |
Full Screenshot Script
CLIENT_SLUG="{client-slug}"SCREENSHOT_DIR="clients/${CLIENT_SLUG}/presentation-artifacts/screenshots"BASE_URL="http://localhost:8080"PAGES=("brand-overview.html:01-brand-overview.png""logo-chooser.html:02-logo-chooser.png""color-system.html:03-color-system.png""typography.html:04-typography.png""applications.html:05-applications.png")for PAGE in "${PAGES[@]}"; doIFS=":" read -r HTML FILENAME <<< "$PAGE"google-chrome \--headless=new \--disable-gpu \--screenshot="${SCREENSHOT_DIR}/${FILENAME}" \--window-size=1440,900 \"${BASE_URL}/${HTML}"echo "Captured: ${FILENAME}"done
Alternative: MCP Playwright (when Chrome unavailable)
If google-chrome is not installed, MCP Playwright can navigate and screenshot, but files will be saved inside the container:
// Via MCP_DOCKER_browser_navigatebrowser_navigate({ url: "http://172.17.0.2/brand-overview.html" })// Then screenshotbrowser_take_screenshot({ type: "png", filename: "screenshots/01-brand-overview.png" })
Caveat: These screenshots land in the container's writable overlay, not on the host. Use docker cp to extract:
docker cp {client-slug}-brand-presentation:/usr/share/nginx/html/screenshots/ \clients/{client-slug}/presentation-artifacts/screenshots/
Alternative: npx Playwright (if installed)
npx playwright screenshot --viewport-size="1440,900" \http://localhost:8080/brand-overview.html \clients/{client-slug}/presentation-artifacts/screenshots/01-brand-overview.png
Prerequisite: npx playwright install must have been run to download browser binaries.
Container Management
Check Running Presentation Servers
docker ps --filter "name=presentation" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
Stop a Presentation Server
docker stop {client-slug}-brand-presentationdocker rm {client-slug}-brand-presentation
Restart (if HTML files were updated)
docker restart {client-slug}-brand-presentation
Screenshot Quality Verification
After generating screenshots, verify:
- File size > 0 — Empty files mean the page didn't render
- File size > 50KB — Screenshots under 50KB are likely blank or error pages
- Correct dimensions — 1440px width expected
ls -la clients/{client-slug}/presentation-artifacts/screenshots/# Check all 5 files exist and are > 50KB
Troubleshooting
| Symptom | Cause | Fix | |
|---|---|---|---|
curl returns 404 | Volume mount path wrong | Verify $(pwd) resolves correctly; use absolute paths | |
curl returns connection refused | Container not running | docker ps to check; docker restart if stopped | |
| MCP Playwright can't connect | Needs container IP, not localhost | Use docker inspect to get IP, navigate to http://{IP}/ | |
Chrome crashes on --screenshot | Missing --disable-gpu flag | Add --disable-gpu to Chrome flags | |
| Screenshots are blank | Page hasn't loaded before capture | Add --virtual-time-budget=5000 flag | |
| Port already in use | Another container on 8080 | docker stop old container or use -p 8081:80 | |
| Screenshots not appearing on host | Using MCP Playwright inside container | Switch to host-side google-chrome --headless or docker cp |
Output Handoff
After screenshots are generated and verified, pass control to:
- `notion-brand-publisher` skill — Upload screenshots and links to Notion client page
- Client communication — Share
http://localhost:8080/URL (or container IP) with client