{"_id":"@dolard.eu/versiq-widget","_rev":"7-cbd46a43c8221a4b05dfac77fbdf3759","name":"@dolard.eu/versiq-widget","dist-tags":{"latest":"0.6.0"},"versions":{"0.1.0":{"name":"@dolard.eu/versiq-widget","version":"0.1.0","keywords":["widget","versiq","qualification","embed","sdk","conversational"],"author":{"name":"Sébastien Dolard","email":"admin@dolard.eu"},"license":"SEE LICENSE IN LICENSE","_id":"@dolard.eu/versiq-widget@0.1.0","maintainers":[{"name":"admindolard.eu","email":"admin@dolard.eu"}],"homepage":"https://github.com/sdolard/Toize/tree/main/packages/widget#readme","bugs":{"url":"https://github.com/sdolard/Toize/issues"},"dist":{"shasum":"50b4e05c7379aa018b05c2053acc9366ac002977","tarball":"https://registry.npmjs.org/@dolard.eu/versiq-widget/-/versiq-widget-0.1.0.tgz","fileCount":11,"integrity":"sha512-dJUGYG9gNkRMut5V1qAHfCppNPKOLz/XhJeUeuLfK7QFxoLL+jwGxgjhZhOaD+uaYYJ8M20vY/t0Z/2uCa8cYg==","signatures":[{"sig":"MEYCIQDRbFdpjicx1T/7xKX8BylkPdEH1LBNn4stjfZTut72IQIhAP/qLEeVMSHqORgzSzJuh4Ucivwm83ders6zazNNGjj2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":234474},"main":"./dist/widget.umd.js","type":"module","_from":"file:dolard.eu-versiq-widget-0.1.0.tgz","types":"./dist/index.d.ts","unpkg":"./dist/widget.umd.js","module":"./dist/widget.es.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/widget.es.js","require":"./dist/widget.umd.js"},"./widget.js":"./dist/widget.umd.js"},"scripts":{"dev":"vite build --watch","size":"size-limit","test":"vitest","build":"pnpm clean && vite build && tsc -p tsconfig.build.json","clean":"rm -rf dist","serve":"npx serve . -p 5500","test:ci":"vitest run","typecheck":"tsc --noEmit","size:check":"size-limit","typecheck:ci":"pnpm typecheck","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"admindolard.eu","email":"admin@dolard.eu"},"jsdelivr":"./dist/widget.umd.js","_resolved":"/private/var/folders/7m/mywx5jw10qbg9bylk3h9rtpc0000gn/T/c216a2320b143362442e9f4332f6a49a/dolard.eu-versiq-widget-0.1.0.tgz","_integrity":"sha512-dJUGYG9gNkRMut5V1qAHfCppNPKOLz/XhJeUeuLfK7QFxoLL+jwGxgjhZhOaD+uaYYJ8M20vY/t0Z/2uCa8cYg==","repository":{"url":"git+https://github.com/sdolard/Toize.git","type":"git","directory":"packages/widget"},"size-limit":[{"gzip":true,"path":"dist/widget.umd.js","limit":"50 KB"}],"_npmVersion":"11.6.2","description":"Versiq Widget SDK - Embed conversational qualification into your website.","directories":{},"sideEffects":false,"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.2.0","@dolard.eu/versiq-core-types":"0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.5","jsdom":"^26.0.0","vitest":"^4.0.15","size-limit":"^11.0.0","typescript":"^6.0.2","@types/node":"^22.16.0","@size-limit/file":"^11.0.0","@vitest/coverage-v8":"^4.0.15"},"_npmOperationalInternal":{"tmp":"tmp/versiq-widget_0.1.0_1778866409391_0.9148514415904228","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @gamaro.io/widget — see https://github.com/sdolard/Toize"},"0.2.0":{"name":"@dolard.eu/versiq-widget","version":"0.2.0","keywords":["widget","versiq","qualification","embed","sdk","conversational"],"author":{"name":"Sébastien Dolard","email":"admin@dolard.eu"},"license":"SEE LICENSE IN LICENSE","_id":"@dolard.eu/versiq-widget@0.2.0","maintainers":[{"name":"admindolard.eu","email":"admin@dolard.eu"}],"homepage":"https://github.com/sdolard/Toize/tree/main/packages/widget#readme","bugs":{"url":"https://github.com/sdolard/Toize/issues"},"dist":{"shasum":"5749f579e26b8c915434a88148fe5d6dc8db491d","tarball":"https://registry.npmjs.org/@dolard.eu/versiq-widget/-/versiq-widget-0.2.0.tgz","fileCount":11,"integrity":"sha512-j119NrmH5f++xrb/tGXrJz9RRFLXp/4c8FaZf6uplM/g33WP/A7sjEDwrcnpWidAlIScrVn5pn4UYMk9+ncNqA==","signatures":[{"sig":"MEUCIA4AdwulompFsf0PtKypW+kqmk/hnbGPL6KRlwLUDS2oAiEAhiv60Snkr6/3SiDPKP0MFurwYGftUkNhZHGK3nbuohE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":251283},"main":"./dist/widget.umd.js","type":"module","_from":"file:dolard.eu-versiq-widget-0.2.0.tgz","types":"./dist/index.d.ts","unpkg":"./dist/widget.umd.js","module":"./dist/widget.es.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/widget.es.js","require":"./dist/widget.umd.js"},"./widget.js":"./dist/widget.umd.js"},"scripts":{"dev":"vite build --watch","size":"size-limit","test":"vitest","build":"pnpm clean && vite build && tsc -p tsconfig.build.json","clean":"rm -rf dist","serve":"npx serve . -p 5500","test:ci":"vitest run","typecheck":"tsc --noEmit","size:check":"size-limit","typecheck:ci":"pnpm typecheck","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f410d484-ba37-4947-9abe-0545033a6872"}},"jsdelivr":"./dist/widget.umd.js","_resolved":"/tmp/535ddbed074eb2097158dba9874a9f2d/dolard.eu-versiq-widget-0.2.0.tgz","_integrity":"sha512-j119NrmH5f++xrb/tGXrJz9RRFLXp/4c8FaZf6uplM/g33WP/A7sjEDwrcnpWidAlIScrVn5pn4UYMk9+ncNqA==","repository":{"url":"git+https://github.com/sdolard/Toize.git","type":"git","directory":"packages/widget"},"size-limit":[{"gzip":true,"path":"dist/widget.umd.js","limit":"50 KB"}],"_npmVersion":"11.12.1","description":"Versiq Widget SDK - Embed conversational qualification into your website.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"zod":"^4.2.0","@dolard.eu/versiq-core-types":"0.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.5","jsdom":"^26.0.0","vitest":"^4.0.15","size-limit":"^11.0.0","typescript":"^6.0.2","@types/node":"^22.16.0","@size-limit/file":"^11.0.0","@vitest/coverage-v8":"^4.0.15"},"_npmOperationalInternal":{"tmp":"tmp/versiq-widget_0.2.0_1779050578908_0.6821792311617223","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @gamaro.io/widget — see https://github.com/sdolard/Toize"},"0.3.0":{"name":"@dolard.eu/versiq-widget","version":"0.3.0","keywords":["widget","versiq","qualification","embed","sdk","conversational"],"author":{"name":"Sébastien Dolard","email":"admin@dolard.eu"},"license":"SEE LICENSE IN LICENSE","_id":"@dolard.eu/versiq-widget@0.3.0","maintainers":[{"name":"admindolard.eu","email":"admin@dolard.eu"}],"homepage":"https://github.com/sdolard/Toize/tree/main/packages/widget#readme","bugs":{"url":"https://github.com/sdolard/Toize/issues"},"dist":{"shasum":"9a2e975206f66e37201bd463a52d78f7bfa5ed47","tarball":"https://registry.npmjs.org/@dolard.eu/versiq-widget/-/versiq-widget-0.3.0.tgz","fileCount":12,"integrity":"sha512-KQIEV3ry9w2sLSGAgoRuO+Spt5YsDUxbEkN08aLOEGDDpVqs22XPZVTe03nxjhoMntrbh1QZc6SN3EhiK7dQCA==","signatures":[{"sig":"MEQCIHfiwTgYPDeTKCoTgtpjdfyXFZzv4NA7SzpoOwBhas+kAiAsm03wVeMuqsMOUDb9n/OWsW/JZMZOGukqUmHXzGkMJg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":273551},"main":"./dist/widget.umd.js","type":"module","_from":"file:dolard.eu-versiq-widget-0.3.0.tgz","types":"./dist/index.d.ts","unpkg":"./dist/widget.umd.js","module":"./dist/widget.es.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/widget.es.js","require":"./dist/widget.umd.js"},"./widget.js":"./dist/widget.umd.js"},"scripts":{"dev":"vite build --watch","size":"size-limit","test":"vitest","build":"pnpm clean && vite build && tsc -p tsconfig.build.json","clean":"rm -rf dist","serve":"npx serve . -p 5500","test:ci":"vitest run","typecheck":"tsc --noEmit","size:check":"size-limit","typecheck:ci":"pnpm typecheck","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f410d484-ba37-4947-9abe-0545033a6872"}},"jsdelivr":"./dist/widget.umd.js","_resolved":"/tmp/b9ab4c486561c27739d7315c03dd50e0/dolard.eu-versiq-widget-0.3.0.tgz","_integrity":"sha512-KQIEV3ry9w2sLSGAgoRuO+Spt5YsDUxbEkN08aLOEGDDpVqs22XPZVTe03nxjhoMntrbh1QZc6SN3EhiK7dQCA==","repository":{"url":"git+https://github.com/sdolard/Toize.git","type":"git","directory":"packages/widget"},"size-limit":[{"gzip":true,"path":"dist/widget.umd.js","limit":"50 KB"}],"_npmVersion":"11.12.1","description":"Versiq Widget SDK - Embed conversational qualification into your website.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"zod":"^4.2.0","@dolard.eu/versiq-core-types":"0.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.5","jsdom":"^26.0.0","vitest":"^4.0.15","size-limit":"^11.0.0","typescript":"^6.0.2","@types/node":"^22.16.0","@size-limit/file":"^11.0.0","@vitest/coverage-v8":"^4.0.15"},"_npmOperationalInternal":{"tmp":"tmp/versiq-widget_0.3.0_1780250116493_0.5930009180698579","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @gamaro.io/widget — see https://github.com/sdolard/Toize"},"0.4.0":{"name":"@dolard.eu/versiq-widget","version":"0.4.0","keywords":["widget","versiq","qualification","embed","sdk","conversational"],"author":{"name":"Sébastien Dolard","email":"admin@dolard.eu"},"license":"SEE LICENSE IN LICENSE","_id":"@dolard.eu/versiq-widget@0.4.0","maintainers":[{"name":"admindolard.eu","email":"admin@dolard.eu"}],"homepage":"https://github.com/sdolard/Toize/tree/main/packages/widget#readme","bugs":{"url":"https://github.com/sdolard/Toize/issues"},"dist":{"shasum":"1477914b325b9c4eca577b59be9b82fdbd17613c","tarball":"https://registry.npmjs.org/@dolard.eu/versiq-widget/-/versiq-widget-0.4.0.tgz","fileCount":12,"integrity":"sha512-X1PHd5iP4WygFSMIX6Xbt2dV9t7b9ykjUZo5SmUy45ZZF+7ItY3wAO9tHvnG5jV+Rn3nXtsqYY+C9Wjtlbf4gA==","signatures":[{"sig":"MEUCIAXvnRvdxUjQ7LBzpJY+eUzecjbJZtWP2fnLnaspeUL1AiEA3jd5R9uv0O3I1KJFgNzyWpmn13g9o24AIvkDAVgXmr4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":269219},"main":"./dist/widget.umd.js","type":"module","_from":"file:dolard.eu-versiq-widget-0.4.0.tgz","types":"./dist/index.d.ts","unpkg":"./dist/widget.umd.js","module":"./dist/widget.es.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/widget.es.js","require":"./dist/widget.umd.js"},"./widget.js":"./dist/widget.umd.js"},"scripts":{"dev":"vite build --watch","size":"size-limit","test":"vitest","build":"pnpm clean && vite build && tsc -p tsconfig.build.json","clean":"rm -rf dist","serve":"npx serve . -p 5500","test:ci":"vitest run","typecheck":"tsc --noEmit","size:check":"size-limit","typecheck:ci":"pnpm typecheck","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:7aea0afa-0b12-4ad8-90c5-e567b93db33f"}},"jsdelivr":"./dist/widget.umd.js","_resolved":"/tmp/538a0334ca9062021e938260457de489/dolard.eu-versiq-widget-0.4.0.tgz","_integrity":"sha512-X1PHd5iP4WygFSMIX6Xbt2dV9t7b9ykjUZo5SmUy45ZZF+7ItY3wAO9tHvnG5jV+Rn3nXtsqYY+C9Wjtlbf4gA==","repository":{"url":"git+https://github.com/sdolard/Toize.git","type":"git","directory":"packages/widget"},"size-limit":[{"gzip":true,"path":"dist/widget.umd.js","limit":"50 KB"}],"_npmVersion":"11.12.1","description":"Versiq Widget SDK - Embed conversational qualification into your website.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"zod":"^4.2.0","@dolard.eu/versiq-core-types":"0.4.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.5","jsdom":"^26.0.0","vitest":"^4.0.15","size-limit":"^11.0.0","typescript":"^6.0.2","@types/node":"^22.16.0","@size-limit/file":"^11.0.0","@vitest/coverage-v8":"^4.0.15"},"_npmOperationalInternal":{"tmp":"tmp/versiq-widget_0.4.0_1780470720211_0.13774430102083568","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @gamaro.io/widget — see https://github.com/sdolard/Toize"},"0.5.0":{"name":"@dolard.eu/versiq-widget","version":"0.5.0","keywords":["widget","versiq","qualification","embed","sdk","conversational"],"author":{"name":"Sébastien Dolard","email":"admin@dolard.eu"},"license":"SEE LICENSE IN LICENSE","_id":"@dolard.eu/versiq-widget@0.5.0","maintainers":[{"name":"admindolard.eu","email":"admin@dolard.eu"}],"homepage":"https://github.com/sdolard/Toize/tree/main/packages/widget#readme","bugs":{"url":"https://github.com/sdolard/Toize/issues"},"dist":{"shasum":"c34d52be96e207621a160934d692421b2bd25b5a","tarball":"https://registry.npmjs.org/@dolard.eu/versiq-widget/-/versiq-widget-0.5.0.tgz","fileCount":12,"integrity":"sha512-ID7Kp6R+5X57GLMsL86Jegl23Nh5edUrACwaUPobDdxtcJuMjJbkDTx7/1oy6I+MOIPl0jRMQO5DRZ5Mu1ZKyw==","signatures":[{"sig":"MEUCIQDTDXPSUg+bwbWplVvybjvPsFL9+K80oFmhjruY7Y3xcQIgLys2hcNoHY8dw7PDXSj/Ow1naznbCCNnc6kpogGsHzc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":269153},"main":"./dist/widget.umd.js","type":"module","_from":"file:dolard.eu-versiq-widget-0.5.0.tgz","types":"./dist/index.d.ts","unpkg":"./dist/widget.umd.js","module":"./dist/widget.es.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/widget.es.js","require":"./dist/widget.umd.js"},"./widget.js":"./dist/widget.umd.js"},"scripts":{"dev":"vite build --watch","size":"size-limit","test":"vitest","build":"pnpm clean && vite build && tsc -p tsconfig.build.json","clean":"rm -rf dist","serve":"npx serve . -p 5500","test:ci":"vitest run","typecheck":"tsc --noEmit","size:check":"size-limit","typecheck:ci":"pnpm typecheck","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:7aea0afa-0b12-4ad8-90c5-e567b93db33f"}},"jsdelivr":"./dist/widget.umd.js","_resolved":"/tmp/fe97f0de0abdd341d4c7a0692306e93c/dolard.eu-versiq-widget-0.5.0.tgz","_integrity":"sha512-ID7Kp6R+5X57GLMsL86Jegl23Nh5edUrACwaUPobDdxtcJuMjJbkDTx7/1oy6I+MOIPl0jRMQO5DRZ5Mu1ZKyw==","repository":{"url":"git+https://github.com/sdolard/Toize.git","type":"git","directory":"packages/widget"},"size-limit":[{"gzip":true,"path":"dist/widget.umd.js","limit":"50 KB"}],"_npmVersion":"11.13.0","description":"Versiq Widget SDK - Embed conversational qualification into your website.","directories":{},"sideEffects":false,"_nodeVersion":"24.17.0","dependencies":{"zod":"^4.2.0","@dolard.eu/versiq-core-types":"0.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.5","jsdom":"^26.0.0","vitest":"^4.0.15","size-limit":"^11.0.0","typescript":"^6.0.2","@types/node":"^22.16.0","@size-limit/file":"^11.0.0","@vitest/coverage-v8":"^4.0.15"},"_npmOperationalInternal":{"tmp":"tmp/versiq-widget_0.5.0_1782884797040_0.31689527554993746","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @gamaro.io/widget — see https://github.com/sdolard/Toize"},"0.6.0":{"name":"@dolard.eu/versiq-widget","version":"0.6.0","keywords":["widget","versiq","qualification","embed","sdk","conversational"],"author":{"name":"Sébastien Dolard","email":"admin@dolard.eu"},"license":"SEE LICENSE IN LICENSE","_id":"@dolard.eu/versiq-widget@0.6.0","maintainers":[{"name":"admindolard.eu","email":"admin@dolard.eu"}],"homepage":"https://github.com/sdolard/Toize/tree/main/packages/widget#readme","bugs":{"url":"https://github.com/sdolard/Toize/issues"},"dist":{"shasum":"3edf89d7ccee6803f56a0a398bd7fad71d92f780","tarball":"https://registry.npmjs.org/@dolard.eu/versiq-widget/-/versiq-widget-0.6.0.tgz","fileCount":12,"integrity":"sha512-u6pMaNlwYgQRCMarmqOvaBVrQ/VqR4f/UnNXsq6A2RGWj8q9bwDUa0ZcTIvyoNSr506OmLZ96ijCIeFBsq5/Jw==","signatures":[{"sig":"MEUCIQDiHs66Nnsizdp4O2cCg6QZflCnK1gmPMLLkiwxdn4RjwIgKJi8j9UhjAB7FbuwMSZ1gSz7kyytOBUqRrE0PwSX788=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":269735},"main":"./dist/widget.umd.js","type":"module","_from":"file:dolard.eu-versiq-widget-0.6.0.tgz","types":"./dist/index.d.ts","unpkg":"./dist/widget.umd.js","module":"./dist/widget.es.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/widget.es.js","require":"./dist/widget.umd.js"},"./widget.js":"./dist/widget.umd.js"},"scripts":{"dev":"vite build --watch","size":"size-limit","test":"vitest","build":"pnpm clean && vite build && tsc -p tsconfig.build.json","clean":"rm -rf dist","serve":"npx serve . -p 5500","test:ci":"vitest run","typecheck":"tsc --noEmit","size:check":"size-limit","typecheck:ci":"pnpm typecheck","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:7aea0afa-0b12-4ad8-90c5-e567b93db33f"}},"jsdelivr":"./dist/widget.umd.js","_resolved":"/tmp/346b4c650c66b4ce73aa2d96411057bc/dolard.eu-versiq-widget-0.6.0.tgz","_integrity":"sha512-u6pMaNlwYgQRCMarmqOvaBVrQ/VqR4f/UnNXsq6A2RGWj8q9bwDUa0ZcTIvyoNSr506OmLZ96ijCIeFBsq5/Jw==","repository":{"url":"git+https://github.com/sdolard/Toize.git","type":"git","directory":"packages/widget"},"size-limit":[{"gzip":true,"path":"dist/widget.umd.js","limit":"50 KB"}],"_npmVersion":"11.16.0","description":"Versiq Widget SDK - Embed conversational qualification into your website.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"zod":"^4.2.0","@dolard.eu/versiq-core-types":"0.6.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.5","jsdom":"^26.0.0","vitest":"^4.0.15","size-limit":"^11.0.0","typescript":"^6.0.2","@types/node":"^22.16.0","@size-limit/file":"^11.0.0","@vitest/coverage-v8":"^4.0.15"},"_npmOperationalInternal":{"tmp":"tmp/versiq-widget_0.6.0_1783364369664_0.21022633621960263","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed to @gamaro.io/widget — see https://github.com/sdolard/Toize"}},"time":{"created":"2026-05-15T17:33:29.282Z","modified":"2026-08-30T13:01:10.318Z","0.1.0":"2026-05-15T17:33:29.555Z","0.2.0":"2026-05-17T20:42:59.039Z","0.3.0":"2026-05-31T17:55:16.648Z","0.4.0":"2026-06-03T07:12:00.404Z","0.5.0":"2026-07-01T05:46:37.196Z","0.6.0":"2026-07-06T18:59:29.817Z"},"bugs":{"url":"https://github.com/sdolard/Toize/issues"},"author":{"name":"Sébastien Dolard","email":"admin@dolard.eu"},"license":"SEE LICENSE IN LICENSE","homepage":"https://github.com/sdolard/Toize/tree/main/packages/widget#readme","keywords":["widget","versiq","qualification","embed","sdk","conversational"],"repository":{"url":"git+https://github.com/sdolard/Toize.git","type":"git","directory":"packages/widget"},"description":"Versiq Widget SDK - Embed conversational qualification into your website.","maintainers":[{"name":"admindolard.eu","email":"admin@dolard.eu"}],"readme":"# @dolard.eu/versiq-widget\n\n[![npm version](https://img.shields.io/npm/v/@dolard.eu/versiq-widget.svg)](https://www.npmjs.com/package/@dolard.eu/versiq-widget)\n[![bundle size](https://img.shields.io/badge/gzip-%3C50%20KB-brightgreen.svg)](#bundle-size)\n[![types](https://img.shields.io/npm/types/@dolard.eu/versiq-widget.svg)](#typescript)\n[![license](https://img.shields.io/badge/license-Commercial%20Source--available-blue.svg)](./LICENSE)\n\nVersiq Widget SDK — embed a conversational conversion agent that answers\nvisitors using **your** site's data (catalogue, inventory, CRM, knowledge base),\nnot the public-web average a generic LLM assistant returns.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Why this widget converts](#why-this-widget-converts)\n- [Configuration](#configuration)\n- [API Reference](#api-reference)\n- [Events](#events)\n- [TypeScript](#typescript)\n- [Vertical Resolution](#vertical-resolution)\n- [Display Modes](#display-modes)\n- [React Integration](#react-integration)\n- [Data Attributes (Script Tag)](#data-attributes-script-tag)\n- [Security](#security)\n- [E2E Test Selectors (data-testid)](#e2e-test-selectors-data-testid)\n- [Performance](#performance)\n- [Browser Support](#browser-support)\n- [Changelog](#changelog)\n- [Support](#support)\n- [License](#license)\n\n## Installation\n\n```bash\nnpm install @dolard.eu/versiq-widget\n# or\npnpm add @dolard.eu/versiq-widget\n```\n\n## Quick Start\n\n### Script Tag (CDN)\n\nHot-link the latest published bundle from any public npm CDN. A single line is\nenough — the publishable key binds the widget to your Agent, everything else is\nresolved server-side.\n\n```html\n<script\n  src=\"https://unpkg.com/@dolard.eu/versiq-widget@latest/dist/widget.umd.js\"\n  data-api-key=\"pk_your_key\"\n></script>\n```\n\nEquivalent via jsDelivr:\n\n```html\n<script\n  src=\"https://cdn.jsdelivr.net/npm/@dolard.eu/versiq-widget@latest/dist/widget.umd.js\"\n  data-api-key=\"pk_your_key\"\n></script>\n```\n\n`@latest` always serves the most recent release, so a bug fix or improvement\nreaches your visitors without you editing the snippet. If you need to pin a\nspecific version for change-control reasons, replace `@latest` with `@<VERSION>`\n(see [npm](https://www.npmjs.com/package/@dolard.eu/versiq-widget) for the list)\n— at the cost of having to bump it manually on every release.\n\n### Programmatic API\n\nThe minimal integration is one line — every visual and behavioural aspect\n(theme, position, language, open-state, branding) is configured in the **Versiq\nadmin portal** for your Agent and resolved server-side from the API key.\n\n```typescript\nimport { createWidget } from \"@dolard.eu/versiq-widget\";\n\nconst widget = createWidget({ apiKey: \"pk_live_your_key\" });\n\n// Control the widget at runtime\nwidget.open();\nwidget.close();\nwidget.reset();\n\n// Cleanup (e.g., on SPA route change)\nwidget.destroy();\n```\n\n## Why this widget converts\n\nTwo reasons most platforms fail to convert mobile visitors, and two reasons this\nwidget does:\n\n1. **It speaks with your data, not the public-web average.** The agent answers\n   from your catalogue, your stock, your CRM, your knowledge base — what your\n   competitors and generic AI assistants don't have.\n2. **It is driven by your thumb, not your keyboard.** The LLM dynamically picks\n   the right component at every turn — quick replies, sliders, product cards —\n   instead of forcing a form. Visitors qualify their need in a few taps on\n   mobile, where 3+ field forms lose 50%+ of users (HubSpot).\n\nThe widget rendering layer (`QuickReplies`, `PropertyCard`, `ActionButtons`) is\nthe runtime that materialises this. Schemas live in the Versiq backend\nrepository and are out of scope for the SDK consumer.\n\n## Configuration\n\nWidget configuration is split into three scopes — only the first one is your\nresponsibility as an integrator.\n\n### 1. Host-side (passed to `createWidget` or as `data-*` attributes)\n\nThese can only live on the integrator's page because they describe the host\ncontext (DOM, identity, environment).\n\n| Option      | Type                    | Default        | Description                                                                                             |\n| ----------- | ----------------------- | -------------- | ------------------------------------------------------------------------------------------------------- |\n| `apiKey`    | `string`                | **required**   | Publishable API key (`pk_live_*`, `pk_test_*`). Binds the widget to one Agent.                          |\n| `container` | `HTMLElement \\| string` | -              | DOM container for inline mode. Required only when the admin has set `position: \"inline\"` on the portal. |\n| `baseUrl`   | `string`                | Production URL | Override the widget iframe origin. Only useful for sandbox / self-hosted setups.                        |\n| `debug`     | `boolean`               | `false`        | Enable debug logging in the browser console.                                                            |\n| `email`     | `string`                | -              | Pre-identified visitor email — must be paired with `userHash`.                                          |\n| `userId`    | `string`                | -              | Host-side stable user identifier — must be paired with `userHash`.                                      |\n| `userHash`  | `string`                | -              | HMAC-SHA256 of `email` (or `userId`), signed with the Agent identity secret. See _Identity_.            |\n\n### 2. Server-resolved (configured in the Versiq admin portal)\n\nThese are **not** passed by the integration — they are stored in the Agent's\n`widget_config` JSONB row and fetched at bootstrap from the API key. To change\nany of them, edit the Agent in the portal.\n\n| Field             | Configured in admin        | Notes                                                                                                       |\n| ----------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------- |\n| `theme`           | Apparence → palette        | Full palette (`primaryColor`, `backgroundColor`, `textColor`, `borderRadius`, `fontFamily`, `colorScheme`). |\n| `position`        | Apparence → position       | `\"bottom-right\"`, `\"bottom-left\"`, or `\"inline\"`.                                                           |\n| `language`        | Apparence → langue         | ISO 639-1 (e.g. `fr`, `en`). Falls back to browser language when unset.                                     |\n| `showProfile`     | Apparence → panneau profil | Toggles the profile panel in the widget header.                                                             |\n| `open`            | Apparence → état initial   | Default open state on page load. Host can still call `widget.open()` programmatically.                      |\n| `brand.title`     | Branding → titre           | Custom header title (falls back to a vertical-specific default).                                            |\n| `brand.avatarUrl` | Branding → avatar          | Custom avatar URL (must originate from the portal upload — arbitrary URLs are rejected).                    |\n| `vertical`        | Agent creation             | `real-estate`, `b2b-qualification`, … Bound to the API key.                                                 |\n\n### 3. Client overrides (advanced — rarely needed in production)\n\nFor tooling, A/B previews or staging environments, every server-resolved field\nabove can also be passed as a `WidgetConfig` argument or `data-*` attribute. A\nhost-side value, when present, **takes precedence over the admin value**. This\nis intentional — but in production you should configure things in the portal so\nall your sites stay in sync.\n\n```typescript\n// Override only for a staging preview — production should leave this out\ncreateWidget({\n  apiKey: \"pk_test_...\",\n  theme: { primaryColor: \"#3B82F6\" },\n  position: \"bottom-left\",\n});\n```\n\n### `ThemeConfig` shape (admin-defined, occasionally overridden)\n\n| Option            | Type                          | Description                                                                                    |\n| ----------------- | ----------------------------- | ---------------------------------------------------------------------------------------------- |\n| `primaryColor`    | `string`                      | Primary brand color (hex, e.g., `#3B82F6`)                                                     |\n| `backgroundColor` | `string`                      | Background color for the widget container                                                      |\n| `textColor`       | `string`                      | Text color                                                                                     |\n| `borderRadius`    | `number`                      | Border radius in pixels                                                                        |\n| `fontFamily`      | `string`                      | Font family                                                                                    |\n| `colorScheme`     | `\"light\" \\| \"dark\" \\| \"auto\"` | Widget color scheme. `\"auto\"` follows the visitor's `prefers-color-scheme`. Defaults to light. |\n\n### Motion\n\nThe widget animates state changes (open/close resize, message and quick-reply\nentrances, hover feedback) with a single, coherent motion language: a harmonic\nduration scale and Material-style easing curves, all transitions kept under\n400ms. These **motion tokens are internal** — they are not part of the\n`ThemeConfig` contract and cannot be overridden by integrators (kept internal\nuntil a concrete need arises). The widget fully honours\n`prefers-reduced-motion: reduce`: when the visitor opts out, every transition\nand animation is neutralised. Design rationale and the full token table live in\n[ADR-018](../../docs/adr/ADR-018-widget-motion-design.md).\n\n## API Reference\n\n### createWidget(config)\n\nCreates a new widget instance. The minimal call is `createWidget({ apiKey })` —\nevery behaviour comes from the admin portal. The example below illustrates the\ninline mode where the integrator must additionally supply a `container`\n(host-context only).\n\n```typescript\nconst widget = createWidget({\n  apiKey: \"pk_live_your_key\",\n  // Required only when the admin set position: \"inline\" on the portal\n  container: document.getElementById(\"widget-container\"),\n});\n```\n\n### VersiqWidget Methods\n\n| Method                                                | Description                                              |\n| ----------------------------------------------------- | -------------------------------------------------------- |\n| `open()`                                              | Open the widget                                          |\n| `close()`                                             | Close the widget                                         |\n| `reset()`                                             | Reset the conversation                                   |\n| `setTheme(theme: ThemeConfig)`                        | Update theme dynamically                                 |\n| `setColorScheme(scheme: \"light\" \\| \"dark\" \\| \"auto\")` | Sugar over `setTheme({ colorScheme })` for dark-mode UIs |\n| `identify(params)`                                    | Set host-attested identity (HMAC)                        |\n| `destroy()`                                           | Remove widget and cleanup                                |\n| `on(event, handler)`                                  | Subscribe to events                                      |\n| `off(event, handler)`                                 | Unsubscribe from events                                  |\n\n### Window API (Script Tag)\n\nWhen using the script tag, the API is available on `window.Versiq`:\n\n```javascript\nwindow.Versiq.open();\nwindow.Versiq.close();\nwindow.Versiq.setTheme({ primaryColor: \"#10B981\" });\n\n// Wire your own dark-mode toggle to the widget:\nwindow.Versiq.setColorScheme(\"dark\"); // or \"light\", or \"auto\"\n```\n\n## Events\n\nSubscribe to widget events to react to user interactions.\n\n```typescript\nwidget.on(\"ready\", () => {\n  console.log(\"Widget is ready\");\n});\n\nwidget.on(\"profile-update\", () => {\n  console.log(\"Profile was updated\"); // signal only, no data\n});\n\nwidget.on(\"qualified\", () => {\n  console.log(\"Lead qualified\"); // signal only, no data\n  // Full profile + score: subscribe to the lead.qualified backend webhook\n});\n\nwidget.on(\"message\", (data) => {\n  console.log(\"New message:\", data.message);\n});\n\nwidget.on(\"error\", (data) => {\n  console.error(\"Widget error:\", data.code, data.message);\n});\n```\n\n### Event Types\n\n| Event                 | Payload                                              | Description                                                            |\n| --------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------- |\n| `ready`               | -                                                    | Widget is loaded and ready                                             |\n| `open`                | -                                                    | Widget was opened                                                      |\n| `close`               | -                                                    | Widget was closed                                                      |\n| `message`             | `{ message: WidgetMessage }`                         | New chat message                                                       |\n| `profile-update`      | -                                                    | Profile was updated (signal only — subscribe to webhooks for the data) |\n| `qualified`           | -                                                    | Lead qualified (signal only — subscribe to the `lead.qualified` webhook for the data) |\n| `funnel-stage-change` | `{ stage: string, previousStage: string \\| null }`   | Conversion funnel stage transition                                     |\n| `cta-shown`           | `{ ctaType: string, objectiveId?: string }`          | A call-to-action was displayed                                         |\n| `cta-clicked`         | `{ ctaType: string, objectiveId?: string }`          | A call-to-action was clicked                                           |\n| `lead-captured`       | `{ hasEmail: boolean, hasPhone: boolean }`           | Lead contact details captured                                          |\n| `error`               | `{ code: string, message: string }`                  | An error occurred                                                      |\n| `quota-warning`       | `{ remaining: number, limit: number }`               | Lead quota running low                                                 |\n| `quota-exceeded`      | -                                                    | Lead quota exceeded                                                    |\n| `identity-verified`   | `{ email: string, userId?: string }`                 | Host identity verified (HMAC)                                          |\n| `widget-unavailable`  | `{ reason: \"timeout\" \\| \"error\", attempts: number }` | SDK exhausted all load retries — the widget degrades to a static state |\n\n## TypeScript\n\nThe package includes full TypeScript support with exported types:\n\n```typescript\nimport type {\n  WidgetConfig,\n  ThemeConfig,\n  VersiqWidget,\n  WidgetEventType,\n  WidgetProfile,\n  WidgetMessage,\n  B2BProfile, // B2B-specific (backward compat)\n} from \"@dolard.eu/versiq-widget\";\n```\n\n### Profile Types\n\n- **`WidgetProfile`** (`Record<string, unknown>`) — Generic profile used in\n  events. Shape depends on the vertical (`BuyerProfile` for real-estate,\n  `B2BProfile` for b2b-qualification).\n- **`B2BProfile`** — Typed B2B qualification profile (sector, companySize,\n  etc.). Kept for backward compatibility.\n\n## Vertical Resolution\n\nThe vertical (`real-estate`, `b2b-qualification`, …) is **resolved server-side\nfrom the API key** — you do not pass it from the integration. Each `pk_*` key is\nbound to exactly one Agent, and each Agent is bound to one vertical. Switching\nvertical = creating a new Agent + new key.\n\n### Real-Estate flow\n\nWhen the resolved vertical is `real-estate`, the widget runs in qualification\nmode: Versiq qualifies the buyer through conversation and emits the profile — no\nproperty data is needed from the integrator (data-dependent tools like\n`searchProperties`, `getCityStats`, `estimateProperty` are automatically\nexcluded).\n\n```typescript\n// Assumes the real-estate Agent is configured for `inline` mode in\n// the admin portal. Only the host-context fields are passed here.\nconst widget = createWidget({\n  apiKey: \"pk_live_your_real_estate_key\",\n  container: \"#chat\",\n});\n\n// UX signals only — trigger a CTA or an analytics event, no lead data here\nwidget.on(\"profile-update\", () => {\n  showProgressIndicator();\n});\n\nwidget.on(\"qualified\", () => {\n  showQualifiedBadge();\n});\n```\n\nThe profile/score data itself never flows through `postMessage` (#1993) — it\nis only delivered server-side via a POST to your configured `webhookUrl` on\n`lead.qualified`, configured in the admin portal:\n\n```json\n{\n  \"event\": \"lead.qualified\",\n  \"data\": {\n    \"sessionId\": \"…\",\n    \"profile\": { \"userType\": \"prospect\", \"location\": \"…\", \"budget\": 450000, \"propertyType\": \"…\" }\n  }\n}\n```\n\n## Display Modes\n\nDisplay mode (`bottom-right`, `bottom-left`, `inline`) is set in the admin\nportal. From the integrator's side, the only difference is whether you also need\nto supply a `container`.\n\n### Floating (admin chose `bottom-right` or `bottom-left`)\n\nWidget appears as a floating button in the corner of the page. No `container`\nneeded.\n\n```typescript\ncreateWidget({ apiKey: \"pk_live_your_key\" });\n```\n\n### Inline (admin chose `inline`)\n\nWidget is mounted directly into a DOM container you provide.\n\n```typescript\ncreateWidget({\n  apiKey: \"pk_live_your_key\",\n  container: document.getElementById(\"chat-container\"),\n});\n```\n\n## React Integration\n\n```tsx\n\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { createWidget, type VersiqWidget } from \"@dolard.eu/versiq-widget\";\n\nexport function ContactWidget() {\n  const widgetRef = useRef<VersiqWidget | null>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    if (!containerRef.current || widgetRef.current) return;\n\n    // Assumes the Agent is configured for `inline` mode in the admin\n    // portal — only the host-context fields (apiKey + container) are passed\n    // here. Theme, position, language, etc. come from the server config.\n    const widget = createWidget({\n      apiKey: \"pk_live_your_key\",\n      container: containerRef.current,\n    });\n\n    widgetRef.current = widget;\n\n    return () => {\n      widgetRef.current?.destroy();\n      widgetRef.current = null;\n    };\n  }, []);\n\n  return <div ref={containerRef} className=\"h-[600px]\" />;\n}\n```\n\n## Data Attributes (Script Tag)\n\nAll `WidgetConfig` options can be passed as kebab-cased `data-*` attributes on\nthe `<script>` tag. The same scope split as the JavaScript API applies — in\npractice only `data-api-key` is needed.\n\n### Host-side (essential)\n\n| Attribute        | Maps to     | Example                                 |\n| ---------------- | ----------- | --------------------------------------- |\n| `data-api-key`   | `apiKey`    | `data-api-key=\"pk_live_abc123\"`         |\n| `data-container` | `container` | `data-container=\"#chat\"`                |\n| `data-base-url`  | `baseUrl`   | `data-base-url=\"https://app.versiq.io\"` |\n| `data-debug`     | `debug`     | `data-debug=\"true\"`                     |\n| `data-email`     | `email`     | `data-email=\"user@example.com\"`         |\n| `data-user-id`   | `userId`    | `data-user-id=\"usr_123\"`                |\n| `data-user-hash` | `userHash`  | `data-user-hash=\"<hmac>\"`               |\n\n`data-container` is a CSS selector and is only needed when the admin set\n`position: \"inline\"` on the portal.\n\n> **No theme / position / language overrides via `data-*`.** Unlike the\n> programmatic API, server-resolved fields (`theme`, `position`, `language`,\n> `showProfile`, `open`) **cannot** be overridden from the script tag — the\n> legacy `data-theme` / `data-position` / `data-language` / `data-show-profile`\n> / `data-open` attributes are silently ignored. Configure these in the admin\n> portal, or use `createWidget({ theme, position, … })` for the tooling/preview\n> override path.\n\n## Security\n\nThe widget runs inside an `<iframe>` in your visitors' browsers. Three host-side\nconcerns are worth understanding before going to production: identity\nattestation, the host `Permissions-Policy`, and your `Content-Security-Policy`.\n\n### Identity verification (HMAC)\n\nBy default a visitor is anonymous. If your page already knows who the visitor is\n(a logged-in user), you can attest that identity to Versiq so leads are attached\nto the right account — without trusting a client-supplied email blindly.\n\nPass `email` (or `userId`) **together with** a `userHash`: an HMAC-SHA256 of the\n`email` (or `userId`), computed **server-side** with your Agent's identity\nsecret (never expose that secret in the browser). The widget forwards the triple\nand the backend recomputes the HMAC to verify it; on success it emits the\n`identity-verified` event.\n\n```typescript\n// Server-side (your backend) — pseudo-code\nconst userHash = hmacSHA256(user.email, AGENT_IDENTITY_SECRET);\n\n// Client-side — pass the precomputed hash, never the secret\ncreateWidget({\n  apiKey: \"pk_live_your_key\",\n  email: user.email,\n  userHash, // injected from your server-rendered page\n});\n```\n\nA mismatched or missing `userHash` leaves the visitor anonymous — the widget\nkeeps working, it just does not attest the identity.\n\n### Host page Permissions-Policy\n\nSome widget features rely on browser-level permissions that **must be granted by\nthe host page** — the iframe itself can't unlock a capability the parent\ndocument forbids.\n\n| Feature                                                                                                            | Browser permission                                         | Required `Permissions-Policy` on the host                                 |\n| ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- | ------------------------------------------------------------------------- |\n| `Autour de moi` quick-reply (real-estate) — proposes nearby cities/districts based on the visitor's current coords | `geolocation` (`navigator.geolocation.getCurrentPosition`) | `geolocation=(self)` at minimum (or include the widget origin explicitly) |\n| Copy property listing / share link buttons                                                                         | `clipboard-write`                                          | `clipboard-write=(self)` (most hosts already inherit the default)         |\n\nIf your site already ships a `Permissions-Policy` header (recommended for\ndefense in depth — see\n[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy)),\nadd `geolocation=(self)` to the list. The widget iframe is created with\n`allow=\"clipboard-write; geolocation\"` so the parent's permission propagates\nautomatically once it's not denied.\n\nMinimal header example:\n\n```http\nPermissions-Policy: camera=(), microphone=(), geolocation=(self)\n```\n\n**What happens if you forget**: the widget keeps working — except the\ngeolocation-backed quick-replies log\n`Geolocation has been disabled in this document by permissions policy.` to the\nvisitor's console and the chip silently does nothing on click. The underlying\nconversation still works; the visitor just types the city manually.\n\n### Content-Security-Policy\n\nPermissions-Policy controls **what the iframe is allowed to do**;\nContent-Security-Policy controls **where scripts / iframes / styles can come\nfrom**. Both are independent and both are needed in production. The CSP\ndirectives required for the Versiq widget are documented in the Versiq backend\nrepo at `docs/B2B_INTEGRATION.md` § \"Content-Security-Policy pour intégrateurs\".\n\n## E2E Test Selectors (data-testid)\n\nFor a smoke test that the widget mounted and works on your page, a small core of\n`data-testid` selectors is exposed. These are guaranteed not to change without a\nmajor version bump.\n\n| Selector                | Element                                                                       | Additional attributes              |\n| ----------------------- | ----------------------------------------------------------------------------- | ---------------------------------- |\n| `widget-root`           | Chat container (open)                                                         | —                                  |\n| `widget-input`          | Message input field                                                           | —                                  |\n| `widget-send`           | Send button                                                                   | —                                  |\n| `widget-message`        | Message bubble                                                                | `data-role=\"user\" \\| \"assistant\"`  |\n| `widget-loading-status` | Running-tool status label beside the typing dots (e.g. \"Recherche de biens…\") | — (absent until a tool runs)       |\n| `widget-suggestion`     | Quick reply chip                                                              | `data-index=\"<N>\"` (position)      |\n| `widget-cta-button`     | Call-to-action button                                                         | `data-objective=\"<objectiveType>\"` |\n| `widget-avatar`         | Header avatar                                                                 | —                                  |\n\n> The widget also exposes a large set of vertical-specific selectors\n> (real-estate map, areas-overview, exploration mode, criteria popup, range\n> slider, contact form). They are internal to the Versiq UI and out of scope for\n> SDK consumers — the full contract lives in the Versiq backend repository under\n> `apps/app/src/app/widget/embed/components/`.\n\n### Example (Playwright)\n\n```ts\nawait page.getByTestId(\"widget-input\").fill(\"Looking for a 2-bedroom in Lyon\");\nawait page.getByTestId(\"widget-send\").click();\nawait expect(\n  page.getByTestId(\"widget-message\").filter({ hasText: \"Lyon\" }),\n).toBeVisible();\n```\n\n## Performance\n\n### Bundle Size\n\n| Format | Size (minified) | Size (gzipped) | Limit |\n| ------ | --------------- | -------------- | ----- |\n| UMD    | ~84 KB          | ~24 KB         | 50 KB |\n| ESM    | ~112 KB         | ~26 KB         | -     |\n\nCI enforces the 50 KB gzipped limit via `size-limit`.\n\n### Largest Contentful Paint (LCP)\n\n**Target**: < 1.5s\n\nThe widget loads as an iframe, so LCP depends on:\n\n1. SDK download (~16 KB gzipped) - typically < 100ms\n2. Iframe creation - instant\n3. Embed page load - varies by network\n\n#### Measured baselines\n\n| Environment             | Device       | LCP          | Notes                                                                                                 |\n| ----------------------- | ------------ | ------------ | ----------------------------------------------------------------------------------------------------- |\n| Localhost (no throttle) | Desktop      | 0.14s        | Reference for development. Not representative of real visitor conditions — production target is 1.5s. |\n| Marketing demo, Fast 4G | Desktop      | _to measure_ | Lighthouse against `https://<marketing>/fr/demo/real-estate`, throttle \"Fast 4G\", incognito.          |\n| Marketing demo, Slow 3G | Mobile (mid) | _to measure_ | Same URL, Lighthouse mobile preset, throttle \"Slow 3G\".                                               |\n| Marketing demo, Fast 4G | Mobile (mid) | _to measure_ | Same URL, Lighthouse mobile preset, throttle \"Fast 4G\".                                               |\n\n> The three \"to measure\" rows are reserved for the next manual measurement pass\n> against the marketing demo in prod. They are kept visible here so a visitor of\n> this README sees what is covered and what is not, rather than a single\n> localhost number that paints an over-optimistic picture.\n\n#### How to measure LCP yourself (Lighthouse)\n\nReproducible manual procedure on any deployment that embeds the widget (staging,\nprod demo, or your own integration). The marketing demo is the canonical\nreference.\n\n1. Open Chrome in **incognito** (no extensions, no cache, no service worker from\n   a previous visit interfering with the measurement).\n2. Go to `https://<marketing-host>/fr/demo/real-estate` (or your own page\n   embedding `@dolard.eu/versiq-widget`).\n3. Open **DevTools → Lighthouse**.\n4. Select **Performance** only, choose the **Mode = Navigation**.\n5. Pick the device preset (Mobile or Desktop) and the throttling profile\n   (`Slow 4G`, `Fast 4G`, or `Slow 3G` — match the row you want to fill in the\n   table above).\n6. Click **Analyze page load**.\n7. Read the **Largest Contentful Paint** metric from the report (top-left block,\n   color-coded green/orange/red against the 2.5s \"good\" threshold).\n\nRun each scenario **3 times** and report the median to absorb cold-cache /\nnetwork jitter. A single run is not a measurement, it's an anecdote.\n\n#### Continuous measurement (production sites)\n\nFor integrators who want to keep an eye on the metric over time without running\nLighthouse manually:\n\n- Install the\n  [**Web Vitals Chrome extension**](https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma)\n  for a live LCP overlay while browsing.\n- Wire [**web-vitals**](https://github.com/GoogleChrome/web-vitals) into your\n  analytics pipeline (Google Analytics 4, Sentry, etc.) to track field LCP per\n  real visitor — Lighthouse alone only measures synthetic loads.\n\nThe Versiq widget itself does not emit web-vitals events (out of scope — the SDK\nshould not impose an analytics dependency on the host). Integrators own the\nmeasurement pipeline for their own page.\n\n### Integration Time\n\n**Target**: < 15 minutes from docs to working widget\n\nThe Quick Start section provides copy-paste integration in under 5 minutes.\n\n## Browser Support\n\nThe SDK ships modern ESM and UMD bundles and targets evergreen browsers:\n\n| Browser                  | Supported             |\n| ------------------------ | --------------------- |\n| Chrome / Edge (Chromium) | last 2 major versions |\n| Firefox                  | last 2 major versions |\n| Safari (macOS / iOS)     | last 2 major versions |\n| Internet Explorer        | not supported         |\n\nThe widget relies on `<iframe>`, `postMessage`, `WeakSet`, and `fetch` — all\navailable in every browser above. For the Node.js toolchain (bundlers, SSR\nhosts), `engines.node` is `>=18`.\n\n## Changelog\n\nRelease notes are maintained automatically by release-please — see\n[CHANGELOG.md](./CHANGELOG.md). Versions are bumped lockstep with\n`@dolard.eu/versiq-core-types`.\n\n## Support\n\n- **Integration help & bug reports**:\n  [open an issue](https://github.com/sdolard/Toize/issues).\n- **Commercial licensing & contracts**: admin@dolard.eu\n\n## License\n\nCommercial Source-available — see [LICENSE](./LICENSE).\n\nThis is **not** an open-source release: the source is published so integrators\ncan audit what runs in their visitors' browsers, but fork / redistribution /\ncompeting-SDK use are prohibited without a written agreement. Production use\nagainst the Versiq backend is governed by the Versiq Commercial Terms of\nService.\n\nFor commercial licensing inquiries: admin@dolard.eu\n","readmeFilename":"README.md"}