modifywithai 1.2.4 → 1.4.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/AGENTS.md +168 -0
- package/dist/index.d.ts +17 -37
- package/dist/index.js +1 -1
- package/package.json +1 -2
package/AGENTS.md
CHANGED
|
@@ -128,6 +128,170 @@ Run the following command to add the API key to `.env.local`:
|
|
|
128
128
|
echo "MWAI_API_KEY={{API_KEY}}" >> .env.local
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
## Step 5: Add "Modify With AI" Button
|
|
132
|
+
|
|
133
|
+
Create a "Modify With AI" button in an appropriate location in the application. This button allows end-users to submit modification requests.
|
|
134
|
+
|
|
135
|
+
Choose a suitable location based on the app's structure. Common placements include:
|
|
136
|
+
- Header/navbar (recommended for most apps)
|
|
137
|
+
- Settings page
|
|
138
|
+
- Admin dashboard
|
|
139
|
+
- Floating action button
|
|
140
|
+
- Footer
|
|
141
|
+
|
|
142
|
+
### Example Implementation
|
|
143
|
+
|
|
144
|
+
Create a client component for the button:
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
"use client"
|
|
148
|
+
|
|
149
|
+
import { useState } from "react"
|
|
150
|
+
import { modifyWithAI } from "modifywithai"
|
|
151
|
+
|
|
152
|
+
export function ModifyWithAIButton() {
|
|
153
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
154
|
+
const [prompt, setPrompt] = useState("")
|
|
155
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
156
|
+
|
|
157
|
+
const handleSubmit = async () => {
|
|
158
|
+
if (!prompt.trim()) return
|
|
159
|
+
|
|
160
|
+
setIsLoading(true)
|
|
161
|
+
const { success, error } = await modifyWithAI(prompt)
|
|
162
|
+
setIsLoading(false)
|
|
163
|
+
|
|
164
|
+
if (success) {
|
|
165
|
+
setPrompt("")
|
|
166
|
+
setIsOpen(false)
|
|
167
|
+
// Optionally show a success toast/notification
|
|
168
|
+
} else {
|
|
169
|
+
// Optionally show an error toast/notification
|
|
170
|
+
console.error(error)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!isOpen) {
|
|
175
|
+
return (
|
|
176
|
+
<button onClick={() => setIsOpen(true)}>
|
|
177
|
+
Modify With AI
|
|
178
|
+
</button>
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<div>
|
|
184
|
+
<textarea
|
|
185
|
+
value={prompt}
|
|
186
|
+
onChange={(e) => setPrompt(e.target.value)}
|
|
187
|
+
placeholder="Describe the changes you want to make..."
|
|
188
|
+
disabled={isLoading}
|
|
189
|
+
/>
|
|
190
|
+
<button onClick={handleSubmit} disabled={isLoading || !prompt.trim()}>
|
|
191
|
+
{isLoading ? "Submitting..." : "Submit"}
|
|
192
|
+
</button>
|
|
193
|
+
<button onClick={() => setIsOpen(false)} disabled={isLoading}>
|
|
194
|
+
Cancel
|
|
195
|
+
</button>
|
|
196
|
+
</div>
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Styling Requirements
|
|
202
|
+
|
|
203
|
+
**Important:** The example above is a minimal reference implementation. You MUST:
|
|
204
|
+
|
|
205
|
+
1. **Match existing button styles** - Look at other buttons in the location you're placing this (e.g., the header/navbar) and match their styling exactly (size, colors, border-radius, font, hover states, etc.)
|
|
206
|
+
2. **Use the project's UI library** - If the project uses shadcn/ui, Radix, Chakra, MUI, Ant Design, or any other component library, use their Button, Dialog/Modal, Popover, Input/Textarea, and other relevant components
|
|
207
|
+
3. **Follow the design system** - Use the project's existing CSS variables, Tailwind classes, or styled-components patterns
|
|
208
|
+
|
|
209
|
+
The button should look like it belongs in the app, not like a foreign element.
|
|
210
|
+
|
|
211
|
+
**After completing all setup steps, ask the user:** "I've placed the 'Modify With AI' button in [location]. Would you like me to move it somewhere else?"
|
|
212
|
+
|
|
213
|
+
## Step 6: Add `data-mwai-id` Attributes (VERY IMPORTANT)
|
|
214
|
+
|
|
215
|
+
**This step is critical for ModifyWithAI to function properly.**
|
|
216
|
+
|
|
217
|
+
ModifyWithAI uses `data-mwai-id` attributes to identify which elements in the UI can be modified. Without these attributes, the AI cannot target specific elements for modification.
|
|
218
|
+
|
|
219
|
+
### How to Add IDs
|
|
220
|
+
|
|
221
|
+
Add a `data-mwai-id` attribute to **every single element** in the codebase that represents a meaningful UI component or section. The ID should be descriptive and based on the element's purpose/context.
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
// Examples:
|
|
225
|
+
<header data-mwai-id="main-header">...</header>
|
|
226
|
+
<nav data-mwai-id="primary-navigation">...</nav>
|
|
227
|
+
<section data-mwai-id="hero-section">...</section>
|
|
228
|
+
<div data-mwai-id="pricing-card-pro">...</div>
|
|
229
|
+
<button data-mwai-id="submit-contact-form">Submit</button>
|
|
230
|
+
<h1 data-mwai-id="page-title">Welcome</h1>
|
|
231
|
+
<p data-mwai-id="feature-description">...</p>
|
|
232
|
+
<img data-mwai-id="team-member-photo-jane" src="..." />
|
|
233
|
+
<footer data-mwai-id="site-footer">...</footer>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Guidelines for Naming IDs
|
|
237
|
+
|
|
238
|
+
1. **Be descriptive**: Use names that clearly describe what the element is or does
|
|
239
|
+
2. **Use kebab-case**: Separate words with hyphens (e.g., `hero-section`, `contact-form`)
|
|
240
|
+
3. **Include context**: If there are multiple similar elements, include distinguishing context (e.g., `pricing-card-basic`, `pricing-card-pro`, `pricing-card-enterprise`)
|
|
241
|
+
4. **Cover all elements**: Add IDs to headings, paragraphs, buttons, images, sections, cards, forms, inputs, navigation items, etc.
|
|
242
|
+
|
|
243
|
+
### What to Cover
|
|
244
|
+
|
|
245
|
+
Go through **every page and component** in the project and add `data-mwai-id` to:
|
|
246
|
+
|
|
247
|
+
- Layout components (headers, footers, sidebars, navigation)
|
|
248
|
+
- Page sections (hero, features, testimonials, pricing, FAQ, CTA)
|
|
249
|
+
- Interactive elements (buttons, links, form inputs)
|
|
250
|
+
- Content elements (headings, paragraphs, images, icons)
|
|
251
|
+
- Cards and list items
|
|
252
|
+
- Modal/dialog content
|
|
253
|
+
- Any other visible UI element
|
|
254
|
+
|
|
255
|
+
**The more elements you tag, the more precisely ModifyWithAI can make targeted modifications.**
|
|
256
|
+
|
|
257
|
+
### Persist the Rule for Future Development
|
|
258
|
+
|
|
259
|
+
To ensure all future elements created by AI assistants also include `data-mwai-id` attributes, add instructions to the appropriate file based on the IDE being used:
|
|
260
|
+
|
|
261
|
+
**If using Claude Code IDE**, append to `CLAUDE.md` (create if it doesn't exist):
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
echo '
|
|
265
|
+
## ModifyWithAI Integration
|
|
266
|
+
When creating or modifying React/JSX elements, ALWAYS add a `data-mwai-id` attribute with a descriptive kebab-case identifier. This is required for ModifyWithAI to identify and modify elements. Example: `<section data-mwai-id="hero-section">...</section>`
|
|
267
|
+
' >> CLAUDE.md
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**If using Cursor IDE**, create a rule file at `.cursor/rules/mwai.mdc`:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
mkdir -p .cursor/rules && cat > .cursor/rules/mwai.mdc << 'EOF'
|
|
274
|
+
---
|
|
275
|
+
description: ModifyWithAI element identification
|
|
276
|
+
globs: ["**/*.tsx", "**/*.jsx"]
|
|
277
|
+
alwaysApply: true
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
When creating or modifying React/JSX elements, ALWAYS add a `data-mwai-id` attribute with a descriptive kebab-case identifier. This is required for ModifyWithAI to identify and modify elements.
|
|
281
|
+
|
|
282
|
+
Example: `<section data-mwai-id="hero-section">...</section>`
|
|
283
|
+
EOF
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**For other IDEs or general use**, append to `AGENTS.md`:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
echo '
|
|
290
|
+
## ModifyWithAI Element IDs
|
|
291
|
+
When creating or modifying React/JSX elements, ALWAYS add a `data-mwai-id` attribute with a descriptive kebab-case identifier. This is required for ModifyWithAI to identify and modify elements. Example: `<section data-mwai-id="hero-section">...</section>`
|
|
292
|
+
' >> AGENTS.md
|
|
293
|
+
```
|
|
294
|
+
|
|
131
295
|
## Verification Checklist
|
|
132
296
|
|
|
133
297
|
After completing the setup, verify:
|
|
@@ -139,4 +303,8 @@ After completing the setup, verify:
|
|
|
139
303
|
- [ ] `app/api/mwai/api/[path]/route.ts` exists and exports HTTP method handlers
|
|
140
304
|
- [ ] `app/api/mwai/shims/[path]/route.ts` exists and re-exports from `"modifywithai/nextjs/shims"`
|
|
141
305
|
- [ ] `MWAI_API_KEY` is set in environment variables
|
|
306
|
+
- [ ] "Modify With AI" button component is created and placed in an appropriate location
|
|
307
|
+
- [ ] `data-mwai-id` attributes are added to all meaningful UI elements across the codebase
|
|
308
|
+
- [ ] AI assistant instructions are configured to add `data-mwai-id` to new elements (CLAUDE.md, .cursor/rules, or AGENTS.md)
|
|
309
|
+
- [ ] User has been asked if they want the "Modify With AI" button moved to a different location
|
|
142
310
|
|
package/dist/index.d.ts
CHANGED
|
@@ -17,44 +17,24 @@ declare const MWAIProvider: ({
|
|
|
17
17
|
children: ReactNode;
|
|
18
18
|
}) => react_jsx_runtime0.JSX.Element;
|
|
19
19
|
//#endregion
|
|
20
|
-
//#region src/popover.d.ts
|
|
21
|
-
type ModificationPopoverProps = {
|
|
22
|
-
/** Text for the trigger button (defaults to "Modify With AI") */
|
|
23
|
-
children?: ReactNode;
|
|
24
|
-
/** Called when modification is submitted successfully */
|
|
25
|
-
onSuccess?: () => void;
|
|
26
|
-
/** Called when modification submission fails */
|
|
27
|
-
onError?: (error: Error) => void;
|
|
28
|
-
/** Custom title for the popover */
|
|
29
|
-
title?: string;
|
|
30
|
-
/** Custom description for the popover */
|
|
31
|
-
description?: string;
|
|
32
|
-
/** Custom placeholder for the textarea */
|
|
33
|
-
placeholder?: string;
|
|
34
|
-
/** Custom submit button text */
|
|
35
|
-
submitText?: string;
|
|
36
|
-
/** Custom loading text */
|
|
37
|
-
loadingText?: string;
|
|
38
|
-
/** Popover side positioning */
|
|
39
|
-
side?: "top" | "right" | "bottom" | "left";
|
|
40
|
-
/** Popover alignment */
|
|
41
|
-
align?: "start" | "center" | "end";
|
|
42
|
-
};
|
|
43
|
-
declare function MWAIButton({
|
|
44
|
-
children,
|
|
45
|
-
onSuccess,
|
|
46
|
-
onError,
|
|
47
|
-
title,
|
|
48
|
-
description,
|
|
49
|
-
placeholder,
|
|
50
|
-
submitText,
|
|
51
|
-
loadingText,
|
|
52
|
-
side,
|
|
53
|
-
align
|
|
54
|
-
}: ModificationPopoverProps): react_jsx_runtime0.JSX.Element;
|
|
55
|
-
//#endregion
|
|
56
20
|
//#region src/hook.d.ts
|
|
57
21
|
declare const useMWAIComponents: () => react_jsx_runtime0.JSX.Element | null;
|
|
58
22
|
declare const MWAIComponents: () => react_jsx_runtime0.JSX.Element | null;
|
|
59
23
|
//#endregion
|
|
60
|
-
|
|
24
|
+
//#region src/modify.d.ts
|
|
25
|
+
type ModifyWithAIOptions = {
|
|
26
|
+
/** Called when modification submission fails */
|
|
27
|
+
onError?: (error: Error) => void;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Submit a modification request to ModifyWithAI
|
|
31
|
+
* @param prompt - The modification prompt describing the changes to make
|
|
32
|
+
* @param options - Optional callbacks for success and error handling
|
|
33
|
+
* @returns Promise that resolves when the modification is submitted
|
|
34
|
+
*/
|
|
35
|
+
declare function modifyWithAI(prompt: string, options?: ModifyWithAIOptions): Promise<{
|
|
36
|
+
success: boolean;
|
|
37
|
+
error?: Error;
|
|
38
|
+
}>;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { MWAIComponents, MWAIHead, MWAIProvider, type ModifyWithAIOptions, modifyWithAI, useMWAIComponents };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import*as e from"react/jsx-runtime";import{Fragment as t,jsx as n
|
|
1
|
+
"use client";import*as e from"react/jsx-runtime";import{Fragment as t,jsx as n}from"react/jsx-runtime";import*as r from"react";import{createContext as i,useContext as a,useLayoutEffect as o,useState as s}from"react";import*as c from"react-dom";import*as l from"react-dom/client";import{createFetch as u,createSchema as d}from"@better-fetch/fetch";import{z as f}from"zod";import{logger as p}from"@better-fetch/logger";const m=({basePath:e=`/api/mwai`}={})=>n(`script`,{type:`importmap`,dangerouslySetInnerHTML:{__html:JSON.stringify({imports:{react:`${e}/shims/react-shim.js`,"react/jsx-runtime":`${e}/shims/react-jsx-shim.js`,"react-dom":`${e}/shims/react-dom-shim.js`,"react-dom/client":`${e}/shims/react-dom-client-shim.js`}})}}),h=i(null),g=({id:e,children:t})=>n(h.Provider,{value:e,children:t}),_=u({schema:d({"/api/mwai/api/list":{output:f.array(f.object({id:f.string(),title:f.string(),description:f.string().nullable(),status:f.enum([`pending`,`success`,`error`]),createdAt:f.number(),updatedAt:f.number(),enabled:f.boolean()}))},"/api/mwai/api/modify":{input:f.object({prompt:f.string()}),output:f.object({success:f.boolean()})}}),retry:{type:`exponential`,attempts:5,baseDelay:1e3,maxDelay:1e4},plugins:[p({enabled:!1})]}),v=()=>{let i=a(h),[u,d]=s(null);return o(()=>{if(!i){console.error(`ModifyWithAI: No id provided. Wrap your app with <ModifyWithAIProvider id='your-id'>`);return}typeof window<`u`&&(window.__REACT__=r,window.__REACT_JSX_RUNTIME__=e,window.__REACT_DOM__=c,window.__REACT_DOM_CLIENT__=l);let t=Function(`url`,`return import(url)`);_(`/api/mwai/api/list`).then(({data:e,error:n})=>{if(n){console.error(`Failed to fetch component list:`,n);return}console.log(`data`,e);let r=e.filter(e=>e.enabled&&e.status===`success`).map(e=>e.id);console.log(`componentsToLoad`,r),r.forEach(e=>{t(`https://bucket.modifywithai.com/${i}/${e}.js`).then(e=>d(t=>[...t||[],e.default])).catch(e=>console.error(`Failed to load external module:`,e))})})},[i]),u?n(t,{children:u.map(e=>n(e,{},e.name))}):null},y=()=>v();async function b(e,t){let n=e.trim();if(!n){let e=Error(`Prompt cannot be empty`);return t?.onError?.(e),{success:!1,error:e}}try{return{success:(await _(`/api/mwai/api/modify`,{method:`POST`,body:{prompt:n},onSuccess:()=>{typeof window<`u`&&window.location.reload()},onError:e=>{let n=Error(e.error.message||`Request failed`);t?.onError?.(n)}})).data?.success??!1}}catch(e){let n=e instanceof Error?e:Error(`Unknown error`);return t?.onError?.(n),{success:!1,error:n}}}export{y as MWAIComponents,m as MWAIHead,g as MWAIProvider,b as modifyWithAI,v as useMWAIComponents};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modifywithai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"next": "^16.0.8"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@base-ui/react": "^1.0.0",
|
|
36
35
|
"@better-fetch/fetch": "^1.1.21",
|
|
37
36
|
"@better-fetch/logger": "^1.1.21",
|
|
38
37
|
"zod": "^4.1.13"
|