diff --git a/components/Snippet.jsx b/components/Snippet.jsx index 85683de..f0bab92 100644 --- a/components/Snippet.jsx +++ b/components/Snippet.jsx @@ -1,14 +1,17 @@ +import javascript from "highlight.js/lib/languages/javascript"; import { useState, useMemo } from "react"; import hljs from "highlight.js/lib/core"; -import javascript from "highlight.js/lib/languages/javascript"; hljs.registerLanguage("javascript", javascript); -export function Snippet({ code }) { +export function Snippet({ code, output }) { const [copied, setCopied] = useState(false); const [hovered, setHovered] = useState(false); - const highlighted = useMemo(() => hljs.highlight(code, { language: "javascript" }).value, [code]); + const highlighted = useMemo( + () => hljs.highlight(code, { language: "javascript" }).value, + [code], + ); async function handleCopy() { try { @@ -27,58 +30,72 @@ export function Snippet({ code }) { } return ( -
+ {/* Code block */}
+ setHovered(true)}
+ onMouseLeave={() => setHovered(false)}
+ className="nx-relative"
>
-
-
-
-
+
+
+
+
+
+
+ {output && (
+
+
+ Expected Output
+
+
+ {output}
+
+
+ )}
);
}
diff --git a/package-lock.json b/package-lock.json
index e8d41dc..8e15799 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
},
"devDependencies": {
"eslint": "^10.0.2",
+ "playwright": "^1.59.1",
"terser": "^5.36.0",
"vercel": "^32.4.1"
}
@@ -14067,6 +14068,53 @@
"node": ">=4"
}
},
+ "node_modules/playwright": {
+ "version": "1.59.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz",
+ "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.59.1"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.59.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz",
+ "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
diff --git a/package.json b/package.json
index aecf70f..f28f900 100644
--- a/package.json
+++ b/package.json
@@ -7,9 +7,11 @@
"dev": "next dev",
"build": "next build",
"postbuild": "next-sitemap",
- "prebuild": "rm -rf .next && node scripts/generate-llms.js",
+ "prebuild": "rm -rf .next && node scripts/generate-llms.js && node scripts/capture-outputs.js && node scripts/inject-outputs.js",
"check:consistency": "node scripts/check-consistency.js",
"generate-skills": "node scripts/generate-skills.js",
+ "inject-outputs": "node scripts/inject-outputs.js",
+ "capture-outputs": "node scripts/capture-outputs.js",
"generate-skills:check": "node scripts/generate-skills.js && git diff --exit-code -- skills dist",
"install-skills": "node scripts/install-skills.js",
"install-global": "node scripts/install-global.js",
@@ -38,6 +40,7 @@
},
"devDependencies": {
"eslint": "^10.0.2",
+ "playwright": "^1.59.1",
"terser": "^5.36.0",
"vercel": "^32.4.1"
},
diff --git a/pages/CoreWebVitals/CLS.mdx b/pages/CoreWebVitals/CLS.mdx
index 8258978..d3c44ab 100644
--- a/pages/CoreWebVitals/CLS.mdx
+++ b/pages/CoreWebVitals/CLS.mdx
@@ -23,7 +23,7 @@ Unexpected layout shifts are frustrating and can cause users to click the wrong
### Snippet
-
+
### Understanding CLS
diff --git a/pages/CoreWebVitals/INP.mdx b/pages/CoreWebVitals/INP.mdx
index 7c99af7..a2268f3 100644
--- a/pages/CoreWebVitals/INP.mdx
+++ b/pages/CoreWebVitals/INP.mdx
@@ -58,7 +58,10 @@ flowchart TD
### Snippet
-
+ 16ms will be tracked.
+Call getINP() to see current INP value.
+Call getINPDetails() for full interaction list.`} />
### Understanding INP
diff --git a/pages/CoreWebVitals/LCP-Image-Entropy.mdx b/pages/CoreWebVitals/LCP-Image-Entropy.mdx
index 4ff3d76..1f7540a 100644
--- a/pages/CoreWebVitals/LCP-Image-Entropy.mdx
+++ b/pages/CoreWebVitals/LCP-Image-Entropy.mdx
@@ -27,7 +27,11 @@ BPP = (file size in bits) / (width ร height)
### Snippet
-
+
### Understanding the Results
diff --git a/pages/CoreWebVitals/LCP-Subparts.mdx b/pages/CoreWebVitals/LCP-Subparts.mdx
index d54534d..64af282 100644
--- a/pages/CoreWebVitals/LCP-Subparts.mdx
+++ b/pages/CoreWebVitals/LCP-Subparts.mdx
@@ -48,7 +48,8 @@ flowchart LR
### Snippet
-
+
### Understanding the Results
diff --git a/pages/CoreWebVitals/LCP-Trail.mdx b/pages/CoreWebVitals/LCP-Trail.mdx
index 0e03fd2..ca660ab 100644
--- a/pages/CoreWebVitals/LCP-Trail.mdx
+++ b/pages/CoreWebVitals/LCP-Trail.mdx
@@ -13,7 +13,9 @@ Each time the browser promotes a larger element as the new LCP, the snippet assi
### Snippet
-
+
### How It Works
diff --git a/pages/CoreWebVitals/LCP-Video-Candidate.mdx b/pages/CoreWebVitals/LCP-Video-Candidate.mdx
index a4bec5b..71fd103 100644
--- a/pages/CoreWebVitals/LCP-Video-Candidate.mdx
+++ b/pages/CoreWebVitals/LCP-Video-Candidate.mdx
@@ -51,7 +51,8 @@ A `` in `` shortcuts this chain, allowing the browser
### Snippet
-
+
### Understanding the Results
diff --git a/pages/CoreWebVitals/LCP.mdx b/pages/CoreWebVitals/LCP.mdx
index e7fb823..14b375e 100644
--- a/pages/CoreWebVitals/LCP.mdx
+++ b/pages/CoreWebVitals/LCP.mdx
@@ -17,7 +17,8 @@ Quick check for [Largest Contentful Paint](https://web.dev/articles/lcp), a Core
### Snippet
-
+
### Understanding LCP
diff --git a/pages/DevTools-Overrides/Fetch-XHR-Timeline.mdx b/pages/DevTools-Overrides/Fetch-XHR-Timeline.mdx
index 2503399..7585d4d 100644
--- a/pages/DevTools-Overrides/Fetch-XHR-Timeline.mdx
+++ b/pages/DevTools-Overrides/Fetch-XHR-Timeline.mdx
@@ -25,7 +25,7 @@ Console snippets can only see requests that have already completed and are visib
Add this inside a `
+For independent scripts (analytics, ads):
+
+For ES
+
+For critical inline
+
+console.groupEnd
+console.groupEnd`} />
### Understanding the Results
diff --git a/pages/Loading/Service-Worker-Analysis.mdx b/pages/Loading/Service-Worker-Analysis.mdx
index 8b6a57a..d98731f 100644
--- a/pages/Loading/Service-Worker-Analysis.mdx
+++ b/pages/Loading/Service-Worker-Analysis.mdx
@@ -67,7 +67,7 @@ sequenceDiagram
### Snippet
-
+
## Interpreting the Results
diff --git a/pages/Loading/TTFB.mdx b/pages/Loading/TTFB.mdx
index a7d836b..6dea505 100644
--- a/pages/Loading/TTFB.mdx
+++ b/pages/Loading/TTFB.mdx
@@ -26,7 +26,7 @@ Time to First Byte (TTFB) measures the time from when the user starts navigating
### Snippet
-
+
## Measure TTFB sub-parts
@@ -66,7 +66,10 @@ sequenceDiagram
### Snippet
-
+
## Measure TTFB for all resources
@@ -76,7 +79,7 @@ Analyzes TTFB for every resource loaded on the page (scripts, stylesheets, image
### Snippet
-
+
## Browser Support
diff --git a/pages/Loading/Validate-Preload-Async-Defer-Scripts.mdx b/pages/Loading/Validate-Preload-Async-Defer-Scripts.mdx
index 49aba70..9292bca 100644
--- a/pages/Loading/Validate-Preload-Async-Defer-Scripts.mdx
+++ b/pages/Loading/Validate-Preload-Async-Defer-Scripts.mdx
@@ -64,7 +64,8 @@ With preload on async script:
### Snippet
-
+
### Understanding the Results
diff --git a/pages/Media/Image-Element-Audit.mdx b/pages/Media/Image-Element-Audit.mdx
index db8edd2..2ac395f 100644
--- a/pages/Media/Image-Element-Audit.mdx
+++ b/pages/Media/Image-Element-Audit.mdx
@@ -70,7 +70,7 @@ For maximum format coverage, wrap images in a `` element:
### Snippet
-
+ elements found on this page.`} />
### Understanding the Results
diff --git a/pages/Media/SVG-Embedded-Bitmap-Analysis.mdx b/pages/Media/SVG-Embedded-Bitmap-Analysis.mdx
index 3966de7..54fa0c4 100644
--- a/pages/Media/SVG-Embedded-Bitmap-Analysis.mdx
+++ b/pages/Media/SVG-Embedded-Bitmap-Analysis.mdx
@@ -37,7 +37,7 @@ The correct pattern is to reference bitmap assets as separate files:
### Snippet
-
+
### Understanding the Results
diff --git a/pages/Media/Video-Element-Audit.mdx b/pages/Media/Video-Element-Audit.mdx
index df4ed68..2f5abcb 100644
--- a/pages/Media/Video-Element-Audit.mdx
+++ b/pages/Media/Video-Element-Audit.mdx
@@ -58,7 +58,7 @@ Every video on a page falls into one of three roles, each with its own optimal c
### Snippet
-
+ elements found on this page.`} />
### Understanding the Results
diff --git a/pages/Resources/Network-Bandwidth-Connection-Quality.mdx b/pages/Resources/Network-Bandwidth-Connection-Quality.mdx
index 77c459e..37f2ecc 100644
--- a/pages/Resources/Network-Bandwidth-Connection-Quality.mdx
+++ b/pages/Resources/Network-Bandwidth-Connection-Quality.mdx
@@ -23,7 +23,11 @@ Network quality directly affects web performance. Segmenting metrics by connecti
### Snippet
-
+
### Understanding the Results
diff --git a/scripts/capture-outputs.js b/scripts/capture-outputs.js
new file mode 100644
index 0000000..ca5ba67
--- /dev/null
+++ b/scripts/capture-outputs.js
@@ -0,0 +1,132 @@
+#!/usr/bin/env node
+// Runs each snippet in a headless browser and captures console output.
+// Writes results to snippets/outputs.json
+
+const { chromium } = require("playwright");
+const fs = require("fs");
+const path = require("path");
+
+const ROOT = path.join(__dirname, "..");
+const SNIPPETS_DIR = path.join(ROOT, "snippets");
+const OUTPUT_FILE = path.join(SNIPPETS_DIR, "outputs.json");
+
+// Collect all .js files recursively from snippets/
+function getSnippetFiles(dir) {
+ const files = [];
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
+ if (entry.isDirectory()) {
+ files.push(...getSnippetFiles(path.join(dir, entry.name)));
+ } else if (entry.name.endsWith(".js")) {
+ files.push(path.join(dir, entry.name));
+ }
+ }
+ return files;
+}
+
+// Convert absolute path to a relative key like "CoreWebVitals/LCP"
+function fileToKey(filePath) {
+ const rel = path.relative(SNIPPETS_DIR, filePath);
+ return rel.replace(/\.js$/, "");
+}
+
+async function captureOutput(browser, code) {
+ const context = await browser.newContext();
+ const page = await context.newPage();
+ const logs = [];
+
+ // Capture all console messages
+ page.on("console", (msg) => {
+ const type = msg.type(); // log, warn, error, info, etc.
+ const text = msg.text();
+ logs.push({ type, text });
+ });
+
+ // Navigate to a blank page (snippets use browser APIs like performance)
+ await page.goto("about:blank");
+
+ try {
+ // Execute the snippet code in the page context
+ await page.evaluate(code);
+ // Give async snippets time to finish
+ await page.waitForTimeout(200);
+ } catch (err) {
+ logs.push({ type: "error", text: `Execution error: ${err.message}` });
+ }
+
+ await context.close();
+ return logs;
+}
+
+// Remove %c directives and their associated CSS style arguments
+// e.g. "%cLCP Active font-weight: bold" โ "LCP Active"
+function cleanConsoleText(text) {
+ // Split on CSS style args that follow %c (they look like CSS property strings)
+ // Strategy: remove %c, then remove the CSS strings that follow as separate tokens
+ let result = text;
+
+ // Remove %c placeholders
+ result = result.replace(/%c/g, "");
+
+ // Remove CSS style strings โ they appear as standalone segments containing
+ // CSS properties like "font-weight: bold; font-size: 14px;"
+ result = result
+ .split("\n")
+ .map((line) =>
+ // A line is a CSS style arg if it matches "prop: value;" pattern and
+ // has no normal words/sentences (no spaces before the first colon)
+ /^[\w-]+\s*:/.test(line.trim()) && !/^(https?|file):/.test(line.trim())
+ ? null
+ : line,
+ )
+ .filter((line) => line !== null)
+ .join("\n");
+
+ // Also remove inline CSS blobs that ended up on same line after %c removal
+ // e.g. "LCP Active font-weight: bold; font-size: 14px;"
+ result = result.replace(/\s+([\w-]+\s*:[^;]+;(\s*[\w-]+\s*:[^;]+;)*)/g, "");
+
+ return result.trim();
+}
+
+function formatLogs(logs) {
+ return logs
+ .filter((l) => l.text && l.text.trim() !== "")
+ .map((l) => cleanConsoleText(l.text))
+ .filter((t) => t !== "")
+ .join("\n");
+}
+
+async function main() {
+ const snippetFiles = getSnippetFiles(SNIPPETS_DIR);
+ console.log(`Found ${snippetFiles.length} snippets\n`);
+
+ const browser = await chromium.launch();
+ const results = {};
+
+ for (const file of snippetFiles) {
+ const key = fileToKey(file);
+ const code = fs.readFileSync(file, "utf-8");
+
+ process.stdout.write(` Running: ${key} ... `);
+
+ try {
+ const logs = await captureOutput(browser, code);
+ const output = formatLogs(logs);
+ results[key] = { output: output || "(no output)", error: null };
+ console.log("โ");
+ } catch (err) {
+ results[key] = { output: null, error: err.message };
+ console.log(`โ ${err.message}`);
+ }
+ }
+
+ await browser.close();
+
+ fs.writeFileSync(OUTPUT_FILE, JSON.stringify(results, null, 2));
+ console.log(`\nOutputs saved to snippets/outputs.json`);
+}
+
+main().catch((err) => {
+ console.error(err);
+ process.exit(1);
+});
diff --git a/scripts/inject-outputs.js b/scripts/inject-outputs.js
new file mode 100644
index 0000000..6f5b8f6
--- /dev/null
+++ b/scripts/inject-outputs.js
@@ -0,0 +1,105 @@
+const fs = require("fs");
+const path = require("path");
+
+const ROOT = path.join(__dirname, "..");
+const PAGES_DIR = path.join(ROOT, "pages");
+const SNIPPETS_DIR = path.join(ROOT, "snippets");
+const OUTPUT_FILE = path.join(SNIPPETS_DIR, "outputs.json");
+
+if (!fs.existsSync(OUTPUT_FILE)) {
+ console.error(
+ "snippets/outputs.json not found. Run capture-outputs.js first.",
+ );
+ process.exit(1);
+}
+
+const outputs = JSON.parse(fs.readFileSync(OUTPUT_FILE, "utf-8"));
+
+function getMdxFiles(dir) {
+ const files = [];
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
+ if (entry.isDirectory()) {
+ files.push(...getMdxFiles(path.join(dir, entry.name)));
+ } else if (entry.name.endsWith(".mdx")) {
+ files.push(path.join(dir, entry.name));
+ }
+ }
+ return files;
+}
+
+function extractKeyFromImport(importLine) {
+ const match = importLine.match(/snippets\/(.+?)\.js\?raw/);
+ return match ? match[1] : null;
+}
+
+function getSnippetImports(content) {
+ const map = {};
+ const lines = content.split("\n");
+ for (const line of lines) {
+ if (!line.includes("snippets/") || !line.includes("?raw")) continue;
+ const varMatch = line.match(/import\s+(\w+)\s+from/);
+ const key = extractKeyFromImport(line);
+ if (varMatch && key) {
+ map[varMatch[1]] = key;
+ }
+ }
+ return map;
+}
+
+function processFile(mdxPath) {
+ let content = fs.readFileSync(mdxPath, "utf-8");
+ const rel = path.relative(ROOT, mdxPath);
+
+ const snippetImports = getSnippetImports(content);
+ if (Object.keys(snippetImports).length === 0) return false;
+
+ let changed = false;
+
+ for (const [varName, outputKey] of Object.entries(snippetImports)) {
+ const outputData = outputs[outputKey];
+ if (!outputData || !outputData.output) continue;
+
+ const outputText = outputData.output;
+
+ const withoutOutput = new RegExp(
+ ` `,
+ "g",
+ );
+ const withOutput = new RegExp(
+ ` `,
+ "g",
+ );
+
+ const escaped = outputText
+ .replace(/\\/g, "\\\\")
+ .replace(/`/g, "\\`")
+ .replace(/\$/g, "\\$");
+
+ const replacement = ` `;
+
+ if (withoutOutput.test(content)) {
+ content = content.replace(withoutOutput, replacement);
+ changed = true;
+ } else if (withOutput.test(content)) {
+ content = content.replace(withOutput, replacement);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ fs.writeFileSync(mdxPath, content);
+ console.log(` updated: ${rel}`);
+ }
+
+ return changed;
+}
+
+const mdxFiles = getMdxFiles(PAGES_DIR);
+console.log(`Processing ${mdxFiles.length} MDX files...\n`);
+
+let updatedCount = 0;
+for (const file of mdxFiles) {
+ if (processFile(file)) updatedCount++;
+}
+
+console.log(`\nDone. Updated ${updatedCount} files.`);
diff --git a/snippets/outputs.json b/snippets/outputs.json
new file mode 100644
index 0000000..26a8f4e
--- /dev/null
+++ b/snippets/outputs.json
@@ -0,0 +1,206 @@
+{
+ "CoreWebVitals/CLS": {
+ "output": "Call getCLS() anytime to check current value.",
+ "error": null
+ },
+ "CoreWebVitals/INP": {
+ "output": "โก INP Tracking Active\nInteractions with duration > 16ms will be tracked.\nCall getINP() to see current INP value.\nCall getINPDetails() for full interaction list.",
+ "error": null
+ },
+ "CoreWebVitals/LCP-Image-Entropy": {
+ "output": "Deprecated API for given entry type.\n๐ผ๏ธ Image Entropy Analysis\nNo images with measurable entropy found.\n(Data URLs and cross-origin images without CORS are excluded)\nconsole.groupEnd",
+ "error": null
+ },
+ "CoreWebVitals/LCP-Subparts": {
+ "output": "๐ LCP Subparts Analysis Active\nWaiting for LCP...",
+ "error": null
+ },
+ "CoreWebVitals/LCP-Trail": {
+ "output": "โฑ๏ธ LCP Trail Active\nHighlights all LCP candidate elements with distinct colors.\nDeprecated API for given entry type.",
+ "error": null
+ },
+ "CoreWebVitals/LCP-Video-Candidate": {
+ "output": "Deprecated API for given entry type.\nโ ๏ธ No LCP entries found. Run this snippet before interacting with the page, or reload and run it immediately.",
+ "error": null
+ },
+ "CoreWebVitals/LCP": {
+ "output": "โฑ๏ธ LCP Tracking Active\nLCP may update as larger elements load.",
+ "error": null
+ },
+ "DevTools-Overrides/Fetch-XHR-Timeline-inject": {
+ "output": "(no output)",
+ "error": null
+ },
+ "DevTools-Overrides/Fetch-XHR-Timeline-read": {
+ "output": "No data found. Make sure the inject snippet is active via DevTools Overrides and reload the page.",
+ "error": null
+ },
+ "Interaction/Forced-Synchronous-Layout": {
+ "output": "โก FSL Detector Active\nMonitoring class/style mutations and geometric property access.\nCall getFSLSummary() for the report or stopFSLDetector() to stop.",
+ "error": null
+ },
+ "Interaction/Input-Latency-Breakdown": {
+ "output": "โจ๏ธ Input Latency Breakdown Active\nInteract with the page (click, type, etc.).\nCall getInputLatencyBreakdown() for the aggregated report.",
+ "error": null
+ },
+ "Interaction/Interactions": {
+ "output": "๐ Interaction Tracking Active\nInteract with the page to see interaction details.\nCall getInteractionSummary() for a summary.",
+ "error": null
+ },
+ "Interaction/Layout-Shift-Loading-and-Interaction": {
+ "output": "๐ Layout Shift Tracking Active\nCurrent CLS: ๐ข 0.0000\nInteract with the page to see new shifts.\nCall getLayoutShiftSummary() for full analysis.\nDeprecated API for given entry type.\nDeprecated API for given entry type.\nDeprecated API for given entry type.",
+ "error": null
+ },
+ "Interaction/Long-Animation-Frames-Helpers": {
+ "output": "๐ง LoAF Helpers Loaded\nObserving long animation frames (>50ms)...\nQuick\nAll",
+ "error": null
+ },
+ "Interaction/Long-Animation-Frames-Script-Attribution": {
+ "output": "โ
No long frames detected",
+ "error": null
+ },
+ "Interaction/Long-Animation-Frames": {
+ "output": "๐ฌ Long Animation Frames Tracking Active\nFrames with blocking duration will be logged.\nCall getLoAFSummary() for full analysis.",
+ "error": null
+ },
+ "Interaction/LongTask": {
+ "output": "โฑ๏ธ Long Tasks Tracking Active\nTasks blocking the main thread for >50ms will be logged.\nCall getLongTaskSummary() for statistics.\nDeprecated API for given entry type.",
+ "error": null
+ },
+ "Interaction/Scroll-Performance": {
+ "output": "๐ Scroll Performance Analysis Active\nScroll to measure FPS. Non-passive listener registrations will be warned.\nCall getScrollSummary() for the full report.",
+ "error": null
+ },
+ "Loading/Back-Forward-Cache": {
+ "output": "๐ bfcache Analysis Running...\nResults will appear shortly.\nCall checkBfcache() anytime to re-run analysis.\n๐ก bfcache\n๐\nโน๏ธ This page was NOT restored from bfcache\n(Either first visit or bfcache was blocked on previous navigation)\n๐ Navigation\n๐ Potential\n[Object, Object]\n๐ก\n1. Close WebSocket connections before page hide.\n๐งช How to\n1. Run this snippet (you already did this โ)\n2. Navigate to another page\n3. Click browser Back button\n4. Check console for restoration message\nOr use Chrome DevTools โ Application โ Back/forward cache\nconsole.groupEnd\nโน๏ธ For detailed reasons, use Chrome 123+ and navigate back to this page.",
+ "error": null
+ },
+ "Loading/CSS-Media-Queries-Analysis": {
+ "output": "๐ CSS Media Queries Analysis (min-width > 768px)\nTotal @media rules found: 0\nTotal classes: 0\nTotal properties: 0\nconsole.groupEnd\n๐พ POTENTIAL MOBILE SAVINGS\nEstimated CSS bytes that mobile doesn't\nโโ From inline CSS: 0 Bytes\nโโ From external files: 0 Bytes\n๐ก By splitting these styles into separate files with media queries,\nmobile users won't need to download, parse, or process this CSS.\nconsole.groupEnd\n๐ท INLINE CSS (