AI-powered frontend editor widget — modify live web interfaces using natural language.
Renders a floating chat button on your page. Users type a natural-language command, the widget captures a screenshot, sends it to your backend, and applies the resulting code changes live.
npm install @patchedcodes/hackathon-widgetor
pnpm add @patchedcodes/hackathon-widgetimport { init } from "@patchedcodes/hackathon-widget";
init({
endpoint: "https://your-backend.com/api/command",
apiKey: "your-api-key",
});A floating button appears in the bottom-right corner of your page. Click it to open the chat panel, describe a visual change, and the widget handles the rest.
init() accepts a WidgetConfig object:
| Option | Type | Default | Description |
|---|---|---|---|
endpoint |
string |
(required) | Backend URL that receives command POST requests. |
apiKey |
string |
(required) | API key sent in the request body to authenticate with the backend. |
position |
"bottom-right" | "bottom-left" | "top-right" | "top-left" |
"bottom-right" |
Position of the floating widget button. |
theme |
"light" | "dark" |
"light" |
Widget color theme. |
headers |
Record<string, string> |
{} |
Custom headers sent with backend requests (e.g. auth tokens). |
onDeployReady |
(branch: string, previewUrl: string) => void |
— | Called when a deployment is ready, before the user clicks "Apply". |
onError |
(error: Error) => void |
— | Called when an error occurs. |
onOpen |
() => void |
— | Called when the widget panel is opened. |
onClose |
() => void |
— | Called when the widget panel is closed. |
init({
endpoint: "https://your-backend.com/api/command",
apiKey: "your-api-key",
onDeployReady: (branch, previewUrl) => {
console.log(`Deploy ready on branch ${branch}: ${previewUrl}`);
},
onError: (error) => {
console.error("Widget error:", error);
},
onOpen: () => console.log("Widget opened"),
onClose: () => console.log("Widget closed"),
});init() returns the underlying DevloyedWidget custom element, which exposes methods for programmatic control:
const widget = init({
endpoint: "https://your-backend.com/api/command",
apiKey: "your-api-key",
});
// Open, close, or toggle the chat panel
widget.open();
widget.close();
widget.toggle();The widget is a vanilla TypeScript Web Component (<devloyed-widget>) that renders inside a Shadow DOM. This means:
- Full style encapsulation — widget styles cannot leak into or be affected by the host page.
- Framework-agnostic — works with React, Vue, Svelte, plain HTML, or any other framework.
- Single bundle — ships as one ES module (
dist/devloyed-widget.js) with no external runtime dependencies beyondhtml2canvas(bundled).
- User opens the widget and types a natural-language command (e.g. "Make the header blue").
- The widget captures a screenshot of the page using
html2canvas. - A multi-step loader plays with randomized progress labels while the request is in flight.
- The command and API key are sent to your backend via a single
POSTrequest. - On response, the loader cascades to completion and the AI's response is shown in the chat.
- If the backend returns a
commitId, a deploy toast appears with an "Apply" button that reloads the page to pick up the changes.
The widget sends a POST request to your endpoint with the following JSON body:
interface CommandRequest {
apiKey: string; // The API key from config
prompt: string; // The user's natural-language command
}Your backend should return:
interface CommandResponse {
commitId: string; // The commit SHA that was pushed
transcript: string; // AI's explanation of what was changed
}The package exports cookie-based routing helpers for reverse-proxy branch switching. These are standalone utilities — not wired into the widget automatically — for consumers who want to implement branch preview routing.
import {
setRoutingCookie,
getRoutingCookie,
clearRoutingCookie,
isOnPreview,
} from "@patchedcodes/hackathon-widget";
// Set cookie to route traffic to a preview branch (reloads by default)
setRoutingCookie("feature/new-header");
// Check current branch
const branch = getRoutingCookie(); // "feature/new-header" or null
// Check if viewing a preview
if (isOnPreview()) {
// show "return to production" button
}
// Clear and return to production
clearRoutingCookie();Options can be passed to setRoutingCookie and clearRoutingCookie:
| Option | Type | Default | Description |
|---|---|---|---|
cookieName |
string |
"devloyed_branch" |
Cookie name. |
maxAge |
number |
3600 |
Cookie max-age in seconds. |
path |
string |
"/" |
Cookie path. |
reload |
boolean |
true |
Whether to reload the page after setting/clearing. |
# Start dev server with mock backend
npm run dev
# Or run them separately:
npm run dev:mock # Mock backend on port 3001
npm run dev:vite # Vite dev server
# Type-check
npm run typecheck
# Build
npm run buildThe mock server (dev/mock-server.mjs) simulates a ~10-second AI processing delay and returns fake commit/branch data for any command.
Types are shipped with the package — no separate @types/ install needed. You can import them directly:
import type { WidgetConfig } from "@patchedcodes/hackathon-widget";
import type { CommandRequest, CommandResponse } from "@patchedcodes/hackathon-widget";The package also exports DevloyedWidget and TransportClient classes for advanced usage.
MIT