@editframe/create 0.43.0 → 0.45.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.
Files changed (99) hide show
  1. package/README.md +11 -0
  2. package/dist/index.js +16 -28
  3. package/dist/index.js.map +1 -1
  4. package/dist/skills/editframe-brand-video-generator/README.md +155 -0
  5. package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
  6. package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
  7. package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
  8. package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
  9. package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
  10. package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
  11. package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
  12. package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
  13. package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
  14. package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
  15. package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
  16. package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
  17. package/dist/skills/editframe-composition/SKILL.md +169 -0
  18. package/dist/skills/editframe-composition/references/audio.md +483 -0
  19. package/dist/skills/editframe-composition/references/captions.md +844 -0
  20. package/dist/skills/editframe-composition/references/composition-model.md +73 -0
  21. package/dist/skills/editframe-composition/references/configuration.md +403 -0
  22. package/dist/skills/editframe-composition/references/css-parts.md +105 -0
  23. package/dist/skills/editframe-composition/references/css-variables.md +640 -0
  24. package/dist/skills/editframe-composition/references/entry-points.md +810 -0
  25. package/dist/skills/editframe-composition/references/events.md +499 -0
  26. package/dist/skills/editframe-composition/references/getting-started.md +259 -0
  27. package/dist/skills/editframe-composition/references/hooks.md +234 -0
  28. package/dist/skills/editframe-composition/references/image.md +241 -0
  29. package/dist/skills/editframe-composition/references/r3f.md +580 -0
  30. package/dist/skills/editframe-composition/references/render-api.md +484 -0
  31. package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
  32. package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
  33. package/dist/skills/editframe-composition/references/scripting.md +606 -0
  34. package/dist/skills/editframe-composition/references/sequencing.md +116 -0
  35. package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
  36. package/dist/skills/editframe-composition/references/surface.md +329 -0
  37. package/dist/skills/editframe-composition/references/text.md +627 -0
  38. package/dist/skills/editframe-composition/references/time-model.md +99 -0
  39. package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
  40. package/dist/skills/editframe-composition/references/timegroup.md +457 -0
  41. package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
  42. package/dist/skills/editframe-composition/references/transcription.md +47 -0
  43. package/dist/skills/editframe-composition/references/transitions.md +608 -0
  44. package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
  45. package/dist/skills/editframe-composition/references/video.md +506 -0
  46. package/dist/skills/editframe-composition/references/waveform.md +327 -0
  47. package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
  48. package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
  49. package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
  50. package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
  51. package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
  52. package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
  53. package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
  54. package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
  55. package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
  56. package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
  57. package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
  58. package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
  59. package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
  60. package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
  61. package/dist/skills/editframe-editor-gui/references/play.md +370 -0
  62. package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
  63. package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
  64. package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
  65. package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
  66. package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
  67. package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
  68. package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
  69. package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
  70. package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
  71. package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
  72. package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
  73. package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
  74. package/dist/skills/editframe-motion-design/SKILL.md +101 -0
  75. package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
  76. package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
  77. package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
  78. package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
  79. package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
  80. package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
  81. package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
  82. package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
  83. package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
  84. package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
  85. package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
  86. package/dist/skills/editframe-webhooks/SKILL.md +126 -0
  87. package/dist/skills/editframe-webhooks/references/events.md +382 -0
  88. package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
  89. package/dist/skills/editframe-webhooks/references/security.md +418 -0
  90. package/dist/skills/editframe-webhooks/references/testing.md +409 -0
  91. package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
  92. package/dist/templates/html/AGENTS.md +13 -0
  93. package/dist/templates/react/AGENTS.md +13 -0
  94. package/dist/utils.js +15 -16
  95. package/dist/utils.js.map +1 -1
  96. package/package.json +2 -2
  97. package/tsdown.config.ts +4 -0
  98. package/dist/detectAgent.js +0 -89
  99. package/dist/detectAgent.js.map +0 -1
@@ -0,0 +1,753 @@
1
+ ---
2
+ title: Server-Side Rendering
3
+ description: Use SSR-safe imports and integrate Editframe with Next.js, Remix, and other server-rendered frameworks without hydration errors.
4
+ type: reference
5
+ nav:
6
+ parent: "Advanced"
7
+ priority: 30
8
+ api:
9
+ entry_points:
10
+ - name: "@editframe/elements/server"
11
+ description: SSR-safe types and utilities (no DOM, no Web Components)
12
+ exports:
13
+ - getRenderInfo
14
+ - RenderInfo (type)
15
+ - EFTimegroup (type)
16
+ - EFMedia (type)
17
+ - RenderToVideoOptions (type)
18
+ - RenderProgress (type)
19
+ - ContentReadyMode (type)
20
+ - name: "@editframe/react/server"
21
+ description: SSR-safe React components and types
22
+ exports:
23
+ - Audio
24
+ - Captions
25
+ - CaptionsActiveWord
26
+ - CaptionsAfterActiveWord
27
+ - CaptionsBeforeActiveWord
28
+ - CaptionsSegment
29
+ - Text
30
+ - TextSegment
31
+ - Image
32
+ - Surface
33
+ - Timegroup
34
+ - Video
35
+ - Waveform
36
+ - PanZoom
37
+ - RenderToVideoOptions (type)
38
+ - RenderProgress (type)
39
+ functions:
40
+ - name: getRenderInfo
41
+ signature: "getRenderInfo(html: string): Promise<RenderInfo>"
42
+ description: Extract render metadata from HTML composition (Node.js safe)
43
+ returns: RenderInfo
44
+ react:
45
+ generate: true
46
+ componentName: "Server-Side Rendering"
47
+ importPath: "@editframe/react"
48
+ nav:
49
+ parent: "Advanced / Server Integration"
50
+ priority: 85
51
+ ---
52
+
53
+ # Server-Side Rendering
54
+
55
+ <!-- html-only -->
56
+ Editframe packages provide SSR-safe entry points for server-side rendering with Next.js, Remix, and other React frameworks. Import from `@editframe/elements/server` or `@editframe/react/server` to access types and components without triggering browser-specific code.
57
+ <!-- /html-only -->
58
+ <!-- react-only -->
59
+ Editframe provides an SSR-safe entry point for server-side rendering with Next.js, Remix, and other React frameworks.
60
+ <!-- /react-only -->
61
+
62
+ ## Problem: Browser APIs in SSR
63
+
64
+ <!-- html-only -->
65
+ The main package entries (`@editframe/elements` and `@editframe/react`) import browser-specific code at the module level:
66
+ - Web Components (`customElements.define()`)
67
+ - DOM APIs (`HTMLElement`, `document`, `window`)
68
+ - Canvas, WebGL, WebCodecs APIs
69
+ <!-- /html-only -->
70
+ <!-- react-only -->
71
+ The main entry point (`@editframe/react`) imports browser-specific code at the module level:
72
+ - Web Components (`customElements.define()`)
73
+ - DOM APIs (`document`, `window`)
74
+ - Browser-only hooks
75
+ - Canvas, WebGL, WebCodecs APIs
76
+ <!-- /react-only -->
77
+
78
+ This code **will crash** if imported during server-side rendering because Node.js doesn't provide these APIs.
79
+
80
+ ## Solution: SSR-Safe Entry Points
81
+
82
+ <!-- html-only -->
83
+ Use the `/server` subpath exports that only include types and SSR-safe utilities.
84
+
85
+ ## @editframe/elements/server
86
+
87
+ Import **types only** and the `getRenderInfo` utility:
88
+
89
+ ```typescript
90
+ import type {
91
+ EFTimegroup,
92
+ EFMedia,
93
+ RenderToVideoOptions,
94
+ RenderProgress,
95
+ } from "@editframe/elements/server";
96
+
97
+ import { getRenderInfo } from "@editframe/elements/server";
98
+ ```
99
+
100
+ ### What's Included
101
+
102
+ - **Types:** TypeScript type definitions for all elements (zero runtime code)
103
+ - **getRenderInfo:** Function to extract render metadata from HTML (Node.js safe)
104
+
105
+ ### What's NOT Included
106
+
107
+ - Web Component class definitions
108
+ - DOM manipulation utilities
109
+ - Browser-specific rendering code
110
+ - Canvas or WebGL APIs
111
+
112
+ ### getRenderInfo Example
113
+
114
+ ```typescript
115
+ // server.ts (Node.js safe)
116
+ import { getRenderInfo } from "@editframe/elements/server";
117
+
118
+ const html = `
119
+ <ef-timegroup mode="sequence" duration="30s">
120
+ <ef-video src="intro.mp4"></ef-video>
121
+ <ef-video src="outro.mp4"></ef-video>
122
+ </ef-timegroup>
123
+ `;
124
+
125
+ const info = await getRenderInfo(html);
126
+ console.log(info.durationMs); // 30000
127
+ console.log(info.width); // 1920
128
+ console.log(info.height); // 1080
129
+ ```
130
+
131
+ ## @editframe/react/server
132
+
133
+ Import **React components** that render to HTML without triggering browser APIs:
134
+
135
+ ```typescript
136
+ import {
137
+ Timegroup,
138
+ Video,
139
+ Audio,
140
+ Image,
141
+ Text,
142
+ Captions,
143
+ Surface,
144
+ Waveform,
145
+ PanZoom,
146
+ } from "@editframe/react/server";
147
+ ```
148
+
149
+ ### What's Included
150
+
151
+ - All composition React components (render to `<ef-*>` tags)
152
+ - Caption styling sub-components
153
+ - All types from `@editframe/elements/server`
154
+
155
+ ### What's NOT Included
156
+
157
+ - GUI components (Preview, Workbench, Controls, Timeline, etc.)
158
+ - Hooks that depend on browser APIs (`useTimingInfo`, `usePlayback`, etc.)
159
+ - Browser rendering utilities
160
+ <!-- /html-only -->
161
+ <!-- react-only -->
162
+ Import from `@editframe/react/server` to access composition components without triggering browser code:
163
+
164
+ ```tsx
165
+ import {
166
+ Timegroup,
167
+ Video,
168
+ Audio,
169
+ Image,
170
+ Text,
171
+ Captions,
172
+ Surface,
173
+ Waveform,
174
+ PanZoom,
175
+ } from "@editframe/react/server";
176
+ ```
177
+
178
+ ## What's Included
179
+
180
+ **Composition Components:**
181
+ - `Timegroup` - Timeline container
182
+ - `Video`, `Audio`, `Image` - Media elements
183
+ - `Text`, `TextSegment` - Text rendering
184
+ - `Captions` + sub-components - Caption styling
185
+ - `Surface` - Element mirroring
186
+ - `Waveform` - Audio visualization
187
+ - `PanZoom` - Pan/zoom container
188
+
189
+ **Types:**
190
+ - All render option types (`RenderToVideoOptions`, `RenderProgress`, etc.)
191
+ - All component prop types
192
+
193
+ ## What's NOT Included
194
+
195
+ **GUI Components:**
196
+ - `Preview`, `Workbench`, `Timeline`, `Controls`
197
+ - `Scrubber`, `Filmstrip`, `TimelineRuler`
198
+ - `Canvas`, `TransformHandles`, `Hierarchy`
199
+ - Any editor/preview UI components
200
+
201
+ **Hooks:**
202
+ - `useTimingInfo`, `usePlayback`, `useCompositionTime`
203
+ - `usePanZoomTransform`, `useMediaInfo`
204
+ - All browser-dependent hooks
205
+
206
+ **Browser Utilities:**
207
+ - `renderToVideo`, `createRenderClone`
208
+ - Browser-specific helpers
209
+ <!-- /react-only -->
210
+
211
+ ## Next.js Integration
212
+
213
+ ### App Router (React Server Components)
214
+
215
+ <!-- html-only -->
216
+ ```typescript
217
+ // app/video/[id]/page.tsx (Server Component)
218
+ import { Timegroup, Video, Audio } from "@editframe/react/server";
219
+
220
+ export default function VideoPage({ params }: { params: { id: string } }) {
221
+ return (
222
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
223
+ <Video src={`/api/videos/${params.id}/intro.mp4`} className="size-full" />
224
+ <Audio src={`/api/videos/${params.id}/music.mp3`} volume={0.3} />
225
+ </Timegroup>
226
+ );
227
+ }
228
+ ```
229
+ <!-- /html-only -->
230
+ <!-- react-only -->
231
+ Import from `/server` in Server Components:
232
+
233
+ ```tsx
234
+ // app/video/[id]/page.tsx (Server Component)
235
+ import { Timegroup, Video, Audio } from "@editframe/react/server";
236
+
237
+ interface Props {
238
+ params: { id: string };
239
+ }
240
+
241
+ export default function VideoPage({ params }: Props) {
242
+ return (
243
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px] bg-black">
244
+ <Video src={`/api/videos/${params.id}/intro.mp4`} className="size-full" />
245
+ <Audio src={`/api/videos/${params.id}/music.mp3`} volume={0.3} />
246
+ </Timegroup>
247
+ );
248
+ }
249
+ ```
250
+ <!-- /react-only -->
251
+
252
+ ### Pages Router (SSR)
253
+
254
+ Use dynamic imports with `ssr: false` for browser-only code:
255
+
256
+ <!-- html-only -->
257
+ ```typescript
258
+ // pages/editor.tsx
259
+ import dynamic from "next/dynamic";
260
+
261
+ // Safe: imports from /server
262
+ import { Timegroup, Video } from "@editframe/react/server";
263
+
264
+ // Unsafe: imports from main entry, requires client-side only
265
+ const Preview = dynamic(
266
+ () => import("@editframe/react").then((mod) => mod.Preview),
267
+ { ssr: false }
268
+ );
269
+
270
+ const Workbench = dynamic(
271
+ () => import("@editframe/react").then((mod) => mod.Workbench),
272
+ { ssr: false }
273
+ );
274
+
275
+ export default function EditorPage() {
276
+ return (
277
+ <div>
278
+ {/* This renders on server */}
279
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
280
+ <Video src="/videos/intro.mp4" className="size-full" />
281
+ </Timegroup>
282
+
283
+ {/* This only renders on client */}
284
+ <Workbench rendering={false} />
285
+ </div>
286
+ );
287
+ }
288
+ ```
289
+ <!-- /html-only -->
290
+ <!-- react-only -->
291
+ ```tsx
292
+ // pages/video/[id].tsx
293
+ import type { GetServerSideProps } from "next";
294
+ import { Timegroup, Video } from "@editframe/react/server";
295
+
296
+ interface Props {
297
+ videoUrl: string;
298
+ }
299
+
300
+ export const getServerSideProps: GetServerSideProps<Props> = async ({ params }) => {
301
+ const videoUrl = await fetchVideoUrl(params?.id);
302
+ return { props: { videoUrl } };
303
+ };
304
+
305
+ export default function VideoPage({ videoUrl }: Props) {
306
+ return (
307
+ <Timegroup mode="fixed" duration="10s" className="w-[1920px] h-[1080px]">
308
+ <Video src={videoUrl} className="size-full" />
309
+ </Timegroup>
310
+ );
311
+ }
312
+ ```
313
+
314
+ ### Client-Only Components
315
+
316
+ For editor UI components, use dynamic imports with `ssr: false`:
317
+
318
+ ```tsx
319
+ // pages/editor.tsx
320
+ import dynamic from "next/dynamic";
321
+ import { Timegroup, Video } from "@editframe/react/server";
322
+
323
+ // Safe: SSR-safe components
324
+ const composition = (
325
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
326
+ <Video src="/video.mp4" className="size-full" />
327
+ </Timegroup>
328
+ );
329
+
330
+ // Safe: Client-only dynamic import
331
+ const Workbench = dynamic(
332
+ () => import("@editframe/react").then((mod) => mod.Workbench),
333
+ { ssr: false }
334
+ );
335
+
336
+ const Preview = dynamic(
337
+ () => import("@editframe/react").then((mod) => mod.Preview),
338
+ { ssr: false }
339
+ );
340
+
341
+ export default function EditorPage() {
342
+ return (
343
+ <div>
344
+ {composition}
345
+ <Workbench rendering={false} />
346
+ </div>
347
+ );
348
+ }
349
+ ```
350
+ <!-- /react-only -->
351
+
352
+ ## Remix Integration
353
+
354
+ Use the `/server` entry for loaders and actions:
355
+
356
+ ```typescript
357
+ // routes/video.$id.tsx
358
+ import type { LoaderFunctionArgs } from "@remix-run/node";
359
+ import { json } from "@remix-run/node";
360
+ import { useLoaderData } from "@remix-run/react";
361
+ import { Timegroup, Video, Audio } from "@editframe/react/server";
362
+
363
+ export async function loader({ params }: LoaderFunctionArgs) {
364
+ const videoData = await fetchVideoData(params.id);
365
+ return json({ videoData });
366
+ }
367
+
368
+ export default function VideoRoute() {
369
+ const { videoData } = useLoaderData<typeof loader>();
370
+
371
+ return (
372
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
373
+ <Video src={videoData.introUrl} className="size-full" />
374
+ <Audio src={videoData.musicUrl} volume={0.3} />
375
+ </Timegroup>
376
+ );
377
+ }
378
+ ```
379
+
380
+ For client-only components, use `ClientOnly`:
381
+
382
+ ```typescript
383
+ import { ClientOnly } from "remix-utils/client-only";
384
+ <!-- html-only -->
385
+
386
+ export default function EditorRoute() {
387
+ return (
388
+ <ClientOnly>
389
+ {() => {
390
+ // Import happens only on client
391
+ const { Workbench } = require("@editframe/react");
392
+ return <Workbench rendering={false} />;
393
+ }}
394
+ </ClientOnly>
395
+ );
396
+ }
397
+ ```
398
+ <!-- /html-only -->
399
+ <!-- react-only -->
400
+ import { Timegroup, Video } from "@editframe/react/server";
401
+
402
+ export default function EditorRoute() {
403
+ return (
404
+ <>
405
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
406
+ <Video src="/video.mp4" className="size-full" />
407
+ </Timegroup>
408
+
409
+ <ClientOnly>
410
+ {() => {
411
+ const { Workbench } = require("@editframe/react");
412
+ return <Workbench rendering={false} />;
413
+ }}
414
+ </ClientOnly>
415
+ </>
416
+ );
417
+ }
418
+ ```
419
+ <!-- /react-only -->
420
+
421
+ ## Pre-rendering Static HTML
422
+
423
+ Generate static HTML for compositions:
424
+
425
+ ```typescript
426
+ // build.ts (Node.js)
427
+ import { renderToString } from "react-dom/server";
428
+ import { Timegroup, Video, Text } from "@editframe/react/server";
429
+ import { writeFileSync } from "fs";
430
+
431
+ const composition = (
432
+ <Timegroup mode="fixed" duration="10s" className="w-[1920px] h-[1080px]">
433
+ <Video src="/assets/background.mp4" className="size-full" />
434
+ <Text className="absolute inset-0 flex items-center justify-center text-6xl">
435
+ Hello World
436
+ </Text>
437
+ </Timegroup>
438
+ );
439
+
440
+ const html = renderToString(composition);
441
+ writeFileSync("./dist/composition.html", html);
442
+ ```
443
+
444
+ This HTML can then be hydrated on the client with the full browser-side code.
445
+
446
+ <!-- react-only -->
447
+ ```tsx
448
+ // client.tsx
449
+ import { hydrateRoot } from "react-dom/client";
450
+ import { Timegroup, Video, Text } from "@editframe/react"; // Full browser version
451
+
452
+ hydrateRoot(
453
+ document.getElementById("root")!,
454
+ <Timegroup mode="fixed" duration="10s" className="w-[1920px] h-[1080px] bg-black">
455
+ <Video src="/assets/background.mp4" className="size-full object-cover" />
456
+ <Text className="absolute inset-0 flex items-center justify-center text-6xl text-white">
457
+ Hello World
458
+ </Text>
459
+ </Timegroup>
460
+ );
461
+ ```
462
+ <!-- /react-only -->
463
+
464
+ ## Type Imports
465
+
466
+ When you only need types (not runtime code), use type-only imports for maximum safety:
467
+
468
+ ```typescript
469
+ // Safe in any environment (no runtime code)
470
+ import type { EFTimegroup, RenderToVideoOptions } from "@editframe/elements/server";
471
+ <!-- react-only -->
472
+ import type { TimegroupProps } from "@editframe/react/server";
473
+ <!-- /react-only -->
474
+
475
+ function createRenderConfig(): RenderToVideoOptions {
476
+ return {
477
+ fps: 30,
478
+ codec: "h264",
479
+ scale: 1,
480
+ };
481
+ }
482
+ ```
483
+
484
+ <!-- react-only -->
485
+ ## Type-Only Imports
486
+
487
+ ```typescript
488
+ // Safe in any environment (no runtime code)
489
+ import type { TimegroupProps, VideoProps, RenderToVideoOptions } from "@editframe/react/server";
490
+
491
+ function createVideoConfig(): VideoProps {
492
+ return {
493
+ src: "/video.mp4",
494
+ className: "size-full",
495
+ };
496
+ }
497
+
498
+ function createRenderOptions(): RenderToVideoOptions {
499
+ return {
500
+ fps: 30,
501
+ codec: "h264",
502
+ scale: 1,
503
+ };
504
+ }
505
+ ```
506
+
507
+ ## Environment-Based Imports
508
+
509
+ Dynamically import based on environment:
510
+
511
+ ```tsx
512
+ // VideoEditor.tsx
513
+ import type { FC } from "react";
514
+
515
+ let Timegroup: any;
516
+ let Video: any;
517
+ let Workbench: any;
518
+
519
+ if (typeof window === "undefined") {
520
+ // Server: import from /server
521
+ const server = await import("@editframe/react/server");
522
+ Timegroup = server.Timegroup;
523
+ Video = server.Video;
524
+ } else {
525
+ // Browser: import from main entry
526
+ const browser = await import("@editframe/react");
527
+ Timegroup = browser.Timegroup;
528
+ Video = browser.Video;
529
+ Workbench = browser.Workbench;
530
+ }
531
+
532
+ export const VideoEditor: FC = () => {
533
+ return (
534
+ <>
535
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
536
+ <Video src="/video.mp4" className="size-full" />
537
+ </Timegroup>
538
+ {typeof window !== "undefined" && <Workbench rendering={false} />}
539
+ </>
540
+ );
541
+ };
542
+ ```
543
+
544
+ ## Typical Setup
545
+
546
+ ### Development (main.tsx)
547
+
548
+ ```tsx
549
+ // src/main.tsx (browser only)
550
+ import ReactDOM from "react-dom/client";
551
+ import { Configuration, TimelineRoot } from "@editframe/react";
552
+ import { Video } from "./Video";
553
+ import "@editframe/elements/styles.css";
554
+
555
+ ReactDOM.createRoot(document.getElementById("root")!).render(
556
+ <Configuration mediaEngine="local">
557
+ <TimelineRoot id="root" component={Video} />
558
+ </Configuration>
559
+ );
560
+ ```
561
+
562
+ ### Video Composition (Video.tsx)
563
+
564
+ ```tsx
565
+ // src/Video.tsx (SSR-safe)
566
+ import { Timegroup, Video, Audio, Text } from "@editframe/react/server";
567
+
568
+ export const Video = () => {
569
+ return (
570
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px] bg-black">
571
+ <Timegroup mode="fixed" duration="5s" className="absolute inset-0">
572
+ <Video src="/assets/intro.mp4" className="size-full object-cover" />
573
+ </Timegroup>
574
+ <Timegroup mode="fixed" duration="10s" className="absolute inset-0">
575
+ <Video src="/assets/main.mp4" className="size-full object-cover" />
576
+ <Audio src="/assets/music.mp3" volume={0.3} />
577
+ <Text className="absolute bottom-0 left-0 p-8 text-4xl text-white">
578
+ Hello World
579
+ </Text>
580
+ </Timegroup>
581
+ </Timegroup>
582
+ );
583
+ };
584
+ ```
585
+
586
+ This pattern works in:
587
+ - Browser (with `@editframe/react`)
588
+ - SSR (with `@editframe/react/server`)
589
+ - Static generation (with `@editframe/react/server`)
590
+ <!-- /react-only -->
591
+
592
+ ## Common Patterns
593
+
594
+ ### Hydration After SSR
595
+
596
+ **Server:**
597
+ ```typescript
598
+ // server.tsx
599
+ import { renderToString } from "react-dom/server";
600
+ import { Timegroup, Video } from "@editframe/react/server";
601
+
602
+ const html = renderToString(
603
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
604
+ <Video src="/video.mp4" className="size-full" />
605
+ </Timegroup>
606
+ );
607
+
608
+ // Send html to client
609
+ ```
610
+
611
+ **Client:**
612
+ ```typescript
613
+ // client.tsx
614
+ import { hydrateRoot } from "react-dom/client";
615
+ import { Timegroup, Video } from "@editframe/react"; // Full browser version
616
+
617
+ hydrateRoot(
618
+ document.getElementById("root"),
619
+ <Timegroup mode="sequence" className="w-[1920px] h-[1080px]">
620
+ <Video src="/video.mp4" className="size-full" />
621
+ </Timegroup>
622
+ );
623
+ ```
624
+
625
+ ### Conditional Imports
626
+
627
+ ```typescript
628
+ // utils.ts
629
+ export async function loadEditorComponents() {
630
+ if (typeof window === "undefined") {
631
+ throw new Error("Editor components require browser environment");
632
+ }
633
+
634
+ const { Workbench, Preview, Timeline } = await import("@editframe/react");
635
+ return { Workbench, Preview, Timeline };
636
+ }
637
+ ```
638
+
639
+ ## Troubleshooting
640
+
641
+ ### Error: `customElements is not defined`
642
+
643
+ **Problem:** Importing from main entry point during SSR.
644
+
645
+ **Solution:** Use `/server` entry point:
646
+ ```typescript
647
+ // ❌ Wrong
648
+ import { Timegroup } from "@editframe/react";
649
+
650
+ // ✅ Correct
651
+ import { Timegroup } from "@editframe/react/server";
652
+ ```
653
+
654
+ ### Error: `HTMLElement is not defined`
655
+
656
+ **Problem:** Web Component class definition loaded during SSR.
657
+
658
+ **Solution:** Use dynamic import with `ssr: false` or conditional import.
659
+
660
+ ### Error: `document is not defined`
661
+
662
+ **Problem:** Browser-specific code running on server.
663
+
664
+ **Solution:** Check imports and ensure all browser code is client-only.
665
+
666
+ <!-- react-only -->
667
+ ### Error: `Cannot find module '@editframe/react/server'`
668
+
669
+ **Problem:** Outdated package version.
670
+
671
+ **Solution:**
672
+ ```bash
673
+ npm install @editframe/react@latest
674
+ ```
675
+
676
+ Ensure version is 0.37.0 or higher.
677
+
678
+ ### Error: `window is not defined`
679
+
680
+ **Problem:** Browser code running on server.
681
+
682
+ **Solution:** Use dynamic import with `ssr: false` or check environment:
683
+ ```tsx
684
+ if (typeof window !== "undefined") {
685
+ // Browser-only code
686
+ }
687
+ ```
688
+
689
+ ### Component renders but doesn't work
690
+
691
+ **Problem:** Hydration mismatch between server and client.
692
+
693
+ **Solution:** Ensure identical imports on both sides or use client-only rendering:
694
+ ```tsx
695
+ import dynamic from "next/dynamic";
696
+
697
+ const ClientComponent = dynamic(() => import("./Component"), {
698
+ ssr: false,
699
+ });
700
+ ```
701
+
702
+ ## What About GUI Components?
703
+
704
+ GUI components like `Workbench`, `Preview`, and `Timeline` are **never** SSR-safe because they:
705
+ - Depend on browser APIs (`ResizeObserver`, `IntersectionObserver`, etc.)
706
+ - Use Web Components internally
707
+ - Require canvas and WebGL contexts
708
+ - Need interactive event handling
709
+
710
+ Always use dynamic imports for GUI components:
711
+
712
+ ```tsx
713
+ const Workbench = dynamic(
714
+ () => import("@editframe/react").then((m) => m.Workbench),
715
+ { ssr: false }
716
+ );
717
+ ```
718
+ <!-- /react-only -->
719
+
720
+ ## Package Structure
721
+
722
+ Both packages expose <!-- html-only -->three<!-- /html-only --> entry points:
723
+
724
+ ### @editframe/elements
725
+ ```json
726
+ {
727
+ "exports": {
728
+ ".": "./dist/index.js", // Browser: Full package (Web Components, DOM APIs)
729
+ "./server": "./dist/server.js", // SSR: Types + getRenderInfo only
730
+ "./node": "./dist/node.js" // Node: Same as /server (backward compat)
731
+ }
732
+ }
733
+ ```
734
+
735
+ ### @editframe/react
736
+ ```json
737
+ {
738
+ "exports": {
739
+ ".": "./dist/index.js", // Browser: Full package (all components + hooks)
740
+ "./server": "./dist/server.js", // SSR: Composition components only
741
+ "./r3f": "./dist/r3f/index.js" // Browser: React Three Fiber integration
742
+ }
743
+ }
744
+ ```
745
+
746
+ ## Related
747
+
748
+ - [entry-points.md](references/entry-points.md) - Complete guide to package entry points
749
+ - [r3f.md](references/r3f.md) - React Three Fiber integration
750
+ - [getting-started.md](references/getting-started.md) - Installation and setup
751
+ <!-- react-only -->
752
+ - [configuration.md](references/configuration.md) - Configuration component
753
+ <!-- /react-only -->