npm package: @patchedcodes/hackathon-widget
Description: AI-powered frontend editor widget — modify live web interfaces using natural language
Latest version: 0.1.4

# @patchedcodes/hackathon-widget

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.

## Install

```bash
npm install @patchedcodes/hackathon-widget
```

or

```bash
pnpm add @patchedcodes/hackathon-widget
```

## Quick Start

```ts
import { 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.

## Configuration

`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. |

## Callbacks

```ts
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"),
});
```

## Programmatic Control

`init()` returns the underlying `DevloyedWidget` custom element, which exposes methods for programmatic control:

```ts
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();
```

## Architecture

The widget is a **vanilla TypeScript Web Component** (`<devloyed-widget>`) that renders inside a [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_Components/Using_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 beyond `html2canvas` (bundled).

### How It Works

1. User opens the widget and types a natural-language command (e.g. "Make the header blue").
2. The widget captures a screenshot of the page using `html2canvas`.
3. A multi-step loader plays with randomized progress labels while the request is in flight.
4. The command and API key are sent to your backend via a single `POST` request.
5. On response, the loader cascades to completion and the AI's response is shown in the chat.
6. If the backend returns a `commitId`, a deploy toast appears with an "Apply" button that reloads the page to pick up the changes.

### Backend Contract

The widget sends a `POST` request to your `endpoint` with the following JSON body:

```ts
interface CommandRequest {
  apiKey: string;   // The API key from config
  prompt: string;   // The user's natural-language command
}
```

Your backend should return:

```ts
interface CommandResponse {
  commitId: string;    // The commit SHA that was pushed
  transcript: string;  // AI's explanation of what was changed
}
```

## Routing Utilities

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.

```ts
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. |

## Development

```bash
# 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 build
```

The mock server (`dev/mock-server.mjs`) simulates a ~10-second AI processing delay and returns fake commit/branch data for any command.

## TypeScript

Types are shipped with the package — no separate `@types/` install needed. You can import them directly:

```ts
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.

## License

MIT