{"_id":"@0xtlt/devlens","_rev":"9-daa982ad461d8e31eaa8784916d50726","name":"@0xtlt/devlens","dist-tags":{"latest":"0.2.7"},"versions":{"0.1.0":{"name":"@0xtlt/devlens","version":"0.1.0","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.1.0","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"ea0083379d16fdafdd1c83d585bfa35373bcb981","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.1.0.tgz","fileCount":18,"integrity":"sha512-o3vK9JGq3afswPXSgeq/NAMnZSKJgZzLTNAc7nLqmIIhiQaUdoV2bgmBYqpOQeEGU6nAhlKVisZusVtszbP+Rg==","signatures":[{"sig":"MEQCIEOHF0jDIb2JM4NedZKuWyXOD086oJEXRq3jmD8+fx2bAiB4/KvZXHvgYLaMxXOjp/JRALGBCUXKQtXCQ370+zuD2w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":80349},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"c40e209475794f278dc169eb441b521fad913e72","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.1.0_1776241012392_0.410886892342732","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@0xtlt/devlens","version":"0.2.0","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.2.0","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"d2b209c392f642143f316f5c7747797237327758","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.0.tgz","fileCount":18,"integrity":"sha512-PA/ow2688p0P3UVUXb8foozihrqWhpudyqVkfMdbWATkLict1bCvt23M8KXkUqSxzNyMdevsshWR6aXCsL+Iag==","signatures":[{"sig":"MEYCIQCFDmSS4G2iLVaII6XO94Ym12vX7qDAiYoLc43wsAel0gIhAJHxMKhZIp8bPyKPRJyU4Cqb9zZfQEhYAmJ+j23av1Fx","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81067},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"82b5bef05aebbe0e8ae4e8697d822009def905f4","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.2.0_1776241292025_0.12005615697227467","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@0xtlt/devlens","version":"0.2.1","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.2.1","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"2261915a89a4a06bd1975aa9426b2ca8881d1da8","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.1.tgz","fileCount":18,"integrity":"sha512-ntxAc3PBxeNQFVajQdID2Bq3eRwJLxJgReFZCkILuVvhxIyWqO+H6F44hozEO8SLaA6WH8MQzvu4Puodx5B7uA==","signatures":[{"sig":"MEYCIQDneIG2nI3zDcx6g0B36ndaOUzM5ct17B3UOT86Sq4/0wIhAIBY21SoxPcbsAgezeBIJzG24e1+seBh6RY/JgpntHfF","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":83168},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"3b31b24b6a95ca849e47423008cfea6fb9ca13c2","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.2.1_1776242622750_0.9789524810559296","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@0xtlt/devlens","version":"0.2.2","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.2.2","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"a046350735d676f1d7fc204642e6df23e4cc8174","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.2.tgz","fileCount":18,"integrity":"sha512-91isKgLHc4t5kWiwgqarpIsFRl0Si0FxCI6CBpPMuddNzfHRH0bSHisAp3hOtnjHBvOXCRe1SyTau86ATTdzpQ==","signatures":[{"sig":"MEYCIQDPjY1VUSZ42Emp1vlf90JLagNiIELqc8zhWJOzECLVwgIhANtnk9W5mumWJeQo8tXmSC+rQRuVyorM/jDfPtn6U7Is","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":83292},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"9c6cb9731353d790905df8bed34e650cee955224","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.2.2_1776243017773_0.08339813786326222","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@0xtlt/devlens","version":"0.2.3","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.2.3","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"e8ba1b1494d744e3290a9df841583acc25de0f7c","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.3.tgz","fileCount":18,"integrity":"sha512-FLIV6p9WUfZe6JgcTEpmKv0nspHWlV9pamizNCY1WDIrp/nL5VDp1FzqZLBycwYUTJtfdOTFQOxn0uKhXFw3oQ==","signatures":[{"sig":"MEYCIQCF/68V9+j+m65ZfXCYKFf+GA9IcYitn2EkxGe/QrCPkQIhAOJP35sAUkMPKuK4kEWB3ASQmEr5QrvUKjxS9m/ETbd5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":84497},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"00136a5548a97ec2b617d05b540ca72edd7710ce","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.2.3_1776244375160_0.10247636604593025","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"@0xtlt/devlens","version":"0.2.4","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.2.4","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"7900ba3e05b417c144ab8a5dd369dc8fce7b117e","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.4.tgz","fileCount":18,"integrity":"sha512-FYrvNs57RgE+liJqgXUPNMyKMfYezmLbbQowQbaVbV3Zp+TwrM0kbnyARDjfmRAwB+sLAmBp/puwC9oVlTcuIQ==","signatures":[{"sig":"MEUCIQDu2N7JaKw6simJ64/9vb9toEI2kEp3yoAT2oGA4VPbyQIgSTj+UjTsO83HNnqYN/hPlTnZf41rMt5r8uNBmUzWu7M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":85777},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"df7cfdbb5c29a9a6b6d419714c3a74ed782a21b9","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.2.4_1776245141784_0.612118517669012","host":"s3://npm-registry-packages-npm-production"}},"0.2.5":{"name":"@0xtlt/devlens","version":"0.2.5","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.2.5","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"4769ad885eee6be343e66ecf840fe729ed27749c","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.5.tgz","fileCount":18,"integrity":"sha512-Nmc5of25p+HISkDoq4uyEMfj+5G6wPjuZpj8wodWzRDLX06GkiO3/eobt6SCzjU98QyBaNsVR2bo4FuNO0HBJw==","signatures":[{"sig":"MEQCICfsVz14fK4N7+UxmCqiceAzyrs71Wr458iTsrgeV3GxAiB2QtGoQzpcF2VCHfrEj9SjH5ax8rSepslbzXukKREhXA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":85908},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"e69c6fdf594631519bb995d4bab1cf3655857dd5","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.2.5_1776246251850_0.6311926058156592","host":"s3://npm-registry-packages-npm-production"}},"0.2.6":{"name":"@0xtlt/devlens","version":"0.2.6","keywords":["devtools","frontend","debug","developer-tools"],"author":{"name":"Thomas Tastet"},"license":"MIT","_id":"@0xtlt/devlens@0.2.6","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"homepage":"https://github.com/0xtlt/devlens#readme","bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"dist":{"shasum":"1d3236e1e343eb6b3ca2978dd16c9c5f260add9d","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.6.tgz","fileCount":18,"integrity":"sha512-+1j3Eba+EwQmJGBjdTfilaeahPbSQlPYv2QgddaA3CIForT8Fjf6pJJUWFJxI74EAtJL/PVGTWo7TSFpkRTeew==","signatures":[{"sig":"MEUCIQCrnnpWzCDRhSIZUHHS9bQhXU4X+8FEszGHkg6pQllTJAIgOT2Jl0tQxocUY2iacmlngZAGu5cAKLVBqlWcaMbJ5Dc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86018},"type":"module","types":"./dist/src/index.d.ts","module":"./dist/devlens.mjs","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"gitHead":"3dd47c1f7da4c5ca8441018e738d8804519e85f8","scripts":{"dev":"vite","lint":"eslint .","build":"tsc && vite build","check":"tsc --noEmit"},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"repository":{"url":"git+https://github.com/0xtlt/devlens.git","type":"git"},"_npmVersion":"11.6.2","description":"Lightweight frontend devtools panel for any web app","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.4","eslint":"^10.2.0","globals":"^17.5.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^25.5.2","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.58.2"},"_npmOperationalInternal":{"tmp":"tmp/devlens_0.2.6_1776248526792_0.3856903242141876","host":"s3://npm-registry-packages-npm-production"}},"0.2.7":{"name":"@0xtlt/devlens","version":"0.2.7","type":"module","description":"Lightweight frontend devtools panel for any web app","author":{"name":"Thomas Tastet"},"repository":{"type":"git","url":"git+https://github.com/0xtlt/devlens.git"},"bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"homepage":"https://github.com/0xtlt/devlens#readme","module":"./dist/devlens.mjs","types":"./dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/devlens.mjs"}},"publishConfig":{"access":"public"},"scripts":{"dev":"vite","build":"tsc && vite build","check":"tsc --noEmit","lint":"eslint ."},"keywords":["devtools","frontend","debug","developer-tools"],"license":"MIT","devDependencies":{"@eslint/js":"^10.0.1","@types/node":"^25.5.2","eslint":"^10.2.0","globals":"^17.5.0","typescript":"~6.0.2","typescript-eslint":"^8.58.2","vite":"^8.0.4","vite-plugin-dts":"^4.5.4"},"gitHead":"210685a03450f83006997f0ad354c183026f88b4","_id":"@0xtlt/devlens@0.2.7","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-jppSG4qWKWMlZ0EGBjuCB+nwlR//ymKvBGUYuvXhZn15v1xb847648bMawZAKND6SmXTAy7Jxi4HLOf+NNx7BA==","shasum":"5fe1a336ab17cdda55b769de2ac662f7d3c40cc8","tarball":"https://registry.npmjs.org/@0xtlt/devlens/-/devlens-0.2.7.tgz","fileCount":18,"unpackedSize":86193,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCi05fHrx/vqu01g9zTt/C3j7f3YTYD1E3/NHA29ccn3QIgDv1hsS+4uRIZVQ/VkYEfyhcTaphui313KuhIsX5adWc="}]},"_npmUser":{"name":"0xtlt","email":"thomastst@protonmail.com"},"directories":{},"maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/devlens_0.2.7_1776249987887_0.67353184253573"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-15T08:16:52.217Z","modified":"2026-04-15T10:46:28.155Z","0.1.0":"2026-04-15T08:16:52.531Z","0.2.0":"2026-04-15T08:21:32.180Z","0.2.1":"2026-04-15T08:43:42.897Z","0.2.2":"2026-04-15T08:50:17.913Z","0.2.3":"2026-04-15T09:12:55.293Z","0.2.4":"2026-04-15T09:25:41.936Z","0.2.5":"2026-04-15T09:44:12.010Z","0.2.6":"2026-04-15T10:22:06.945Z","0.2.7":"2026-04-15T10:46:28.022Z"},"bugs":{"url":"https://github.com/0xtlt/devlens/issues"},"author":{"name":"Thomas Tastet"},"license":"MIT","homepage":"https://github.com/0xtlt/devlens#readme","keywords":["devtools","frontend","debug","developer-tools"],"repository":{"type":"git","url":"git+https://github.com/0xtlt/devlens.git"},"description":"Lightweight frontend devtools panel for any web app","maintainers":[{"name":"0xtlt","email":"thomastst@protonmail.com"}],"readme":"# DevLens\n\nA lightweight, zero-dependency devtools panel you can drop into any web app. It gives you a floating tab bar with live plugins for network inspection, repaint tracking, console mirroring, accessibility auditing, SEO checks and heading outlines — without touching browser devtools.\n\nBuilt in vanilla TypeScript. No runtime dependencies. ~20 KB gzipped for the full bundle.\n\n## Install\n\n```bash\nnpm install @0xtlt/devlens\n# or\nbun add @0xtlt/devlens\n```\n\n## Quick start\n\n```ts\nimport { devlens, allPlugins } from '@0xtlt/devlens'\n\ndevlens({ plugins: allPlugins() })\n```\n\nOr pick only the plugins you need:\n\n```ts\nimport { devlens, consolePlugin, seoPlugin } from '@0xtlt/devlens'\n\ndevlens({ plugins: [consolePlugin(), seoPlugin()] })\n```\n\nNo bundler? Drop it into any HTML page via [esm.sh](https://esm.sh):\n\n```html\n<script type=\"module\">\n  import { devlens, allPlugins } from 'https://esm.sh/@0xtlt/devlens'\n  devlens({ plugins: allPlugins() })\n</script>\n```\n\nThe panel mounts in the bottom-right corner. Press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd> or click the 🔍 button to open it.\n\nOnly load DevLens in development — it mutates the DOM and patches a few globals (`console.error`, `console.warn`, `addEventListener`). A common pattern:\n\n```ts\nif (import.meta.env.DEV) {\n  const { devlens, consolePlugin /* … */ } = await import('@0xtlt/devlens')\n  devlens({ plugins: [consolePlugin()] })\n}\n```\n\n## Plugins\n\nEach plugin is a factory — call it to get a plugin instance, pass the result to `devlens({ plugins: [...] })`.\n\n| Factory | Tab | What it does |\n| --- | --- | --- |\n| `networkPlugin()` | 🌐 Network | Reads `performance.getEntriesByType('resource')` to list requests, group by domain, and flag slow / oversized transfers. Read-only — does not patch `fetch`. |\n| `repaintsPlugin()` | 🎨 Repaints | Watches `MutationObserver` events and draws a canvas overlay that highlights frequently-mutating elements. Color ramps from teal (x1–2) to red (x15+). |\n| `consolePlugin()` | 🚨 Console | Hooks `console.error`, `console.warn`, `window.onerror` and `unhandledrejection`; mirrors them as toasts (when active) and keeps the last 50 entries. |\n| `a11yAuditPlugin()` | ♿ A11y Audit | DOM audit for missing `lang`, heading skips, unlabeled inputs, empty links or buttons, duplicate ids, autoplaying media and more. Draws dashed overlays on offenders. |\n| `a11yTabOrderPlugin()` | 🔢 Tab Order | Numbers every focusable element in the order the keyboard will visit them, making tab traps and positive `tabindex` values obvious. |\n| `a11yClickAuditPlugin()` | 👆 Click Audit | Flags clicks that land on non-semantic elements (`div`, `span`, `img`) carrying click handlers but no `role` + `tabindex`. |\n| `seoPlugin()` | 🔍 SEO | Checks title length, meta description, Open Graph (ogp.me required + recommended), Twitter Card, canonical, robots, charset, viewport, hreflang and JSON-LD. |\n| `headingsPlugin()` | 🗂 Headings | Renders the h1–h6 outline. Flags level skips, empty headings, missing / multiple h1, hidden headings. Click a row to scroll + flash the element on the page. |\n\nYou can also define plugins inline — anything matching the `DevLensPlugin` interface works:\n\n```ts\ndevlens({\n  plugins: [\n    {\n      name: 'Info',\n      icon: '📋',\n      panel: () => `<div>URL: ${location.href}</div>`,\n    },\n  ],\n})\n```\n\n## API\n\n### `devlens(config?)`\n\nMount the panel. Only one instance can exist at a time — a second call logs a warning and returns the existing instance.\n\n```ts\nfunction devlens(config?: Partial<DevLensConfig>): PanelController\n```\n\n**Config**\n\n| Field | Type | Default | Description |\n| --- | --- | --- | --- |\n| `position` | `'bottom-left' \\| 'bottom-right' \\| 'top-left' \\| 'top-right'` | `'bottom-right'` | Panel anchor on the viewport. |\n| `defaultOpen` | `boolean` | `false` | Open the panel on first load instead of just showing the toggle. |\n| `shortcut` | `string` | `'ctrl+shift+d'` | Keyboard shortcut — `ctrl`, `shift`, `alt` modifiers plus a single key. |\n| `plugins` | `DevLensPlugin[]` | `[]` | Plugins to register, in tab order. |\n\n**Returned controller**\n\n```ts\ninterface PanelController {\n  addPlugin(plugin: DevLensPlugin): void\n  removePlugin(name: string): void\n  open(): void\n  close(): void\n  toggle(): void\n  destroy(): void\n}\n```\n\n### `allPlugins()`\n\nReturns a fresh instance of every built-in plugin, ready to be passed to `devlens({ plugins: ... })`. Use this when you want the full experience without picking plugins individually.\n\n```ts\nfunction allPlugins(): DevLensPlugin[]\n```\n\n### `destroyDevlens()`\n\nTear down the current panel and release the singleton slot so `devlens()` can be called again.\n\n### `DevLensPlugin`\n\n```ts\ninterface DevLensPlugin {\n  name: string\n  icon?: string\n  panel: () => HTMLElement | string\n  onMount?: (container: HTMLElement) => void\n  onUnmount?: () => void\n}\n```\n\n**Lifecycle.** `panel()` is called once each time the tab becomes active and must return the tab's content (element or HTML string). `onMount(container)` runs right after the content is attached, with `container` pointing at the wrapper element. `onUnmount()` runs when the user switches to another tab or the panel is destroyed — release any listeners, intervals or overlays there.\n\n**Interval convention.** If your plugin uses `setInterval` for periodic refresh, set the id on a DOM node you own:\n\n```ts\nconst id = setInterval(render, 3000)\ncontainer.setAttribute('data-interval', String(id))\n```\n\nThe panel clears every `[data-interval]` descendant on unmount, so you don't have to.\n\n**Overlay convention.** Any element your plugin adds to `document.body` should carry a `data-devlens` attribute. Other plugins (notably Repaints and A11y Audit) use it to ignore their own internals and avoid feedback loops.\n\n## Development\n\n```bash\nbun install\nbun run dev      # Vite dev server with the playground at index.html\nbun run check    # TypeScript type-check\nbun run lint     # ESLint\nbun run build    # library build (ESM + d.ts) to dist/\n```\n\nThe `dev/` folder holds the playground (`dev/main.ts`) that registers every plugin against `index.html` for manual testing.\n\n### Project layout\n\n```\nsrc/\n  index.ts         Public entry — exports devlens(), allPlugins() and every plugin factory\n  panel.ts         Panel shell, tab switching, keyboard shortcut\n  styles.ts        Injected CSS for the panel chrome\n  toasts.ts        Top-right toast notifications used by plugins\n  types.ts         DevLensPlugin + DevLensConfig\n  config.ts        Default config\n  plugins/\n    network.ts\n    repaints.ts\n    console.ts\n    a11y-audit.ts\n    a11y-tab-order.ts\n    a11y-click-audit.ts\n    seo.ts\n    headings.ts\n```\n\n### Writing a new plugin\n\n1. Create `src/plugins/my-plugin.ts` that exports a factory returning a `DevLensPlugin`.\n2. Export it from `src/index.ts` and add it to the `allPlugins()` helper so users who opt into everything get it for free.\n3. Register it in `dev/main.ts` so the playground picks it up.\n4. Follow the existing patterns: vanilla DOM, inline styles, `data-devlens` on overlays, `data-interval` on your refresh loop.\n\n### Conventions\n\n- Zero runtime dependencies. Keep it that way — the whole point is that DevLens drops into any project without dragging a graph behind it.\n- Vanilla DOM only. No framework, no JSX, no shadow DOM.\n- Plugins must be safe to register multiple times across hot reloads. Use `localStorage` / `sessionStorage` for any state that should survive a refresh.\n- Never throw from a plugin. Swallow errors and surface them as warnings in the tab.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}