@popmelt.com/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +126 -0
- package/README.md +176 -0
- package/dist/index.d.mts +109 -0
- package/dist/index.mjs +12507 -0
- package/dist/server.d.mts +21 -0
- package/dist/server.mjs +1745 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Polyform Shield License 1.0.0
|
|
2
|
+
|
|
3
|
+
<https://polyformproject.org/licenses/shield/1.0.0>
|
|
4
|
+
|
|
5
|
+
## Acceptance
|
|
6
|
+
|
|
7
|
+
In order to get any license under these terms, you must agree to
|
|
8
|
+
them as both strict obligations and conditions to all your licenses.
|
|
9
|
+
|
|
10
|
+
## Copyright License
|
|
11
|
+
|
|
12
|
+
The licensor grants you a copyright license for the software to do
|
|
13
|
+
everything you might do with the software that would otherwise
|
|
14
|
+
infringe the licensor's copyright in it for any permitted purpose.
|
|
15
|
+
However, you may only distribute the software according to
|
|
16
|
+
[Distribution License](#distribution-license) and make changes or
|
|
17
|
+
new works based on the software according to [Changes and New Works
|
|
18
|
+
License](#changes-and-new-works-license).
|
|
19
|
+
|
|
20
|
+
## Distribution License
|
|
21
|
+
|
|
22
|
+
The licensor grants you an additional copyright license to distribute
|
|
23
|
+
copies of the software. Your license to distribute covers
|
|
24
|
+
distributing the software with changes and new works permitted by
|
|
25
|
+
[Changes and New Works License](#changes-and-new-works-license).
|
|
26
|
+
|
|
27
|
+
## Notices
|
|
28
|
+
|
|
29
|
+
You must ensure that anyone who gets a copy of any part of the
|
|
30
|
+
software from you also gets a copy of these terms or the URL above,
|
|
31
|
+
as well as copies of any plain-text lines beginning with
|
|
32
|
+
`Required Notice:` that the licensor provided with the software.
|
|
33
|
+
For example:
|
|
34
|
+
|
|
35
|
+
**Required Notice: Copyright Popmelt ([https://popmelt.com](https://popmelt.com))**
|
|
36
|
+
|
|
37
|
+
## Changes and New Works License
|
|
38
|
+
|
|
39
|
+
The licensor grants you an additional copyright license to make
|
|
40
|
+
changes and new works based on the software for any permitted
|
|
41
|
+
purpose.
|
|
42
|
+
|
|
43
|
+
## Patent License
|
|
44
|
+
|
|
45
|
+
The licensor grants you a patent license for the software that
|
|
46
|
+
covers patent claims the licensor can license, or becomes able to
|
|
47
|
+
license, that you would infringe by using the software.
|
|
48
|
+
|
|
49
|
+
## Noncompete
|
|
50
|
+
|
|
51
|
+
Any purpose is a permitted purpose, except for providing any product
|
|
52
|
+
that competes with the licensor's product. If you are not sure
|
|
53
|
+
whether your use qualifies, contact the licensor.
|
|
54
|
+
|
|
55
|
+
**Licensor's Product: Agentic Design Collaboration Tools ([https://popmelt.com](https://popmelt.com))**
|
|
56
|
+
|
|
57
|
+
## Personal Uses
|
|
58
|
+
|
|
59
|
+
Personal use for research, experiment, and testing for the benefit
|
|
60
|
+
of public knowledge, personal study, private entertainment, hobby
|
|
61
|
+
projects, amateur pursuits, or religious observance, without any
|
|
62
|
+
anticipated commercial application, is always a permitted purpose.
|
|
63
|
+
|
|
64
|
+
## Noncommercial Organizations
|
|
65
|
+
|
|
66
|
+
Use by any charitable organization, educational institution,
|
|
67
|
+
public research organization, public safety or health organization,
|
|
68
|
+
environmental protection organization, or government institution
|
|
69
|
+
is always a permitted purpose regardless of the source of funding or
|
|
70
|
+
obligations resulting from the funding.
|
|
71
|
+
|
|
72
|
+
## Fair Use
|
|
73
|
+
|
|
74
|
+
You may have "fair use" rights for the software under the law.
|
|
75
|
+
These terms do not limit them.
|
|
76
|
+
|
|
77
|
+
## No Other Rights
|
|
78
|
+
|
|
79
|
+
These terms do not allow you to sublicense or transfer any of your
|
|
80
|
+
licenses to anyone else, or prevent the licensor from granting
|
|
81
|
+
licenses to anyone else. These terms do not imply any other
|
|
82
|
+
licenses.
|
|
83
|
+
|
|
84
|
+
## Patent Defense
|
|
85
|
+
|
|
86
|
+
If you make any written claim that the software infringes or
|
|
87
|
+
contributes to infringement of any patent, your patent license for
|
|
88
|
+
the software granted under these terms ends immediately. If your
|
|
89
|
+
company makes such a claim, your patent license ends immediately for
|
|
90
|
+
work on behalf of your company.
|
|
91
|
+
|
|
92
|
+
## Violations
|
|
93
|
+
|
|
94
|
+
The first time you are notified in writing that you have violated
|
|
95
|
+
any of these terms, or any agreement made under them, you can keep
|
|
96
|
+
your licenses by taking all practical steps to comply within 30 days
|
|
97
|
+
after the notice. If you do not do so, your licenses end immediately.
|
|
98
|
+
|
|
99
|
+
## No Liability
|
|
100
|
+
|
|
101
|
+
***As far as the law allows, the software comes as is, without any
|
|
102
|
+
warranty or condition, and the licensor will not be liable to you for
|
|
103
|
+
any damages arising out of these terms or the use or nature of the
|
|
104
|
+
software, under any kind of legal claim.***
|
|
105
|
+
|
|
106
|
+
## Definitions
|
|
107
|
+
|
|
108
|
+
The **licensor** is the entity offering these terms, and the
|
|
109
|
+
**software** is the software the licensor makes available under these
|
|
110
|
+
terms.
|
|
111
|
+
|
|
112
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
113
|
+
|
|
114
|
+
**Your company** is any legal entity, sole proprietorship, or other
|
|
115
|
+
kind of organization that you work for, plus all organizations that
|
|
116
|
+
have control over, are under the control of, or are under common
|
|
117
|
+
control with that organization. **Control** means ownership of
|
|
118
|
+
substantially all the assets of an entity, or the power to direct
|
|
119
|
+
its management and policies by vote, contract, or otherwise. Control
|
|
120
|
+
can be direct or indirect.
|
|
121
|
+
|
|
122
|
+
**Your licenses** are all the licenses granted to you for the
|
|
123
|
+
software under these terms.
|
|
124
|
+
|
|
125
|
+
**Use** means anything you do with the software requiring one of
|
|
126
|
+
your licenses.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="src/assets/bar - popmelt.png" alt="Comment and zhuzh, then hand off." width="360" style="border-radius: 12px;" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Popmelt
|
|
6
|
+
|
|
7
|
+
## What is it?
|
|
8
|
+
|
|
9
|
+
Popmelt is a design collaboration layer for AI models like Codex or Claude Code. It combines the best parts of collaborative design tools like Figma with the best way to design products today: in code, with AI, right in your browser.
|
|
10
|
+
|
|
11
|
+
It's a good fit for anyone involved in UI Design and Engineering for the web: it doesn't require deep technical expertise to use, and it won't get in your way if you *do* have that knowledge and want to use it.
|
|
12
|
+
|
|
13
|
+
Drop it into any React codebase and get a full design-feedback loop: draw on your running UI, pin feedback to elements, adjust style and layout directly, and give your AI the visual and technical context it needs to execute your vision in a keystroke.
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<img src="src/assets/annotations.jpg" alt="Popmelt annotations on a running app" width="720" style="border-radius: 6px;" />
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
**Popmelt is free to use and completely local**. It runs inside your codebase, with your existing AI CLI tools ([Claude Code](https://code.claude.com/docs/en/cli-reference), [Codex](https://developers.openai.com/codex/cli/)) handling code changes behind the scenes. You don't need an account to use it and we never see your data.
|
|
20
|
+
|
|
21
|
+
## Why does it exist?
|
|
22
|
+
|
|
23
|
+
We're experienced product engineers and early adopters of AI coding models. We know their strengths, we know their weaknesses, and we've learned how to squeeze the best performance out of each generation. Popmelt was built to streamline our way of working, and we're proud to make it available to the design and engineering community.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## How do I set it up?
|
|
27
|
+
|
|
28
|
+
If you're a human, we recommend asking your AI to handle installation for you. We cover the basics below, but your AI should be able to integrate it into whatever setup you throw at it as long as it supports Node and React.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @popmelt.com/core
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Peer dependencies: `react >=18`, `react-dom >=18`, `lucide-react >=0.400` (toolbar icons).
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Frontend
|
|
38
|
+
|
|
39
|
+
Wrap your app in `PopmeltProvider`. In development, double-tap Cmd/Ctrl to open the toolbar.
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { PopmeltProvider } from '@popmelt.com/core';
|
|
43
|
+
|
|
44
|
+
export default function App() {
|
|
45
|
+
return (
|
|
46
|
+
<PopmeltProvider>
|
|
47
|
+
{/* your app */}
|
|
48
|
+
</PopmeltProvider>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Backend
|
|
54
|
+
|
|
55
|
+
Start the bridge server so Popmelt can talk to Claude/Codex. In Next.js, `instrumentation.ts` is the cleanest place:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// instrumentation.ts (Next.js)
|
|
59
|
+
export async function register() {
|
|
60
|
+
if (process.env.NODE_ENV === 'development' && process.env.NEXT_RUNTIME === 'nodejs') {
|
|
61
|
+
const { startPopmelt } = await import('@popmelt.com/core/server');
|
|
62
|
+
await startPopmelt({ port: 1111 });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For other frameworks, call `startPopmelt()` anywhere in your dev server startup.
|
|
68
|
+
|
|
69
|
+
### That's it
|
|
70
|
+
|
|
71
|
+
Open your app in the browser and double-tap Cmd (or Ctrl) to toggle the toolbar. Draw, type, point at things, hit Cmd+Enter. Your AI sees your annotated screenshot and code context and gets to work.
|
|
72
|
+
|
|
73
|
+
## How do I use it?
|
|
74
|
+
|
|
75
|
+
### Annotation tools
|
|
76
|
+
|
|
77
|
+
| Tool | Shortcut | What it does |
|
|
78
|
+
|------|----------|-------------|
|
|
79
|
+
| **Comment** | `C` | Click any element to pin a comment. Captures tag, classes, React component name, and ancestor context. |
|
|
80
|
+
| **Handle** | `H` | Drag padding, gap, border-radius, font-size, and line-height handles directly on elements. Shift to snap to a scale. |
|
|
81
|
+
| **Rectangle** | `R` | Draw a rectangle to highlight a region. Auto-prompts for a text label. |
|
|
82
|
+
| **Oval** | `O` | Draw an ellipse. |
|
|
83
|
+
| **Line** | `L` | Draw a straight line. |
|
|
84
|
+
| **Pen** | `P` | Freehand drawing. |
|
|
85
|
+
| **Text** | `T` | Click to place a text label anywhere. |
|
|
86
|
+
|
|
87
|
+
<p align="center">
|
|
88
|
+
<img src="src/assets/bar - comment.png" alt="Comment tool guidance" width="360" style="border-radius: 12px;" />
|
|
89
|
+
<img src="src/assets/bar - rectangle.png" alt="Rectangle tool guidance" width="360" style="border-radius: 12px;" />
|
|
90
|
+
<img src="src/assets/bar - text.png" alt="Text tool guidance" width="360" style="border-radius: 12px;" />
|
|
91
|
+
</p>
|
|
92
|
+
|
|
93
|
+
### Handle tool
|
|
94
|
+
|
|
95
|
+
Switch to the Handle tool (`H`) and hover any element to see draggable handles for its spatial properties:
|
|
96
|
+
|
|
97
|
+
- **Padding** — drag the inner edges of any element to adjust padding per-side. Hold Shift to snap to a scale (0, 2, 4, 8, 12, 16, 20, 24, 32).
|
|
98
|
+
- **Gap** — drag between flex or grid children to adjust row/column gap.
|
|
99
|
+
- **Border radius** — drag element corners to round them.
|
|
100
|
+
- **Font size** — drag the right edge of a text element to resize.
|
|
101
|
+
- **Line height** — drag below a text element to adjust leading.
|
|
102
|
+
|
|
103
|
+
All changes apply as inline styles instantly. Hold Cmd/Alt and swipe on a flex container to cycle `justify-content` or `flex-direction`; hold Shift and swipe to cycle `align-items`. Cmd+Z / Cmd+Shift+Z to undo/redo any change.
|
|
104
|
+
|
|
105
|
+
<p align="center">
|
|
106
|
+
<img src="src/assets/bar - handle.png" alt="Handle tool guidance" width="360" style="border-radius: 12px;" />
|
|
107
|
+
</p>
|
|
108
|
+
|
|
109
|
+
### Style panel
|
|
110
|
+
|
|
111
|
+
Right-click any element with the Comment tool to open the style panel. Edit layout (flex/grid direction, alignment, gap, sizing), typography (size, weight, line-height, letter-spacing, color), backgrounds, borders, and effects. Every modification is tracked and included in the feedback sent to your AI.
|
|
112
|
+
|
|
113
|
+
### AI Collaboration
|
|
114
|
+
|
|
115
|
+
Cmd+Enter captures a full-page screenshot with your annotations baked in, bundles it with structured feedback (element selectors, style diffs, annotation text), and sends it to Claude or Codex via a local bridge server. Your AI reads the screenshot, sees exactly what you marked up, and edits your code. Cmd+C copies the screenshot to your clipboard instead.
|
|
116
|
+
|
|
117
|
+
- **Threaded conversations** — follow-up annotations on the same element continue the existing thread. Your AI sees prior context without re-explaining.
|
|
118
|
+
- **Questions** — if your AI needs clarification, it asks. A badge appears on the annotation; reply inline and the conversation continues.
|
|
119
|
+
- **Multi-task plans** — prefix your annotation with `/plan` and your AI decomposes the work into spatial tasks, each pinned to a region of the UI. Approve and they execute in sequence.
|
|
120
|
+
- **Provider switching** — toggle between Claude (Opus/Sonnet) and Codex at any time. Popmelt handles both.
|
|
121
|
+
|
|
122
|
+
<p align="center">
|
|
123
|
+
<img src="src/assets/bar - model.png" alt="Model switcher guidance" width="360" style="border-radius: 12px;" />
|
|
124
|
+
</p>
|
|
125
|
+
|
|
126
|
+
### Persistence
|
|
127
|
+
|
|
128
|
+
Annotations and style modifications save to localStorage automatically. Cmd+Backspace clears unsent annotations and modifications.
|
|
129
|
+
|
|
130
|
+
Thread history persists to `.popmelt/threads.json` in your project root for cross-session continuity.
|
|
131
|
+
|
|
132
|
+
## API
|
|
133
|
+
|
|
134
|
+
### `PopmeltProvider`
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<PopmeltProvider
|
|
138
|
+
enabled={true} // default: process.env.NODE_ENV === 'development'
|
|
139
|
+
bridgeUrl="http://localhost:1111" // default
|
|
140
|
+
>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### `startPopmelt(options?)`
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
await startPopmelt({
|
|
147
|
+
port: 1111, // bridge server port (default: 1111)
|
|
148
|
+
projectRoot: '.', // working directory for your AI
|
|
149
|
+
claudePath: 'claude', // path to Claude CLI binary
|
|
150
|
+
maxTurns: 10, // max turns per job
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Returns `{ port: number, close: () => Promise<void> }`.
|
|
155
|
+
|
|
156
|
+
### `usePopmelt()`
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const { isEnabled } = usePopmelt();
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Requirements
|
|
163
|
+
|
|
164
|
+
- React 18+
|
|
165
|
+
- Node.js 18+ (server)
|
|
166
|
+
- Claude CLI or Codex CLI installed for AI integration
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
[PolyForm Shield 1.0.0](./LICENSE)
|
|
171
|
+
|
|
172
|
+
**tl;dr** you can use and extend this software freely for yourself and your team. You may not sell it, offer it as a managed service, or take our code and create a competing AI design collaboration product/service with it. The software is offered as-is, and you're responsible for its use in your projects.
|
|
173
|
+
|
|
174
|
+
**If you need a custom license** for your use case, contact [reb@popmelt.com](mailto:reb@popmelt.com) with a brief outline of your desired terms.
|
|
175
|
+
|
|
176
|
+
<img src="src/assets/popmelt-logo.svg" alt="Comment and zhuzh, then hand off." width="64" />
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
|
+
|
|
4
|
+
type PopmeltContextValue = {
|
|
5
|
+
isEnabled: boolean;
|
|
6
|
+
};
|
|
7
|
+
type PopmeltProviderProps = PropsWithChildren<{
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
bridgeUrl?: string;
|
|
10
|
+
}>;
|
|
11
|
+
declare function PopmeltProvider({ children, enabled, bridgeUrl, }: PopmeltProviderProps): react.JSX.Element;
|
|
12
|
+
declare function usePopmelt(): PopmeltContextValue;
|
|
13
|
+
|
|
14
|
+
type AnnotationLifecycleStatus = 'pending' | 'in_flight' | 'resolved' | 'needs_review' | 'dismissed' | 'waiting_input';
|
|
15
|
+
type ToolType = 'freehand' | 'line' | 'rectangle' | 'circle' | 'text' | 'inspector' | 'hand';
|
|
16
|
+
type Point = {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
};
|
|
20
|
+
type ElementInfo = {
|
|
21
|
+
selector: string;
|
|
22
|
+
tagName: string;
|
|
23
|
+
id?: string;
|
|
24
|
+
className?: string;
|
|
25
|
+
textContent?: string;
|
|
26
|
+
dataAttributes?: Record<string, string>;
|
|
27
|
+
reactComponent?: string;
|
|
28
|
+
context?: string;
|
|
29
|
+
};
|
|
30
|
+
type StyleChange = {
|
|
31
|
+
property: string;
|
|
32
|
+
original: string;
|
|
33
|
+
modified: string;
|
|
34
|
+
};
|
|
35
|
+
type StyleModification = {
|
|
36
|
+
selector: string;
|
|
37
|
+
durableSelector?: string;
|
|
38
|
+
element: ElementInfo;
|
|
39
|
+
changes: StyleChange[];
|
|
40
|
+
captured?: boolean;
|
|
41
|
+
};
|
|
42
|
+
type Annotation = {
|
|
43
|
+
id: string;
|
|
44
|
+
type: ToolType;
|
|
45
|
+
points: Point[];
|
|
46
|
+
color: string;
|
|
47
|
+
strokeWidth: number;
|
|
48
|
+
text?: string;
|
|
49
|
+
fontSize?: number;
|
|
50
|
+
timestamp: number;
|
|
51
|
+
groupId?: string;
|
|
52
|
+
captured?: boolean;
|
|
53
|
+
status?: AnnotationLifecycleStatus;
|
|
54
|
+
question?: string;
|
|
55
|
+
resolutionSummary?: string;
|
|
56
|
+
replyCount?: number;
|
|
57
|
+
threadId?: string;
|
|
58
|
+
elements?: ElementInfo[];
|
|
59
|
+
linkedSelector?: string;
|
|
60
|
+
linkedAnchor?: 'top-left' | 'bottom-left';
|
|
61
|
+
planId?: string;
|
|
62
|
+
planTaskId?: string;
|
|
63
|
+
};
|
|
64
|
+
type BridgeStatus = {
|
|
65
|
+
ok: boolean;
|
|
66
|
+
activeJob: {
|
|
67
|
+
id: string;
|
|
68
|
+
status: string;
|
|
69
|
+
} | null;
|
|
70
|
+
queueDepth: number;
|
|
71
|
+
sessionId: string | null;
|
|
72
|
+
};
|
|
73
|
+
type BridgeEvent = {
|
|
74
|
+
type: 'job_started' | 'delta' | 'tool_use' | 'done' | 'error';
|
|
75
|
+
data: Record<string, unknown>;
|
|
76
|
+
timestamp: number;
|
|
77
|
+
};
|
|
78
|
+
type ClaudeResponse = {
|
|
79
|
+
jobId: string;
|
|
80
|
+
sessionId?: string;
|
|
81
|
+
text: string;
|
|
82
|
+
success: boolean;
|
|
83
|
+
toolsUsed: string[];
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
type AnnotationData = {
|
|
87
|
+
id: string;
|
|
88
|
+
type: string;
|
|
89
|
+
instruction?: string;
|
|
90
|
+
linkedSelector?: string;
|
|
91
|
+
elements: ElementInfo[];
|
|
92
|
+
};
|
|
93
|
+
type FeedbackData = {
|
|
94
|
+
timestamp: string;
|
|
95
|
+
url: string;
|
|
96
|
+
viewport: {
|
|
97
|
+
width: number;
|
|
98
|
+
height: number;
|
|
99
|
+
};
|
|
100
|
+
scrollPosition: {
|
|
101
|
+
x: number;
|
|
102
|
+
y: number;
|
|
103
|
+
};
|
|
104
|
+
annotations: AnnotationData[];
|
|
105
|
+
styleModifications: StyleModification[];
|
|
106
|
+
inspectedElement?: ElementInfo;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export { type Annotation, type BridgeEvent, type BridgeStatus, type ClaudeResponse, type ElementInfo, type FeedbackData, type Point, PopmeltProvider, type StyleChange, type StyleModification, type ToolType, usePopmelt };
|