skills/app-polish/SKILL.md
--- name: app-polish description: Post-ship launch-ready polish audit. Walks a freshly-shipped web app against the ten-point launch-polish checklist (analytics, stats surface, OG images, PWA, SEO, keyboard, accessibility, visual regression, API docs, craft signals) and routes to the dedicated sub-skill for each gap. Use right after `/ro:cf-ship` / `/ro:fly-deploy` / `/ro:gh-ship`, or before a Product Hunt / Show HN launch. category: quality-review argument-hint: [--app <dir>] [--only <checks>] [
npx skillsauth add RonanCodes/ronan-skills skills/app-polishInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Pre-launch audit for a web app. Walks ten checks in order; for each gap, routes to a dedicated sub-skill that actually does the work. Designed to run on the Friday before a Tuesday / Wednesday launch.
/ro:app-polish # audit current repo, report gaps
/ro:app-polish --app ./connections-helper
/ro:app-polish --only analytics,og # run only a subset
/ro:app-polish --skip pwa,visual-reg # skip items not applicable
/ro:app-polish --fix # auto-invoke each sub-skill for gaps found
Report format per check:
[✓|⚠|✗] <check> — <one-line finding>
Sub-skill: /ro:<skill>
Effort: <S|M|L>
Launch impact: <high|medium|low>
Run in this order (earlier items compound into later ones — e.g. analytics events need to exist before visual regression baselines get captured).
/ro:posthogIs there an analytics provider wired up? Are custom events fired on share handlers, CTAs, forms? Is there a typed track() wrapper?
Detect:
grep -rn "posthog.init\|plausible.init\|Mixpanel" src 2>&1 | head -3
grep -rn "posthog.capture\|track(" src 2>&1 | wc -l
Verdict rules:
track() wrapper exists + share/cta/form events fired.Fix: invoke /ro:posthog install if missing, then see the "Launch-ready event instrumentation" section for the event checklist.
Is there a stats endpoint (counts, usage, reach) and is it displayed in the UI? Numbers on a page are a low-cost trust signal.
Detect:
grep -rn "/api/stats\|/api/metrics\|/api/health" src --include='*.ts' --include='*.tsx' | head
grep -rn "toLocaleString\|stats\." src/routes src/components 2>&1 | head
Verdict rules:
Fix: add a StatsBanner component (see seo-launch-ready for template) that fetch('/api/stats') + renders counts with toLocaleString(). Keep it aria-live="polite".
/ro:og-image-dynamicEvery share-target URL should unfurl with a distinct Open Graph image. Generic static OG kills click-through on Twitter/Reddit/LinkedIn previews.
Detect:
grep -rn 'og:image\|twitter:image' src 2>&1 | head
ls -la public/*.png 2>&1 | head
Verdict:
og-image.png for all URLs./api/og.png (or similar) exists and meta tags reference a per-URL variant.Fix: /ro:og-image-dynamic — Satori + Cloudflare Workers or Vercel OG template.
/ro:pwa-installDaily-return apps (puzzles, habit trackers, dashboards) should be installable. Replaces the need for an email list.
Detect:
ls public/manifest.json public/manifest.webmanifest 2>&1
ls public/sw.js public/service-worker.js 2>&1
grep -rn 'link.*rel="manifest"' src 2>&1 | head -3
Verdict:
Fix: /ro:pwa-install.
/ro:seo-launch-readySitemap, robots.txt, JSON-LD structured data, canonical URLs, meta tags complete across all routes.
Detect:
ls public/sitemap.xml public/robots.txt 2>&1
grep -rn 'application/ld+json\|canonical\|og:title' src 2>&1 | head
Verdict:
Fix: /ro:seo-launch-ready.
/ro:keyboard-shortcutsPower-user signal that drives screencasts and portfolio respect. Especially for utility apps.
Detect:
grep -rn "addEventListener.*keydown\|useHotkeys\|useKeyboard" src 2>&1 | head -3
Verdict:
? brings up a shortcut list and main actions have bindings.Fix: /ro:keyboard-shortcuts.
/ro:accessibility-ciaria-live regions on async state, focus management in modals, colour contrast, axe-core unit + e2e, Lighthouse CI.
Detect:
grep -rn 'aria-live\|aria-label\|role=' src 2>&1 | wc -l
grep -l 'axe-core\|@axe-core/playwright\|jest-axe' package.json 2>&1
ls .github/workflows 2>&1 | head
Verdict:
aria-live on any async region, or axe-core not in deps.Fix: /ro:accessibility-ci.
/ro:visual-regressionPlaywright screenshot baselines + PR diff comments. Protects the polish work from silent CSS regressions.
Detect:
grep -rn 'toHaveScreenshot\|pixelmatch\|percy' tests e2e 2>&1 | head
Verdict:
toHaveScreenshot assertions.Fix: /ro:visual-regression.
Scalar / Swagger / Redoc docs exposed and linked from the footer. Craft signal.
Detect:
grep -rn '/api/docs\|/api/openapi\|@scalar\|swagger-ui' src 2>&1 | head
grep -rn 'footer.*API\|footer.*docs' src 2>&1 | head
Verdict:
/how-it-works has a visible link.Fix: add <a href="/api/docs" target="_blank">API</a> in the footer.
Miscellaneous polish: robots meta, canonical URL, 404 page, aria-label on all icon-only buttons, environment-specific favicon (optional), skip-to-content link.
Detect:
grep -rn 'skip.*content\|skip.*main' src 2>&1 | head
find src -name 'not-found*' -o -name '404*' 2>&1 | head
grep -rn '<Button[^>]*onClick' src/App.tsx | grep -v 'aria-label\|title' | head
Verdict:
aria-label, or no 404 route.Fix: spot-fix, no dedicated sub-skill.
#!/usr/bin/env bash
# /ro:app-polish implementation sketch
set -euo pipefail
APP=${1:-.}
cd "$APP"
echo "=== App Polish Audit: $(pwd) ==="
echo
# 1. Analytics
if grep -rn "posthog.init\|plausible.init" src >/dev/null 2>&1; then
events=$(grep -rn "track(\|posthog.capture" src 2>/dev/null | wc -l | tr -d ' ')
if [ "$events" -ge 3 ]; then
echo "[✓] analytics — provider + $events custom event call sites"
else
echo "[⚠] analytics — provider wired but only $events custom events (need ≥3)"
echo " Sub-skill: /ro:posthog · Effort: S · Impact: high"
fi
else
echo "[✗] analytics — no provider detected"
echo " Sub-skill: /ro:posthog · Effort: S · Impact: high"
fi
# ...(repeat for 2-10)
The --fix flag invokes the sub-skill for each ⚠ or ✗ in sequence, with a confirmation prompt per skill.
| Existing skill | Role in polish |
| --- | --- |
| /ro:close-the-loop | Runs the app's own test suite; polish is what to run on top of tests passing. |
| /ro:playwright-check | Underlying browser tool; visual-regression uses it for baselines. |
| /ro:visual-diff | Per-image pixel diff; visual-regression composes this into a CI flow. |
| /ro:design-system-audit | Deeper audit of colour tokens, spacing, typography. Run alongside app-polish for the visual axis. |
| /ro:security-audit | Secrets, headers, rate limits, CSP. Complementary to polish. |
| /ro:cf-ship / /ro:fly-deploy / /ro:gh-ship | What ships the app; app-polish runs right after a successful ship, before the marketing beat. |
--fix. The user should pick which gaps to close./ro:close-the-loop is the per-PR gate./ro:posthog — analytics + event instrumentation/ro:og-image-dynamic — per-URL Open Graph images/ro:pwa-install — manifest + service worker/ro:seo-launch-ready — sitemap + JSON-LD + meta/ro:keyboard-shortcuts — global key handler/ro:accessibility-ci — axe + Lighthouse + a11y unit tests/ro:visual-regression — Playwright screenshot baselines/ro:design-system-audit — visual invariants/ro:security-audit — CSP, secrets, rate limiting/ro:close-the-loop — per-PR verification, complements polishdevelopment
--- name: worktree description: Coordinate multiple agents on one repo via a worktree-lock pool, so two agents never clobber each other's working tree. Acquire the first free slot (main, then beta/gamma… worktrees, created on demand), work there on your own branch, release when you've pushed. Use before modifying any repo that might be in use by another agent (factory, dataforce, etc.), or whenever you're told a repo is being worked on. Backed by `ro worktree`. category: development argument-hin
testing
--- name: ship description: Ship a feature branch the local-CI-first way — run the full local gate, push, open a PR, squash-merge, then deploy, without waiting on GitHub Actions. Use when a branch is ready for main and you want it merged and deployed now. Reads CI policy from `ro ci` (default skips remote CI because GitHub Actions billing keeps hitting limits). Sibling to /ro:gh-ship (waits on GitHub checks) and /ro:cf-ship (the deploy half). Triggers on "ship it", "ship this", "merge and deploy
testing
--- name: setup-logging description: Set up (or audit) the observability stack in a TanStack Start + Cloudflare Workers app so it is "diagnosable by default" — structured logging (logtape) with a request context carrying trace_id + userId + tenant/orgId, a trace_id propagated FE→BE→logs→Sentry→PostHog, Cloudflare Workers observability enabled, and Sentry + PostHog wired. Two modes: `setup` (wire it into an app) and `audit` (check an existing app + report gaps). Use when scaffolding a new app, wh
development
Manage credentials INSIDE the active ~/.claude/.env file — read which token/account to use for a given app (Simplicity vs Dataforce vs Ronan-personal), add or update a secret WITHOUT it passing through the chat (an interactive Terminal window prompts for it), and track secrets that were exposed in a transcript so they get rotated. Sibling to /ro:context (which switches WHICH env file is active). Use when the user wants to add an API key/token/secret, asks "which credential do I use for X", needs the env organized/labelled, or a secret was pasted into the chat and should be rotated.