@dentsdumidi/chmln
v0.1.0
Published
Embeddable product feedback widget that turns user wishes into safe UI previews.
Downloads
109
Maintainers
Readme
Chameleon
Chameleon helps users show what they expected your product to do.
Instead 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.
Chameleon 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.
What It Does
- captures safe page context from the current page
- lets users chat with an AI model about what they expected
- keeps conversation state per feedback journey
- renders a temporary preview using structured operations
- exports a report for product review
Supported preview operations:
setTextsetStyleinsertAfterinsertBeforereplaceremove
Chameleon can update existing page elements and safely insert common preview primitives:
buttonselectinputtextareacheckboxradiolinkimagetextbadgelistcardsectionformmodaltabletabstoolbar
No raw HTML. No generated JavaScript. No production DOM mutation.
Docker
docker compose up --buildDashboard: http://localhost:8080
Demo: http://localhost:8080/demo/
For the local demo-only OpenAI path:
CHAMELEON_OPENAI_API_KEY=sk-... docker compose up --buildThe local direct-OpenAI demo keeps response state in memory per journey. It resets on refresh or rebuild.
Hosted Backend
The hosted MVP lives in supabase/.
import { createCloudProposalGenerator, createCloudReportSubmitter, mountChameleon } from "@dentsdumidi/chmln";
const cloud = {
functionsUrl: "https://PROJECT.supabase.co/functions/v1",
projectId: "PROJECT_ID",
anonKey: "SUPABASE_ANON_KEY"
};
mountChameleon({
generateProposal: createCloudProposalGenerator(cloud),
onSubmit: createCloudReportSubmitter(cloud)
});Deploy 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.
Local SDK
npm install @dentsdumidi/chmlnimport { createOpenAIProposalGenerator, mountChameleon } from "@dentsdumidi/chmln";
mountChameleon({
generateProposal: createOpenAIProposalGenerator({
apiKey: "demo-openai-api-key"
}),
onSubmit(report) {
console.log(report);
}
});Do not put a private LLM provider key in a public page. Use the hosted/backend path for production.
Browser CDN
The browser entry exposes window.Chameleon:
<script type="module">
import "https://esm.sh/@dentsdumidi/chmln/browser";
window.Chameleon.init({
projectId: "PROJECT_ID",
endpoint: "https://PROJECT.supabase.co/functions/v1/chameleon-propose"
});
</script>init is for proposal generation. Wire report submission through onSubmit or the hosted helpers from the npm package.
Package
The npm package publishes:
@dentsdumidi/chmln: ESM SDK with TypeScript declarations@dentsdumidi/chmln/browser: browser/CDN entry that attacheswindow.Chameleon
Before publishing, verify the package from Docker:
npm run docker:packThe full chameleon package name is already taken on npm, so this package uses @dentsdumidi/chmln.
React 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.
Core Shape
The model returns structured scenario JSON:
{
"title": "Add dropdown next to action",
"summary": "User expected an adjacent dropdown for extra actions.",
"chatResponse": "I kept the original button and added a dropdown next to it. What still feels off?",
"scenarioType": "ui_improvement",
"components": [
{
"type": "pagePreview",
"operations": [
{
"type": "setStyle",
"target": { "role": "button", "text": "Vague action" },
"styles": [{ "property": "background-color", "value": "red" }]
},
{
"type": "insertAfter",
"target": { "role": "button", "text": "Vague action" },
"node": {
"type": "select",
"label": "More actions",
"options": ["Option 1", "Option 2"],
"styles": [{ "property": "margin-left", "value": "8px" }]
}
}
]
}
],
"acceptanceCriteria": ["The original button remains visible.", "The dropdown appears to its right."]
}This keeps feedback visual and reviewable while staying safe for customer websites.
Trying Real Pages
Arbitrary 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.
