@coppsary/motionly 1.1.1 → 1.1.3

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/README.md CHANGED
@@ -1,448 +1,127 @@
1
1
  <div align="center">
2
2
  <img src="public/logo.svg" alt="Motionly Logo" width="100">
3
-
3
+
4
4
  # Motionly
5
-
5
+
6
6
  **AI-native motion graphics editor**
7
7
  </div>
8
8
 
9
9
  <p align="center">
10
- <em>AI-assisted workflows create editable animation projects you can refine visually.<br/>Edit timing, assets, animations, and layouts before exporting the final result.</em>
10
+ <em>Create editable animations with AI, then refine every detail visually.</em>
11
11
  </p>
12
12
 
13
13
  <p align="center">
14
- <img src="https://img.shields.io/badge/TypeScript-5.7-3178C6?style=flat&logo=typescript&logoColor=white" alt="TypeScript">
15
- <img src="https://img.shields.io/badge/Svelte-5.56-FF3E00?style=flat&logo=svelte&logoColor=white" alt="Svelte">
16
- <img src="https://img.shields.io/badge/Canvas-2D_Renderer-E34F26?style=flat&logo=html5&logoColor=white" alt="Canvas">
17
- <img src="https://img.shields.io/badge/GSAP-3.15-0AE448?style=flat&logo=greensock&logoColor=white" alt="GSAP">
18
- <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue?style=flat" alt="License"></a>
19
- <br>
14
+ <a href="https://www.producthunt.com/products/motionly">
15
+ <img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1202670&theme=dark" alt="Motionly on Product Hunt" height="54" />
16
+ </a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://www.npmjs.com/package/@coppsary/motionly">
21
+ <img src="https://img.shields.io/npm/dm/%40coppsary%2Fmotionly?style=flat&logo=npm&logoColor=white" alt="npm Downloads">
22
+ </a>
20
23
  <a href="https://motionly.mintlify.app/"><img src="https://img.shields.io/badge/Docs-Mintlify-7C3AED?style=flat" alt="Documentation"></a>
21
24
  <a href="https://github.com/COPPSARY/Motionly"><img src="https://img.shields.io/github/stars/COPPSARY/Motionly?style=flat" alt="GitHub Stars"></a>
25
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue?style=flat" alt="License"></a>
22
26
  </p>
23
27
 
24
28
  <p align="center">
25
- <a href="#overview">Overview</a> &middot;
26
29
  <a href="#showcase">Showcase</a> &middot;
27
- <a href="#visual-editor">Visual Editor</a> &middot;
28
- <a href="#motion-files">Motion Files</a> &middot;
29
- <a href="#agent-and-llm-support">Agent and LLM Support</a> &middot;
30
- <a href="#contributing">Contributing</a>
30
+ <a href="#features">Features</a> &middot;
31
+ <a href="#quick-start">Quick Start</a> &middot;
32
+ <a href="#development">Development</a> &middot;
33
+ <a href="https://motionly.mintlify.app/">Docs</a>
31
34
  </p>
32
35
 
33
36
  ---
34
37
 
35
38
  ## Showcase
36
39
 
37
- | Visual Editor |
38
- | :---------------------------------------------------: |
40
+ <table align="center">
41
+ <tr>
42
+ <th>Animation Preview</th>
43
+ </tr>
44
+ <tr>
45
+ <td align="center">
46
+ <img src=".github/assets/showcase-2.gif" alt="Motionly Animation">
47
+ </td>
48
+ </tr>
49
+ </table>
50
+
51
+ | Visual Editor |
52
+ | :---: |
39
53
  | ![Motionly Editor](.github/assets/screenshot.jpg) |
40
54
 
41
- | Animation Preview |
42
- | :--------------------------------------------------------: |
43
- | ![Motionly Animation](.github/assets/showcase.gif) |
44
55
 
45
- ---
46
56
 
47
- ## Overview
48
57
 
49
- Motionly is a motion graphics editor where AI-assisted workflows create editable animation projects that you can refine visually. Edit timing, assets, animations, and layouts through a timeline and canvas editor before exporting the final result.
50
58
 
51
- The current focus is the core editing loop: reliable preview, direct manipulation, useful animation presets, clear timeline control, clean serialization, and dependable export.
52
- ---
53
-
54
- ## Visual Editor
55
-
56
- Current editor features:
57
-
58
- **Interface:**
59
- - Left navigation rail with icon-based navigation (Media, Audio, Text, Effects, Scenes, AI Config, Settings)
60
- - Organized Assets panel with folder structure showing audio and visual assets
61
- - Assets panel tabs: Assets and Presets
62
- - AI Config (rail): enabled skills and an AI context preview
63
- - Settings (rail): brand profile editor
64
- - Preset browser with animated GIF previews
65
- - Professional properties panel with custom sliders, styled inputs, and visual preset cards
66
-
67
- **Canvas & Preview:**
68
- - Centered canvas preview with the project aspect ratio
69
- - Play, pause, reset, timeline scrubber, timecode, and frame display
70
- - Fit, zoom, and fullscreen preview controls
71
- - Click asset thumbnails for temporary full-screen preview (no timeline disruption)
72
-
73
- **Editing:**
74
- - Drag-to-move and corner scaling for elements
75
- - Visual position, scale, rotation, opacity, text, color, timing, and easing controls
76
- - Add text, delete layers, resize the timeline, and trim layer ranges
77
- - Scene, canvas, and timeline selection
78
-
79
- **Timeline Editing:**
80
- - Persistent Main, Overlay, and Audio track roles saved through `.motion`
81
- - Uniform visual layers with free gaps/overlaps and no ripple behavior
82
- - Horizontal timing changes stay on the current layer; vertical drag moves to any visual layer
83
- - Optional clip-edge/playhead snapping is off by default
84
- - Grab a clip's center to move it in time or across layers; a dashed ghost previews the persisted landing position (mouse and touch)
85
- - On-timeline GSAP keyframes: selecting an animated element shows draggable keyframe diamonds on its row with per-keyframe easing controls, add-at-playhead, and right-click delete; edits persist into `.motion`
86
- - Playhead-based Split for media, text, images, overlays, and effects
87
- - Timeline zoom controls plus `Ctrl/Cmd` wheel or trackpad pinch
88
- - Undo/Redo history and persistent track hide/mute controls
89
- - Visual media clips with thumbnails and transition markers
90
-
91
- **Audio:**
92
- - Audio defined in `.motion` format (persists with project)
93
- - Synchronized audio preview playback
94
- - Audio shown in organized Assets panel
95
-
96
- **Project Management:**
97
- - Open and save `.motion` projects
98
- - Load presets with confirmation dialog
99
- - All edits automatically serialize to `.motion` format
100
-
101
- **AI Assistant:**
102
- - BYOK Motionly Assistant that generates and loads editable `.motion` projects
103
- - OpenAI, Anthropic, OpenRouter, Google Gemini, Hugging Face, and custom OpenAI-compatible endpoints
104
- - Locally stored keys and model overrides
105
- - AI Config (rail) manages enabled skills fed to the assistant; Settings (rail) holds a brand profile (BRAND.md). Both become assistant knowledge.
106
-
107
- **Export:**
108
- - Canvas-frame MP4 export through the local Motionly/FFmpeg server with progress and project-audio mixing
109
-
110
- Current limits:
111
-
112
- - MP4/WebM/MOV clips use the browser's native codecs and render decoded frames during preview, scrub, trim, and export
113
- - GIF uses frame-accurate `ImageDecoder` when available, Lottie uses the official dotLottie Canvas renderer, and animated SVG uses a real-time SVG-to-Canvas runtime
114
- - Video clip audio is muted and is not mixed into export yet; use the project audio track
115
- - Two simultaneous clips that reference one video alias cannot seek that decoder to two source times; import a second alias when needed
116
- - Project audio exports at its timeline offset; embedded audio from video clips remains muted
117
- - Animated SVG and GIF fallback export in real time because those runtimes do not expose deterministic seeking
118
- - Canvas resolution, aspect ratio, and FPS still come from `.motion`
119
- - WebM, GIF, still-image, and image-sequence export are not exposed yet
120
59
 
121
60
  ---
122
61
 
123
- ## Motion Files
124
-
125
- The main sample project is:
126
-
127
- ```text
128
- video-motion/motionly.motion
129
- ```
130
-
131
- Its sample assets live in:
132
-
133
- ```text
134
- video-motion/assets/motionly/
135
- ```
136
-
137
- Example:
138
-
139
- ```motion
140
- canvas {
141
- size 1920x1080
142
- fps 60
143
- duration 8s
144
- background #020308
145
- }
146
-
147
- camera {
148
- zoom 1
149
- x 0
150
- y 0
151
- }
152
-
153
- audio "/assets/my-project/background.mp3"
154
-
155
- import "/video-motion/assets/my-project/logo.svg" as mark
156
- import "/video-motion/assets/my-project/video.mp4" as bgVideo
157
-
158
- mark {
159
- center
160
- layer hero
161
- width 220
162
- opacity 0
163
- animation maskReveal(delay 1s duration 900ms direction down ease power3.out)
164
- }
165
-
166
- text title {
167
- value "Motion graphics, written."
168
- center
169
- layer text
170
- size 72
171
- textAnimation keynoteText(split words stagger 80ms duration 800ms delay 1s ease power3.out)
172
- }
173
-
174
- clip bgVideo {
175
- track 1
176
- start 0s
177
- duration 5s
178
- trimIn 0s
179
- trimOut 0s
180
- }
181
- ```
182
-
183
- Motionly supports semantic layers, camera animation, reusable presets, SVG/image assets, text reveals, generated background effects, timeline clips, audio, preview playback, and MP4 export.
184
-
185
- ### Use Your Own Assets
186
-
187
- For a new animation:
188
-
189
- 1. Copy `video-motion/motionly.motion` to a new `.motion` file or replace its contents.
190
- 2. Remove sample files you do not need from `video-motion/assets/motionly/`.
191
- 3. Prefer creating a separate folder such as `video-motion/assets/my-project/`.
192
- 4. Add your own images, SVGs, logos, audio files, and videos.
193
- 5. Update every `import` path in the `.motion` project.
194
- 6. Open the project in Motionly and finish positioning and timing visually.
195
- 7. Or drag assets from the Assets panel onto the timeline to create clips.
196
-
197
- Images, SVGs, and videos can be imported and used as timeline clips. Audio persists in `.motion` format. Drag assets onto the timeline to create clips that persist in the project file.
198
-
199
- **Note:** Timeline clips reference assets by filename. Keep original files in the same location to reload projects with clips.
200
-
201
- See [AI Authoring Guide](docs/agents/ai-authoring.mdx) for a complete asset and prompting workflow.
202
-
203
- ---
62
+ ## Features
204
63
 
205
- ## Agent And LLM Support
64
+ Motionly combines a canvas, timeline, and visual controls with an editable `.motion` source format.
206
65
 
207
- Motionly includes a built-in AI Chat panel and repository guidance for external agent tools.
66
+ - Preview, select, position, scale, rotate, and style elements visually
67
+ - Edit timing, keyframes, easing, clips, transitions, and audio on the timeline
68
+ - Use smooth animation presets for text, images, SVGs, and video
69
+ - Draft editable projects with the optional BYOK AI assistant
70
+ - Save projects as readable `.motion` files and export MP4
208
71
 
209
- Open Motionly Assistant beside Assets, enter your own provider key, and describe the animation you want. Motionly detects OpenAI, Anthropic, OpenRouter, Google Gemini, and Hugging Face keys, or accepts a custom OpenAI-compatible endpoint. You can leave the model blank for Motionly's default or enter an exact model ID. The key and chat history stay in browser storage; requests go directly from the browser to that provider, never through a Motionly server. The assistant receives the current project and imported asset list, returns a `.motion` draft, and exposes a **Load into Editor** action that validates the source through the normal parser and scene-graph pipeline.
72
+ AI-generated work always goes through Motionly's parser and remains fully editable in the visual editor.
210
73
 
211
- **Model quality matters.** The AI model you choose directly affects composition, timing, and correct preset use. Smaller models may generate valid syntax but weaker visual decisions. Prefer a current, high-capability model with strong code-generation and instruction-following performance.
74
+ ## Quick Start
212
75
 
213
- For coding agents working inside a project, install the skill with `npx @coppsary/motionly skills add` (or `npx @coppsary/motionly init`, which asks which agent). This writes the `SKILL.md` contract plus a full `references/` library into your agent's folder — Codex (`.agents/`), Claude Code (`.claude/`), Gemini CLI (`.gemini/`), opencode (`.opencode/`), or Kiro (`.kiro/`):
214
-
215
- | Path | Purpose |
216
- |---|---|
217
- | `<agent>/skills/motionly/SKILL.md` | Quick `.motion` contract |
218
- | `<agent>/skills/motionly/references/llms.txt` | Discovery index for the focused skills |
219
- | `<agent>/skills/motionly/references/skills/*/SKILL.md` | Full library: `motion-dsl`, `svg`, `animation`, `timeline`, and more |
220
-
221
- Point the agent at `AGENTS.md` and the installed `SKILL.md`, then let it load `references/llms.txt` and the reference skills the task needs. Working inside a clone of this repository instead? The same guidance lives at `AGENTS.md` and `.agents/skills/write-motionly/`. See the [AI Authoring Guide](docs/agents/ai-authoring.mdx) for prompting details.
222
-
223
- Use this short prompt with an LLM or agent working inside the repository:
224
-
225
- ```text
226
- /motionly
227
- Read AGENTS.md and .agents/skills/write-motionly/SKILL.md first.
228
- Inspect my assets, storyboard the animation, then create a valid .motion project.
229
- Use only supported Motionly syntax and presets. Keep one focal subject per shot,
230
- avoid overlap and repeated fade-only scenes, and validate the final project.
231
- Open the result for visual refinement instead of treating the generated file as final.
232
- ```
233
-
234
- The in-app assistant or external agent creates the first editable version. Motionly remains the place where you preview, adjust, save, and export it.
235
-
236
- ---
237
-
238
- ## Goals
239
-
240
- Current product goals:
241
-
242
- - Make visual editing, selection, timeline trimming, and saving feel reliable.
243
- - Improve preview and MP4 frame pacing on longer projects.
244
- - Add visual canvas controls for FPS, resolution, duration, and aspect ratio.
245
- - Add image, video, and persistent audio clips to the timeline.
246
- - Improve existing animation presets and add a small set of distinct transitions.
247
- - Add more export formats only after MP4 is dependable.
248
- - Provide a hosted editor/sandbox without removing local or self-hosted use.
249
- - Explore optional Remotion and Hyperframe support for code-based composition and rendering workflows while keeping `.motion` as the editable source format.
250
- - Keep BYOK AI drafting optional, local-first, and compatible with external providers.
251
-
252
- See the [Roadmap](ROADMAP.md) for the planned order of work.
253
-
254
- ---
255
-
256
- ## Architecture
257
-
258
- ```text
259
- .motion source
260
- -> parser
261
- -> AST
262
- -> scene graph
263
- -> animation preset compiler
264
- -> animation evaluator
265
- -> canvas renderer
266
- -> preview / export
267
- ```
268
-
269
- Core folders:
270
-
271
- | Path | Purpose |
272
- |---|---|
273
- | `AGENTS.md` | Agent guidance and product boundaries |
274
- | `.agents/skills/write-motionly` | Reusable agent skill for authoring `.motion` |
275
- | `src/ui` | Svelte editor and app shell |
276
- | `src/language` | Tokenizer, parser, AST, and serializer |
277
- | `src/scene` | Scene graph normalization and layer/camera structure |
278
- | `src/animation` | Deterministic animation evaluation |
279
- | `src/animation-library` | Reusable animation presets |
280
- | `src/render` | Canvas renderer |
281
- | `src/export` | MP4 and export pipeline |
282
- | `video-motion` | Sample `.motion` projects and assets |
283
-
284
- ---
285
-
286
- ## Open Source
287
-
288
- Motionly is licensed under the Apache License 2.0.
289
-
290
- Project docs:
291
-
292
- - [Introduction](docs/introduction.mdx)
293
- - [Quick Start](docs/quickstart.mdx)
294
- - [Installation](docs/installation.mdx)
295
- - [User Guide](docs/guides/user-guide.mdx)
296
- - [UI Guide](docs/editor/ui-guide.mdx)
297
- - [Motion Language Overview](docs/motion-language/overview.mdx)
298
- - [Animation Presets](docs/animation/presets.mdx)
299
- - [Export Overview](docs/export/overview.mdx)
300
- - [AI Authoring Guide](docs/agents/ai-authoring.mdx)
301
- - [Contributing](CONTRIBUTING.md)
302
- - [Code of Conduct](CODE_OF_CONDUCT.md)
303
- - [Security Policy](SECURITY.md)
304
- - [Roadmap](ROADMAP.md)
305
- - [Changelog](CHANGELOG.md)
306
-
307
- ---
308
-
309
- ## Export
310
-
311
- Motionly currently exposes MP4 export through the editor when the browser supports MP4 `MediaRecorder` output.
312
-
313
- Known limitations:
314
-
315
- - Export runs in real time and still needs pacing and reliability improvements.
316
- - Attached audio is not included yet.
317
- - Resolution and FPS use the current canvas settings.
318
- - WebM, GIF, PNG, and image-sequence export are roadmap work.
319
-
320
- ---
321
-
322
- ## Install and use
323
-
324
- Motionly ships on npm — no clone and no global install. It needs Node.js `20.19.0` or newer, and every command runs through `npx`.
325
-
326
- ### Create a project
327
-
328
- ```bash
329
- npx @coppsary/motionly init demo
330
- ```
331
-
332
- `init` scaffolds the project and asks **which agent you're using**, then installs the Motionly agent skill for just that one (or choose "All supported agents"). Supported agents: **Codex, Claude Code, Gemini CLI, opencode, and Kiro**. The install is not a single file: it writes the `SKILL.md` contract plus a full `references/` library (`motion-dsl`, `svg`, `animation`, `timeline`, and more) with an `llms.txt` discovery index.
333
-
334
- Skip the prompt with flags:
76
+ Requires Node.js `20.19.0` or newer.
335
77
 
336
78
  ```bash
337
- npx @coppsary/motionly init demo --provider opencode # install for one agent, no prompt
338
- npx @coppsary/motionly init demo --all # every supported agent
339
- npx @coppsary/motionly init demo --skip-skills # no agent skills
340
- ```
341
-
342
- Provider names are `codex`, `claude`, `gemini`, `opencode`, and `kiro`. Use `--scope project` (default) or `--scope global` to install for every project on your machine.
343
-
344
- The scaffolded project:
345
-
346
- ```text
347
- demo/
348
- ├── AGENTS.md
349
- ├── assets/
350
- ├── project.motion
351
- ├── meta.json
352
- └── README.md
79
+ npx @coppsary/motionly init my-video
353
80
  ```
354
81
 
355
- ### Add skills to an existing project
82
+ The setup creates a project, optionally installs the Motionly skill for your coding agent, and opens the editor. To return later:
356
83
 
357
84
  ```bash
358
- npx @coppsary/motionly skills add # pick scope and agents
359
- npx @coppsary/motionly skills add --all --scope project
360
- npx @coppsary/motionly skills add --provider codex --scope global
85
+ cd my-video
86
+ npx @coppsary/motionly dev
361
87
  ```
362
88
 
363
- Re-running is safe: existing skill files are kept, never overwritten.
364
-
365
- ### Open and edit
89
+ Want the editor without creating a project?
366
90
 
367
91
  ```bash
368
- cd demo
369
- npx @coppsary/motionly dev
92
+ npx @coppsary/motionly
370
93
  ```
371
94
 
372
- Motionly opens `http://localhost:4173/editor`, loads `project.motion`, serves media from `assets/`, and saves editor changes back to the project. Add `--port <n>` to change the port or `--no-open` to skip launching the browser. For the no-setup browser editor, run `npx @coppsary/motionly`.
373
-
374
- ## Development from source
95
+ See the [Quick Start](https://motionly.mintlify.app/quickstart) and [Installation Guide](https://motionly.mintlify.app/installation) for editing, export, CLI options, agent setup, and requirements.
375
96
 
376
- For local development from source:
97
+ ## Development
377
98
 
378
99
  ```bash
100
+ git clone https://github.com/COPPSARY/Motionly.git
101
+ cd Motionly
379
102
  npm install
380
103
  npm run dev
381
104
  ```
382
105
 
383
- Open:
384
-
385
- ```text
386
- http://localhost:5173
387
- ```
388
-
389
- To serve your own production build locally:
390
-
391
- ```bash
392
- npm run build
393
- npm run serve
394
- ```
395
-
396
- ---
397
-
398
- ## Test
106
+ Before opening a pull request:
399
107
 
400
108
  ```bash
109
+ npm run test:run
401
110
  npm run build
402
- npm test -- --run
403
111
  ```
404
112
 
405
- ---
406
-
407
-
408
- ## Contributing
113
+ See [Contributing](CONTRIBUTING.md), the [Roadmap](ROADMAP.md), and the [documentation](https://motionly.mintlify.app/) for project details.
409
114
 
410
- Repository:
115
+ ## License
411
116
 
412
- https://github.com/COPPSARY/Motionly
413
-
414
- Contribution priorities:
415
-
416
- 1. Improve the visual editor and timeline experience.
417
- 2. Fix preview and MP4 export performance and correctness.
418
- 3. Add focused tests for parser, serialization, presets, editor workflows, and export.
419
- 4. Keep `.motion` examples and implementation files readable.
420
- 5. Avoid large dependencies unless they clearly simplify the core workflow.
421
-
422
- Before opening a PR:
423
-
424
- - Run `npm test -- --run`
425
- - Run `npm run build`
426
- - Keep `.motion` examples readable
427
- - Avoid hidden state in rendering
428
- - Do not mutate imported assets
429
- - Prefer deterministic frame evaluation over runtime side effects
430
-
431
- ---
432
-
433
- ## Links
434
-
435
- <div align="center">
436
-
437
- | Platform | Link |
438
- |---|---|
439
- | GitHub | [COPPSARY](https://github.com/COPPSARY) |
440
- | Facebook | [COPPSARY](https://web.facebook.com/profile.php?id=61567582710788) |
441
-
442
- </div>
117
+ Licensed under the [Apache License 2.0](LICENSE).
443
118
 
444
119
  ---
445
120
 
446
121
  <div align="center">
447
122
  <p><em>Effortless Animation</em></p>
123
+ <p>
124
+ <a href="https://github.com/COPPSARY">GitHub</a> &middot;
125
+ <a href="https://web.facebook.com/profile.php?id=61567582710788">Facebook</a>
126
+ </p>
448
127
  </div>
package/bin/motionly.js CHANGED
@@ -26,6 +26,7 @@ const PROVIDERS = {
26
26
  gemini: '.gemini/skills/motionly/SKILL.md',
27
27
  opencode: '.opencode/skills/motionly/SKILL.md',
28
28
  kiro: '.kiro/skills/motionly/SKILL.md',
29
+ rayu: '.rayu/skills/motionly/SKILL.md',
29
30
  };
30
31
 
31
32
  const AGENT_LABELS = {
@@ -34,6 +35,7 @@ const AGENT_LABELS = {
34
35
  gemini: 'Gemini CLI',
35
36
  opencode: 'opencode',
36
37
  kiro: 'Kiro',
38
+ rayu: 'RAYU',
37
39
  };
38
40
 
39
41
  const MIME = {
@@ -306,6 +308,17 @@ async function readRequestBody(request, maximum = 5_000_000) {
306
308
  return source;
307
309
  }
308
310
 
311
+ async function readRequestBuffer(request, maximum = 200_000_000) {
312
+ const chunks = [];
313
+ let total = 0;
314
+ for await (const chunk of request) {
315
+ total += chunk.length;
316
+ if (total > maximum) throw new Error('TOO_LARGE');
317
+ chunks.push(chunk);
318
+ }
319
+ return Buffer.concat(chunks);
320
+ }
321
+
309
322
  function safeFile(rootPath, pathname) {
310
323
  const filePath = normalize(join(rootPath, pathname));
311
324
  return filePath === rootPath || filePath.startsWith(`${rootPath}${sep}`) ? filePath : null;
@@ -369,7 +382,7 @@ async function serveEditor(argv, projectFolder = null) {
369
382
  return;
370
383
  }
371
384
 
372
- if (pathname.startsWith('/assets/')) {
385
+ if (pathname.startsWith('/assets/') && (request.method === 'GET' || request.method === 'HEAD')) {
373
386
  const bundledAsset = safeFile(dist, pathname.slice(1));
374
387
  if (bundledAsset && (await exists(bundledAsset))) {
375
388
  await serveFile(response, bundledAsset, request.method);
@@ -379,10 +392,19 @@ async function serveEditor(argv, projectFolder = null) {
379
392
 
380
393
  if (assetsRoot && pathname.startsWith('/assets/')) {
381
394
  const filePath = safeFile(assetsRoot, pathname.slice('/assets/'.length));
382
- if (!filePath) {
395
+ if (!filePath || filePath === assetsRoot) {
383
396
  response.writeHead(403).end('Forbidden');
384
397
  return;
385
398
  }
399
+ if (request.method === 'PUT') {
400
+ // Save an uploaded/dragged asset into the project's on-disk assets folder
401
+ // so it can be reused, edited, or deleted like any other project media.
402
+ const data = await readRequestBuffer(request);
403
+ await mkdir(dirname(filePath), { recursive: true });
404
+ await writeFile(filePath, data);
405
+ response.writeHead(204, { 'X-Motionly-Asset': basename(filePath) }).end();
406
+ return;
407
+ }
386
408
  await serveFile(response, filePath, request.method);
387
409
  return;
388
410
  }
@@ -406,7 +428,7 @@ async function serveEditor(argv, projectFolder = null) {
406
428
  });
407
429
 
408
430
  server.listen(port, () => {
409
- const url = `http://localhost:${port}${projectRoot ? '/editor' : ''}`;
431
+ const url = `http://localhost:${port}`;
410
432
  console.log(
411
433
  `\n Motionly is running.\n Open this URL in your browser: ${url}${projectRoot ? `\n Project: ${projectRoot}` : ''}\n Press Ctrl+C to stop.\n`
412
434
  );
@@ -434,7 +456,7 @@ function printHelp() {
434
456
  npx @coppsary/motionly init <folder> --skip-skills Create a project without agent skills
435
457
  npx @coppsary/motionly skills add Install agent skills into an existing project
436
458
  npx @coppsary/motionly skills add --all
437
- npx @coppsary/motionly skills add --provider <codex|claude|gemini|opencode|kiro>
459
+ npx @coppsary/motionly skills add --provider <codex|claude|gemini|opencode|kiro|rayu>
438
460
  npx @coppsary/motionly dev [project-folder] Reopen and edit a local project
439
461
 
440
462
  Options: --scope <project|global>, --port <number>, --no-open`);