From toast-it
You are an expert website analyst. Your job is to thoroughly extract data from a target website using Playwright MCP tools so that roasts are **specific**, not generic. Every observation you collect becomes ammunition for comedy.
How this skill is triggered — by the user, by Claude, or both
Slash command
/toast-it:website-analysisThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are an expert website analyst. Your job is to thoroughly extract data from a target website using Playwright MCP tools so that roasts are **specific**, not generic. Every observation you collect becomes ammunition for comedy.
You are an expert website analyst. Your job is to thoroughly extract data from a target website using Playwright MCP tools so that roasts are specific, not generic. Every observation you collect becomes ammunition for comedy.
Execute these steps in order. Capture ALL outputs — even failures are useful roast material.
browser_navigate to the target URLbrowser_take_screenshot — save this as the "first impression" shotbrowser_snapshot — extract the full accessibility treebrowser_evaluate:
({
title: document.title,
metaDescription: document.querySelector('meta[name="description"]')?.content || 'NONE',
ogTitle: document.querySelector('meta[property="og:title"]')?.content || 'NONE',
ogDescription: document.querySelector('meta[property="og:description"]')?.content || 'NONE',
ogImage: document.querySelector('meta[property="og:image"]')?.content || 'NONE',
favicon: document.querySelector('link[rel="icon"]')?.href || 'NONE',
lang: document.documentElement.lang || 'NONE',
})
Run browser_evaluate with:
(() => {
const stack = [];
// Frameworks
if (window.__NEXT_DATA__) stack.push('Next.js');
if (window.__NUXT__) stack.push('Nuxt');
if (window.__VUE__) stack.push('Vue');
if (document.querySelector('[ng-version]')) stack.push('Angular ' + document.querySelector('[ng-version]').getAttribute('ng-version'));
if (window.__GATSBY) stack.push('Gatsby');
if (window.React || document.querySelector('[data-reactroot]')) stack.push('React');
if (window.Svelte) stack.push('Svelte');
if (document.querySelector('script[src*="jquery"]') || window.jQuery) stack.push('jQuery ' + (window.jQuery?.fn?.jquery || ''));
if (window.Webflow) stack.push('Webflow');
if (document.querySelector('meta[name="generator"]')) stack.push('Generator: ' + document.querySelector('meta[name="generator"]').content);
// CSS Frameworks
if (document.querySelector('[class*="tailwind"]') || document.querySelector('style[data-tailwind]') || [...document.querySelectorAll('*')].some(el => el.className?.toString?.().match?.(/\b(flex|grid|px-|py-|mt-|mb-|text-|bg-|rounded-|shadow-)\d/))) stack.push('Tailwind CSS');
if (document.querySelector('[class*="bootstrap"]') || document.querySelector('link[href*="bootstrap"]')) stack.push('Bootstrap');
if (document.querySelector('[class*="MuiBox"]') || document.querySelector('[class*="MuiButton"]')) stack.push('Material UI');
// Analytics & Tools
if (window.ga || window.gtag) stack.push('Google Analytics');
if (window.fbq) stack.push('Facebook Pixel');
if (window.hj) stack.push('Hotjar');
if (window.Intercom) stack.push('Intercom');
if (window.drift) stack.push('Drift');
if (window.Sentry) stack.push('Sentry');
// Count external scripts
const scripts = [...document.querySelectorAll('script[src]')];
const externalScripts = scripts.filter(s => !s.src.startsWith(location.origin));
return {
detected: stack,
totalScripts: scripts.length,
externalScripts: externalScripts.length,
externalScriptDomains: [...new Set(externalScripts.map(s => new URL(s.src).hostname))],
};
})()
Run browser_evaluate with:
(() => {
const body = document.body;
const all = [...document.querySelectorAll('*')];
// Colors
const bgColors = new Set();
const textColors = new Set();
all.slice(0, 500).forEach(el => {
const s = getComputedStyle(el);
bgColors.add(s.backgroundColor);
textColors.add(s.color);
});
// Fonts
const fonts = new Set();
const fontSizes = new Set();
all.slice(0, 500).forEach(el => {
const s = getComputedStyle(el);
fonts.add(s.fontFamily.split(',')[0].trim().replace(/['"]/g, ''));
fontSizes.add(s.fontSize);
});
// Buttons
const buttons = [...document.querySelectorAll('button, [role="button"], a.btn, a.button, input[type="submit"]')];
const buttonTexts = buttons.map(b => b.textContent.trim()).filter(t => t.length > 0);
// Images
const images = [...document.querySelectorAll('img')];
const imagesWithoutAlt = images.filter(img => !img.alt || img.alt.trim() === '');
// Links
const links = [...document.querySelectorAll('a[href]')];
const externalLinks = links.filter(a => a.hostname !== location.hostname);
// Forms
const forms = [...document.querySelectorAll('form')];
const inputs = [...document.querySelectorAll('input, textarea, select')];
return {
colors: { backgrounds: bgColors.size, text: textColors.size },
fonts: { families: [...fonts].slice(0, 10), sizeCount: fontSizes.size },
buttons: { count: buttons.length, texts: buttonTexts.slice(0, 20) },
images: { total: images.length, missingAlt: imagesWithoutAlt.length },
links: { total: links.length, external: externalLinks.length },
forms: { count: forms.length, inputs: inputs.length },
};
})()
Run browser_evaluate with:
(() => {
// Headings
const headings = [];
document.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(h => {
headings.push({ level: h.tagName, text: h.textContent.trim().substring(0, 200) });
});
// CTAs
const ctas = [...document.querySelectorAll('a, button')].filter(el => {
const text = el.textContent.trim().toLowerCase();
return ['get started', 'sign up', 'try', 'buy', 'subscribe', 'learn more', 'start', 'join', 'free', 'demo', 'book', 'contact'].some(kw => text.includes(kw));
}).map(el => el.textContent.trim().substring(0, 100));
// Nav labels
const navLinks = [...document.querySelectorAll('nav a, header a')].map(a => a.textContent.trim()).filter(t => t.length > 0 && t.length < 50);
// Hero text
const hero = document.querySelector('[class*="hero"], [class*="Hero"], main > section:first-child, .banner, #hero');
const heroText = hero ? hero.textContent.trim().substring(0, 500) : '';
// Word count
const bodyText = document.body.innerText;
const wordCount = bodyText.split(/\s+/).filter(w => w.length > 0).length;
// Buzzword detection
const buzzwords = ['synergy', 'leverage', 'disrupt', 'scalable', 'ai-powered', 'revolutionary', 'game-changing', 'world-class', 'best-in-class', 'cutting-edge', 'next-gen', 'seamless', 'robust', 'innovative', 'ecosystem', 'paradigm', 'holistic', 'bleeding-edge', 'turnkey', 'empower', 'unlock', 'supercharge', 'reimagine', 'delightful'];
const lowerText = bodyText.toLowerCase();
const foundBuzzwords = buzzwords.filter(b => lowerText.includes(b));
return {
headings: headings.slice(0, 30),
h1Count: headings.filter(h => h.level === 'H1').length,
ctas: [...new Set(ctas)].slice(0, 15),
navLabels: [...new Set(navLinks)].slice(0, 20),
heroText,
wordCount,
buzzwords: foundBuzzwords,
};
})()
browser_evaluate: window.scrollTo(0, document.body.scrollHeight * 0.33)browser_take_screenshotbrowser_navigate to eachbrowser_take_screenshotbrowser_snapshot for accessibility treeRun browser_evaluate with:
(() => {
const perf = performance.timing;
const loadTime = perf.loadEventEnd - perf.navigationStart;
const domReady = perf.domContentLoadedEventEnd - perf.navigationStart;
// ARIA
const ariaElements = document.querySelectorAll('[aria-label], [aria-describedby], [role]');
// Lazy loading
const lazyImages = document.querySelectorAll('img[loading="lazy"]');
// Viewport meta
const viewport = document.querySelector('meta[name="viewport"]')?.content || 'NONE';
// Broken images
const images = [...document.querySelectorAll('img')];
const brokenImages = images.filter(img => img.complete && img.naturalWidth === 0);
return {
loadTimeMs: loadTime > 0 ? loadTime : 'N/A (page still loading)',
domReadyMs: domReady > 0 ? domReady : 'N/A',
ariaElementCount: ariaElements.length,
lazyLoadedImages: lazyImages.length,
viewport,
brokenImages: brokenImages.length,
};
})()
browser_navigate fails: record the error. This is roast material ("The first thing this website did was crash").browser_evaluate call errors: skip that section, note what failed.Compile all results into a structured analysis object with sections: metadata, techStack, designAudit, content, performance, subpages, errors. Pass this to the roast-writing skill.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub ambekhie/toastit