{"_id":"@dentsdumidi/chmln","name":"@dentsdumidi/chmln","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@dentsdumidi/chmln","version":"0.1.0","description":"Embeddable product feedback widget that turns user wishes into safe UI previews.","type":"module","main":"dist/index.js","browser":"dist/browser.js","unpkg":"dist/browser.js","jsdelivr":"dist/browser.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.js"}},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/j-j-kam/chameleon.git"},"bugs":{"url":"https://github.com/j-j-kam/chameleon/issues"},"homepage":"https://github.com/j-j-kam/chameleon#readme","keywords":["feedback","product-feedback","web-component","ui-preview","ai"],"publishConfig":{"access":"public"},"engines":{"node":">=18"},"scripts":{"build":"tsc","prepack":"npm run build","docker:build":"docker compose build","docker:run":"docker compose up","docker:pack":"docker compose run --build --rm pack","demo":"docker compose up --build","dashboard":"npm run demo"},"devDependencies":{"typescript":"^5.5.0"},"_id":"@dentsdumidi/chmln@0.1.0","_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-A0Fs93wS7u2fgumHVYP9sAhLg0ijxmAo9M6piZwXv032P3PEC+gZfhvNkGhGpTgxghEsfseDjHaiPSX8j/hnyw==","shasum":"d31f489ab039d105f5720b77a6373e1c24dc7b98","tarball":"https://registry.npmjs.org/@dentsdumidi/chmln/-/chmln-0.1.0.tgz","fileCount":15,"unpackedSize":51822,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAFINPGkeCKWutTfoGneZk34JBldX84w9gtYHjEK5mgIAiAiMe+chDykwF6dRzo1vAQx8grKuLO0JdoInRmdSJ0vaQ=="}]},"_npmUser":{"name":"dentsdumidi","email":"georgy@skrub.ai"},"directories":{},"maintainers":[{"name":"dentsdumidi","email":"georgy@skrub.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/chmln_0.1.0_1786287382767_0.018966649441040095"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-09T14:56:22.610Z","0.1.0":"2026-08-09T14:56:22.923Z","modified":"2026-08-09T14:56:23.197Z"},"maintainers":[{"name":"dentsdumidi","email":"georgy@skrub.ai"}],"description":"Embeddable product feedback widget that turns user wishes into safe UI previews.","homepage":"https://github.com/j-j-kam/chameleon#readme","keywords":["feedback","product-feedback","web-component","ui-preview","ai"],"repository":{"type":"git","url":"git+https://github.com/j-j-kam/chameleon.git"},"bugs":{"url":"https://github.com/j-j-kam/chameleon/issues"},"license":"MIT","readme":"# Chameleon\n\nChameleon helps users show what they expected your product to do.\n\nInstead of vague feedback like \"this is confusing\" or \"I wish this worked differently\", users chat with an embeddable widget and shape a safe preview of the missing flow, behavior, or UI they had in mind.\n\nChameleon does not edit the real app or run model-generated code. It clones the page, applies structured preview operations, and sends the product team the prompt, page context, chat history, and final scenario.\n\n## What It Does\n\n- captures safe page context from the current page\n- lets users chat with an AI model about what they expected\n- keeps conversation state per feedback journey\n- renders a temporary preview using structured operations\n- exports a report for product review\n\nSupported preview operations:\n\n- `setText`\n- `setStyle`\n- `insertAfter`\n- `insertBefore`\n- `replace`\n- `remove`\n\nChameleon can update existing page elements and safely insert common preview primitives:\n\n- `button`\n- `select`\n- `input`\n- `textarea`\n- `checkbox`\n- `radio`\n- `link`\n- `image`\n- `text`\n- `badge`\n- `list`\n- `card`\n- `section`\n- `form`\n- `modal`\n- `table`\n- `tabs`\n- `toolbar`\n\nNo raw HTML. No generated JavaScript. No production DOM mutation.\n\n## Docker\n\n```sh\ndocker compose up --build\n```\n\nDashboard: `http://localhost:8080`\nDemo: `http://localhost:8080/demo/`\n\nFor the local demo-only OpenAI path:\n\n```sh\nCHAMELEON_OPENAI_API_KEY=sk-... docker compose up --build\n```\n\nThe local direct-OpenAI demo keeps response state in memory per journey. It resets on refresh or rebuild.\n\n## Hosted Backend\n\nThe hosted MVP lives in `supabase/`.\n\n```ts\nimport { createCloudProposalGenerator, createCloudReportSubmitter, mountChameleon } from \"@dentsdumidi/chmln\";\n\nconst cloud = {\n  functionsUrl: \"https://PROJECT.supabase.co/functions/v1\",\n  projectId: \"PROJECT_ID\",\n  anonKey: \"SUPABASE_ANON_KEY\"\n};\n\nmountChameleon({\n  generateProposal: createCloudProposalGenerator(cloud),\n  onSubmit: createCloudReportSubmitter(cloud)\n});\n```\n\nDeploy the Supabase functions with `OPENAI_API_KEY` set server-side. Hosted proposal generation stores the last OpenAI response id per widget journey and continues from it on the next turn.\n\n## Local SDK\n\n```sh\nnpm install @dentsdumidi/chmln\n```\n\n```ts\nimport { createOpenAIProposalGenerator, mountChameleon } from \"@dentsdumidi/chmln\";\n\nmountChameleon({\n  generateProposal: createOpenAIProposalGenerator({\n    apiKey: \"demo-openai-api-key\"\n  }),\n  onSubmit(report) {\n    console.log(report);\n  }\n});\n```\n\nDo not put a private LLM provider key in a public page. Use the hosted/backend path for production.\n\n## Browser CDN\n\nThe browser entry exposes `window.Chameleon`:\n\n```html\n<script type=\"module\">\n  import \"https://esm.sh/@dentsdumidi/chmln/browser\";\n\n  window.Chameleon.init({\n    projectId: \"PROJECT_ID\",\n    endpoint: \"https://PROJECT.supabase.co/functions/v1/chameleon-propose\"\n  });\n</script>\n```\n\n`init` is for proposal generation. Wire report submission through `onSubmit` or the hosted helpers from the npm package.\n\n## Package\n\nThe npm package publishes:\n\n- `@dentsdumidi/chmln`: ESM SDK with TypeScript declarations\n- `@dentsdumidi/chmln/browser`: browser/CDN entry that attaches `window.Chameleon`\n\nBefore publishing, verify the package from Docker:\n\n```sh\nnpm run docker:pack\n```\n\nThe full `chameleon` package name is already taken on npm, so this package uses `@dentsdumidi/chmln`.\n\nReact bindings are intentionally not included in the first package. The core Web Component API is the stable surface; a React wrapper can be added as a thin package after the core API settles.\n\n## Core Shape\n\nThe model returns structured scenario JSON:\n\n```ts\n{\n  \"title\": \"Add dropdown next to action\",\n  \"summary\": \"User expected an adjacent dropdown for extra actions.\",\n  \"chatResponse\": \"I kept the original button and added a dropdown next to it. What still feels off?\",\n  \"scenarioType\": \"ui_improvement\",\n  \"components\": [\n    {\n      \"type\": \"pagePreview\",\n      \"operations\": [\n        {\n          \"type\": \"setStyle\",\n          \"target\": { \"role\": \"button\", \"text\": \"Vague action\" },\n          \"styles\": [{ \"property\": \"background-color\", \"value\": \"red\" }]\n        },\n        {\n          \"type\": \"insertAfter\",\n          \"target\": { \"role\": \"button\", \"text\": \"Vague action\" },\n          \"node\": {\n            \"type\": \"select\",\n            \"label\": \"More actions\",\n            \"options\": [\"Option 1\", \"Option 2\"],\n            \"styles\": [{ \"property\": \"margin-left\", \"value\": \"8px\" }]\n          }\n        }\n      ]\n    }\n  ],\n  \"acceptanceCriteria\": [\"The original button remains visible.\", \"The dropdown appears to its right.\"]\n}\n```\n\nThis keeps feedback visual and reviewable while staying safe for customer websites.\n\n## Trying Real Pages\n\nArbitrary production websites often block console-injected scripts with CSP. For real-page testing, use a Chrome extension content script. For customer adoption, use first-party install through the script/npm SDK so the host app intentionally allows Chameleon.\n","readmeFilename":"README.md","_rev":"1-addbfc66d517fee8accc398add26293b"}