diff --git a/astro.config.mjs b/astro.config.mjs index cc7569a7..150e39de 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -2,6 +2,7 @@ import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; import starlightLinksValidator from 'starlight-links-validator'; import starlightLlmsTxt from 'starlight-llms-txt'; +import starlightMdTxt from 'starlight-md-txt'; const sourceMaps = process.env.SOURCE_MAPS === 'true'; @@ -43,6 +44,7 @@ export default defineConfig({ { label: 'Minimizing query costs', link: 'docs/guides/minimizing-costs' }, { label: 'Guided tour', link: 'docs/guides/guided-tour' }, { label: 'Release cycle', link: 'docs/guides/release-cycle' }, + { label: 'AI agents', link: 'docs/guides/ai-agents' }, ], }, { @@ -71,6 +73,7 @@ export default defineConfig({ }, plugins: [ starlightLlmsTxt(), + starlightMdTxt({ absoluteLinks: true }), starlightLinksValidator({ exclude: ['/', '/about/**', '/faq/**', '/reports/**'], // Pages outside starlight }), diff --git a/package-lock.json b/package-lock.json index 137ad04e..6f528c5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "run-script-os": "1.1.6", "starlight-links-validator": "^0.26.0", "starlight-llms-txt": "^0.12.0", + "starlight-md-txt": "^0.2.0", "web-vitals": "6.2.2", "xml-js": "1.6.11", "zod": "^4.6.5" @@ -4162,6 +4163,29 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", + "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -6841,6 +6865,32 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -10554,6 +10604,43 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-mdx-jsx": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", @@ -10579,6 +10666,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-phrasing": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", @@ -10912,6 +11018,113 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-factory-destination": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", @@ -10957,6 +11170,34 @@ "micromark-util-types": "^2.0.0" } }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, "node_modules/micromark-factory-space": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", @@ -11168,6 +11409,32 @@ ], "license": "MIT" }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", @@ -13061,6 +13328,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -13871,6 +14153,36 @@ "astro": "^7.0.0" } }, + "node_modules/starlight-md-txt": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/starlight-md-txt/-/starlight-md-txt-0.2.0.tgz", + "integrity": "sha512-uzZai1PJJoDLkuFTe2D2dKR5O839skOxHU+kbVwRhJsZgwHy/Xen5rsRi4uTvp6ssC2E4PVxWoDp2r/D/cA7rw==", + "dev": true, + "license": "MIT", + "workspaces": [ + ".", + "docs" + ], + "dependencies": { + "mdast-util-gfm-table": "^2.0.0", + "micromark-extension-gfm-table": "^2.1.2", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0" + }, + "peerDependencies": { + "@astrojs/mdx": ">=3.0.0", + "@astrojs/starlight": ">=0.30.0", + "astro": ">=4.0.0 || >=5.0.0 || >=6.0.0 || >=7.0.0" + }, + "peerDependenciesMeta": { + "@astrojs/mdx": { + "optional": true + } + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -14756,6 +15068,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-remove": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz", diff --git a/package.json b/package.json index b89640df..6bbf84ec 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "run-script-os": "1.1.6", "starlight-links-validator": "^0.26.0", "starlight-llms-txt": "^0.12.0", + "starlight-md-txt": "^0.2.0", "web-vitals": "6.2.2", "xml-js": "1.6.11", "zod": "^4.6.5" diff --git a/src/content/docs/docs/guides/ai-agents.mdx b/src/content/docs/docs/guides/ai-agents.mdx new file mode 100644 index 00000000..fe67c9e6 --- /dev/null +++ b/src/content/docs/docs/guides/ai-agents.mdx @@ -0,0 +1,94 @@ +--- +title: AI agents +description: Use HTTP Archive data from Claude Code, Codex, and other AI agents with the HTTP Archive agent plugin and MCP server +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +The [HTTP Archive agent plugin](https://github.com/HTTPArchive/httparchive-plugin) lets AI coding agents such as Claude Code and Codex answer questions about how the web is built. It gives an agent two ways to reach HTTP Archive data: + +- **Tech Report tools** for technology adoption, Core Web Vitals, Lighthouse and page weight trends. These come from the [Tech Report](/reports/techreport/landing) through a remote MCP server and need no Google Cloud account. +- **BigQuery skills** for anything else. They teach the agent to inspect live table schemas, read these docs, preview rows for free, and write partition- and cluster-pruned SQL against the [public dataset](/docs/guides/getting-started/). + +## Install the plugin + + + + ```bash + claude plugin marketplace add httparchive/httparchive-plugin + claude plugin install httparchive@httparchive + ``` + + Or, inside a session, run `/plugin marketplace add httparchive/httparchive-plugin`, then `/plugin install httparchive@httparchive`. + + + ```bash + codex plugin marketplace add httparchive/httparchive-plugin + codex plugin add httparchive@httparchive + ``` + + + Copy the folders under [`skills/`](https://github.com/HTTPArchive/httparchive-plugin/tree/main/skills) into your agent's skills directory, for example `~/.agents/skills/`, and add the MCP server below. + + + +The plugin connects the Tech Report MCP server automatically. To use the server on its own, without the skills, add it to any MCP client that supports Streamable HTTP: + + + + ```bash + claude mcp add --transport http httparchive https://cdn.httparchive.org/mcp + ``` + + + ```bash + codex mcp add httparchive --url https://cdn.httparchive.org/mcp + ``` + + + Add a remote MCP server with the URL `https://cdn.httparchive.org/mcp`. It needs no authentication. + + + +## What's included + +### Skills + +| Skill | Use | +|---|---| +| `httparchive-docs-and-metrics` | Looks up these docs and discovers which `custom_metrics` keys exist in `crawl.pages` | +| `httparchive-query-optimizer` | Inspects schemas, previews rows with `bq head`, dry-runs queries, and applies the rules in [Minimizing query costs](/docs/guides/minimizing-costs/) | + +### Tech Report tools + +| Tool | Returns | +|---|---| +| `search_technologies`, `list_categories`, `list_versions` | Technologies, categories and versions tracked by the Tech Report | +| `list_ranks`, `list_geos` | Rank segments and geographies available as filters | +| `get_adoption_metrics` | Share of sites using a technology over time | +| `get_cwv_metrics`, `get_cwv_distribution`, `get_geo_breakdown` | Core Web Vitals pass rates, histograms and per-country breakdowns | +| `get_lighthouse_metrics`, `get_audits_metrics` | Lighthouse category scores and audit results | +| `get_page_weight_metrics` | Page, JavaScript and CSS weight | + +## Requirements + +The Tech Report tools work out of the box. + +The BigQuery skills run the `bq` command-line tool, so install the [Google Cloud CLI](https://cloud.google.com/sdk/docs/install) and authenticate against a project with BigQuery enabled, as described in [Getting started](/docs/guides/getting-started/). Queries are billed to that project. The skills read these docs with the agent's built-in web fetch, so they need no other tools. + +Every docs page is also available as Markdown at its URL plus `.md`, for example [`/docs/guides/minimizing-costs.md`](/docs/guides/minimizing-costs.md), and the full docs are at [`/llms.txt`](/llms.txt). Point any agent at these to give it HTTP Archive context. + +:::danger +An agent can write queries that scan terabytes. The skills tell it to dry-run before every query and to prototype on `rank <= 1000` first, but review the estimated bytes before letting it run anything large. We **strongly** recommend setting a [custom query quota](https://cloud.google.com/bigquery/docs/custom-quotas) on the project. +::: + +## Example prompts + +- "How has React adoption changed over the last two years, and how do React sites compare on Core Web Vitals?" +- "Which countries have the best LCP pass rate for WordPress sites?" +- "Write a query that counts how many of the top 10,000 mobile pages load a third-party font, and check its cost first." +- "Which `custom_metrics` keys describe structured data on a page?" + +## Contribute + +The plugin is open source on [GitHub](https://github.com/HTTPArchive/httparchive-plugin). Report issues or suggest new skills there. diff --git a/src/content/docs/docs/index.mdx b/src/content/docs/docs/index.mdx index 4ce5bd8d..59ca28d8 100644 --- a/src/content/docs/docs/index.mdx +++ b/src/content/docs/docs/index.mdx @@ -38,6 +38,9 @@ import { Card, CardGrid } from '@astrojs/starlight/components'; Learn how millions of URLs are crawled each month, how pipelines process data, and when new datasets are published in the [Release Cycle guide](/docs/guides/release-cycle/). + + Let Claude Code, Codex explore HTTP Archive dataset with the [HTTP Archive agent plugin](/docs/guides/ai-agents/), or ask any MCP client about web technologies and Core Web Vitals. + ## Dataset Reference diff --git a/src/pages/index.astro b/src/pages/index.astro index 705fa9b7..4aa8ca81 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -148,6 +148,39 @@ const description = +
+
+
+ + +
+

+ AI Agents + Agents Plugin +

+ +

+ Ask your AI agent how the web is built. The HTTP Archive agent plugin + writes cost-safe BigQuery queries against the public dataset, and + answers technology adoption and Core Web Vitals questions straight + from the Tech Report. +

+ Set Up the Agent Plugin + View on GitHub +
+
+
+
+