@revideo/create 0.5.11-alpha.1102 → 0.5.11-alpha.1104

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 (185) hide show
  1. package/examples/README.md +43 -0
  2. package/examples/avatar-with-background/package.json +27 -0
  3. package/examples/avatar-with-background/src/project.meta +31 -0
  4. package/examples/avatar-with-background/src/project.ts +6 -0
  5. package/examples/avatar-with-background/src/render.ts +14 -0
  6. package/examples/avatar-with-background/src/revideo.d.ts +1 -0
  7. package/examples/avatar-with-background/src/scenes/example.meta +5 -0
  8. package/examples/avatar-with-background/src/scenes/example.tsx +28 -0
  9. package/examples/avatar-with-background/tsconfig.json +9 -0
  10. package/examples/avatar-with-background/vite.config.ts +8 -0
  11. package/examples/default/README.md +19 -0
  12. package/examples/default/package.json +20 -0
  13. package/examples/default/src/project.tsx +56 -0
  14. package/examples/default/src/render.ts +15 -0
  15. package/examples/default/tsconfig.json +10 -0
  16. package/examples/github-stars-celebration/package-lock.json +3833 -0
  17. package/examples/github-stars-celebration/package.json +24 -0
  18. package/examples/github-stars-celebration/src/global.css +1 -0
  19. package/examples/github-stars-celebration/src/project.meta +28 -0
  20. package/examples/github-stars-celebration/src/project.ts +8 -0
  21. package/examples/github-stars-celebration/src/render.ts +15 -0
  22. package/examples/github-stars-celebration/src/revideo.d.ts +1 -0
  23. package/examples/github-stars-celebration/src/scenes/example.meta +5 -0
  24. package/examples/github-stars-celebration/src/scenes/example.tsx +51 -0
  25. package/examples/github-stars-celebration/tsconfig.json +9 -0
  26. package/examples/github-stars-celebration/vite.config.ts +8 -0
  27. package/examples/google-cloud-run-parallelized/README.md +127 -0
  28. package/examples/google-cloud-run-parallelized/render-orchestrator/Dockerfile +56 -0
  29. package/examples/google-cloud-run-parallelized/render-orchestrator/package.json +22 -0
  30. package/examples/google-cloud-run-parallelized/render-orchestrator/src/index.ts +72 -0
  31. package/examples/google-cloud-run-parallelized/render-orchestrator/src/revideo.d.ts +1 -0
  32. package/examples/google-cloud-run-parallelized/render-orchestrator/tsconfig.json +10 -0
  33. package/examples/google-cloud-run-parallelized/render-worker/.gcloudignore +17 -0
  34. package/examples/google-cloud-run-parallelized/render-worker/.puppeteerrc.cjs +9 -0
  35. package/examples/google-cloud-run-parallelized/render-worker/package.json +30 -0
  36. package/examples/google-cloud-run-parallelized/render-worker/src/index.ts +45 -0
  37. package/examples/google-cloud-run-parallelized/render-worker/src/project.meta +31 -0
  38. package/examples/google-cloud-run-parallelized/render-worker/src/project.ts +6 -0
  39. package/examples/google-cloud-run-parallelized/render-worker/src/render.ts +14 -0
  40. package/examples/google-cloud-run-parallelized/render-worker/src/revideo.d.ts +1 -0
  41. package/examples/google-cloud-run-parallelized/render-worker/src/scenes/example.tsx +30 -0
  42. package/examples/google-cloud-run-parallelized/render-worker/tsconfig.json +13 -0
  43. package/examples/google-cloud-run-parallelized/render-worker/vite.config.ts +9 -0
  44. package/examples/logo.svg +6 -0
  45. package/examples/logo_dark.svg +6 -0
  46. package/examples/marketing-templates/README.md +10 -0
  47. package/examples/marketing-templates/marketing-template/package.json +24 -0
  48. package/examples/marketing-templates/marketing-template/src/globals.css +0 -0
  49. package/examples/marketing-templates/marketing-template/src/project.meta +28 -0
  50. package/examples/marketing-templates/marketing-template/src/project.ts +9 -0
  51. package/examples/marketing-templates/marketing-template/src/render.ts +15 -0
  52. package/examples/marketing-templates/marketing-template/src/revideo.d.ts +1 -0
  53. package/examples/marketing-templates/marketing-template/src/scenes/example.meta +5 -0
  54. package/examples/marketing-templates/marketing-template/src/scenes/example.tsx +67 -0
  55. package/examples/marketing-templates/marketing-template/tsconfig.json +9 -0
  56. package/examples/marketing-templates/marketing-template/vite.config.ts +9 -0
  57. package/examples/marketing-templates/multiple-videos-in-one/package.json +24 -0
  58. package/examples/marketing-templates/multiple-videos-in-one/src/project.meta +28 -0
  59. package/examples/marketing-templates/multiple-videos-in-one/src/project.ts +9 -0
  60. package/examples/marketing-templates/multiple-videos-in-one/src/render.ts +15 -0
  61. package/examples/marketing-templates/multiple-videos-in-one/src/revideo.d.ts +1 -0
  62. package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.meta +5 -0
  63. package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.tsx +122 -0
  64. package/examples/marketing-templates/multiple-videos-in-one/tsconfig.json +9 -0
  65. package/examples/marketing-templates/multiple-videos-in-one/vite.config.ts +9 -0
  66. package/examples/minimal-drag-drop/README.md +29 -0
  67. package/examples/minimal-drag-drop/next/app/api/render/route.ts +22 -0
  68. package/examples/minimal-drag-drop/next/app/globals.css +3 -0
  69. package/examples/minimal-drag-drop/next/app/layout.tsx +25 -0
  70. package/examples/minimal-drag-drop/next/app/page.tsx +277 -0
  71. package/examples/minimal-drag-drop/next/next-env.d.ts +5 -0
  72. package/examples/minimal-drag-drop/next/next.config.mjs +4 -0
  73. package/examples/minimal-drag-drop/next/package-lock.json +5577 -0
  74. package/examples/minimal-drag-drop/next/package.json +35 -0
  75. package/examples/minimal-drag-drop/next/postcss.config.js +6 -0
  76. package/examples/minimal-drag-drop/next/public/favicon.ico +0 -0
  77. package/examples/minimal-drag-drop/next/public/next.svg +1 -0
  78. package/examples/minimal-drag-drop/next/public/vercel.svg +1 -0
  79. package/examples/minimal-drag-drop/next/tailwind.config.ts +30 -0
  80. package/examples/minimal-drag-drop/next/tsconfig.json +26 -0
  81. package/examples/minimal-drag-drop/next/utils/parse.ts +35 -0
  82. package/examples/minimal-drag-drop/revideo/package-lock.json +3771 -0
  83. package/examples/minimal-drag-drop/revideo/package.json +24 -0
  84. package/examples/minimal-drag-drop/revideo/src/global.css +1 -0
  85. package/examples/minimal-drag-drop/revideo/src/project.meta +28 -0
  86. package/examples/minimal-drag-drop/revideo/src/project.ts +9 -0
  87. package/examples/minimal-drag-drop/revideo/src/render.ts +15 -0
  88. package/examples/minimal-drag-drop/revideo/src/revideo.d.ts +1 -0
  89. package/examples/minimal-drag-drop/revideo/src/scenes/example.meta +5 -0
  90. package/examples/minimal-drag-drop/revideo/src/scenes/example.tsx +44 -0
  91. package/examples/minimal-drag-drop/revideo/tsconfig.json +9 -0
  92. package/examples/minimal-drag-drop/revideo/vite.config.ts +6 -0
  93. package/examples/parallelized-aws-lambda/.dockerignore +3 -0
  94. package/examples/parallelized-aws-lambda/Dockerfile +21 -0
  95. package/examples/parallelized-aws-lambda/Dockerfile.base +64 -0
  96. package/examples/parallelized-aws-lambda/README.md +197 -0
  97. package/examples/parallelized-aws-lambda/revideo-project/.puppeteerrc.cjs +9 -0
  98. package/examples/parallelized-aws-lambda/revideo-project/package-lock.json +4133 -0
  99. package/examples/parallelized-aws-lambda/revideo-project/package.json +28 -0
  100. package/examples/parallelized-aws-lambda/revideo-project/src/lambda.ts +157 -0
  101. package/examples/parallelized-aws-lambda/revideo-project/src/project.meta +28 -0
  102. package/examples/parallelized-aws-lambda/revideo-project/src/project.ts +7 -0
  103. package/examples/parallelized-aws-lambda/revideo-project/src/render.ts +17 -0
  104. package/examples/parallelized-aws-lambda/revideo-project/src/revideo.d.ts +1 -0
  105. package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.meta +5 -0
  106. package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.tsx +30 -0
  107. package/examples/parallelized-aws-lambda/revideo-project/tsconfig.json +10 -0
  108. package/examples/parallelized-aws-lambda/revideo-project/vite.config.ts +9 -0
  109. package/examples/reddit-post-video/README.md +84 -0
  110. package/examples/reddit-post-video/package-lock.json +2941 -0
  111. package/examples/reddit-post-video/package.json +27 -0
  112. package/examples/reddit-post-video/src/global.css +1 -0
  113. package/examples/reddit-post-video/src/metadata.json +576 -0
  114. package/examples/reddit-post-video/src/project.meta +31 -0
  115. package/examples/reddit-post-video/src/project.ts +9 -0
  116. package/examples/reddit-post-video/src/render.ts +157 -0
  117. package/examples/reddit-post-video/src/revideo.d.ts +1 -0
  118. package/examples/reddit-post-video/src/scenes/example.meta +5 -0
  119. package/examples/reddit-post-video/src/scenes/example.tsx +74 -0
  120. package/examples/reddit-post-video/tsconfig.json +9 -0
  121. package/examples/reddit-post-video/vite.config.ts +6 -0
  122. package/examples/rive-explanation-video/README.md +9 -0
  123. package/examples/rive-explanation-video/package.json +25 -0
  124. package/examples/rive-explanation-video/src/global.css +1 -0
  125. package/examples/rive-explanation-video/src/project.meta +31 -0
  126. package/examples/rive-explanation-video/src/project.ts +8 -0
  127. package/examples/rive-explanation-video/src/render.ts +15 -0
  128. package/examples/rive-explanation-video/src/revideo.d.ts +1 -0
  129. package/examples/rive-explanation-video/src/scenes/example.meta +5 -0
  130. package/examples/rive-explanation-video/src/scenes/example.tsx +218 -0
  131. package/examples/rive-explanation-video/tsconfig.json +9 -0
  132. package/examples/rive-explanation-video/vite.config.ts +8 -0
  133. package/examples/saas-template/.prettierrc +9 -0
  134. package/examples/saas-template/README.md +26 -0
  135. package/examples/saas-template/app/actions.tsx +114 -0
  136. package/examples/saas-template/app/api/render/route.ts +23 -0
  137. package/examples/saas-template/app/globals.css +3 -0
  138. package/examples/saas-template/app/layout.tsx +25 -0
  139. package/examples/saas-template/app/page.tsx +204 -0
  140. package/examples/saas-template/next.config.mjs +4 -0
  141. package/examples/saas-template/package.json +40 -0
  142. package/examples/saas-template/postcss.config.js +6 -0
  143. package/examples/saas-template/revideo/global.css +1 -0
  144. package/examples/saas-template/revideo/project.ts +9 -0
  145. package/examples/saas-template/revideo/scene.tsx +179 -0
  146. package/examples/saas-template/tailwind.config.ts +30 -0
  147. package/examples/saas-template/tsconfig.json +27 -0
  148. package/examples/saas-template/utils/parse.ts +35 -0
  149. package/examples/stitching-videos/README.md +7 -0
  150. package/examples/stitching-videos/package.json +23 -0
  151. package/examples/stitching-videos/src/project.meta +28 -0
  152. package/examples/stitching-videos/src/project.ts +20 -0
  153. package/examples/stitching-videos/src/render.ts +27 -0
  154. package/examples/stitching-videos/src/revideo.d.ts +1 -0
  155. package/examples/stitching-videos/src/scenes/example.tsx +30 -0
  156. package/examples/stitching-videos/tsconfig.json +9 -0
  157. package/examples/stitching-videos/vite.config.ts +8 -0
  158. package/examples/three-js-example/README.md +8 -0
  159. package/examples/three-js-example/package-lock.json +2753 -0
  160. package/examples/three-js-example/package.json +25 -0
  161. package/examples/three-js-example/src/components/Three.ts +166 -0
  162. package/examples/three-js-example/src/global.css +1 -0
  163. package/examples/three-js-example/src/project.meta +31 -0
  164. package/examples/three-js-example/src/project.ts +8 -0
  165. package/examples/three-js-example/src/render.ts +15 -0
  166. package/examples/three-js-example/src/revideo.d.ts +1 -0
  167. package/examples/three-js-example/src/scenes/basic3D.meta +5 -0
  168. package/examples/three-js-example/src/scenes/basic3D.tsx +89 -0
  169. package/examples/three-js-example/tsconfig.json +9 -0
  170. package/examples/three-js-example/vite.config.ts +6 -0
  171. package/examples/youtube-shorts/README.md +65 -0
  172. package/examples/youtube-shorts/package-lock.json +3881 -0
  173. package/examples/youtube-shorts/package.json +30 -0
  174. package/examples/youtube-shorts/src/get-assets.ts +34 -0
  175. package/examples/youtube-shorts/src/global.css +3 -0
  176. package/examples/youtube-shorts/src/metadata.json +635 -0
  177. package/examples/youtube-shorts/src/project.meta +28 -0
  178. package/examples/youtube-shorts/src/project.ts +9 -0
  179. package/examples/youtube-shorts/src/render.ts +12 -0
  180. package/examples/youtube-shorts/src/revideo.d.ts +1 -0
  181. package/examples/youtube-shorts/src/scenes/example.tsx +224 -0
  182. package/examples/youtube-shorts/src/utils.ts +123 -0
  183. package/examples/youtube-shorts/tsconfig.json +9 -0
  184. package/examples/youtube-shorts/vite.config.ts +8 -0
  185. package/package.json +9 -9
@@ -0,0 +1,277 @@
1
+ 'use client';
2
+
3
+ import {Player} from '@revideo/player-react';
4
+ import {useState, useEffect} from 'react';
5
+ import {LoaderCircle} from 'lucide-react';
6
+ import { parseStream } from '../utils/parse';
7
+ import {Player as CorePlayer} from '@revideo/core';
8
+ import {Scene2D, Shape} from '@revideo/2d';
9
+
10
+
11
+ function Button({
12
+ children,
13
+ loading,
14
+ onClick,
15
+ }: {
16
+ children: React.ReactNode;
17
+ loading: boolean;
18
+ onClick: () => void;
19
+ }) {
20
+ return (
21
+ <button
22
+ className="text-sm flex items-center gap-x-2 rounded-md p-2 bg-gray-200 text-gray-700 hover:bg-gray-300"
23
+ onClick={() => onClick()}
24
+ disabled={loading}
25
+ >
26
+ {loading && <LoaderCircle className="animate-spin h-4 w-4 text-gray-700" />}
27
+ {children}
28
+ </button>
29
+ );
30
+ }
31
+
32
+ export default function Home() {
33
+ const [nodes, setNodes] = useState<Map<string, any>>(new Map([
34
+ ['txt', { text: "Text 1", x: 0, y: 0 }]
35
+ ]));
36
+ const [draggingNode, setDraggingNode] = useState<Shape | null>(null);
37
+ const [dragOffset, setDragOffset] = useState<{ x: number, y: number } | null>(null);
38
+ const [playerRect, setPlayerRect] = useState<DOMRect | null>(null);
39
+ const [corePlayer, setCorePlayer] = useState<CorePlayer | null>(null);
40
+ const [transformMatrix, setTransformMatrix] = useState<DOMMatrix | null>(null);
41
+
42
+ const [renderLoading, setRenderLoading] = useState(false);
43
+ const [progress, setProgress] = useState(0);
44
+ const [downloadUrl, setDownloadUrl] = useState<string | null>(null);
45
+
46
+ const [playing, setPlaying] = useState<boolean>(false);
47
+ const [dimensions, setDimensions] = useState<{x: number, y: number}>({ x: 1920, y: 1080 });
48
+ const [selectedNode, setSelectedNode] = useState<{
49
+ key: string;
50
+ x: number;
51
+ y: number;
52
+ width: number;
53
+ height: number;
54
+ } | null>(null);
55
+
56
+ useEffect(() => {
57
+ if (playerRect) {
58
+ setTransformMatrix(createTransformationMatrix(playerRect, dimensions));
59
+ }
60
+ }, [playerRect, dimensions]);
61
+
62
+ const handlePlayerReady = (player: CorePlayer) => {
63
+ setCorePlayer(player);
64
+ };
65
+
66
+ const addTextNode = () => {
67
+ setNodes(prevNodes => {
68
+ const newNodes = new Map(prevNodes);
69
+ const newKey = `txt_${newNodes.size+1}`;
70
+ newNodes.set(newKey, { text: `Text ${newNodes.size+1}`, x: 0, y: 0 });
71
+ return newNodes;
72
+ });
73
+ };
74
+
75
+ const handlePointerDown = (event: React.PointerEvent<HTMLDivElement>) => {
76
+ if (playerRect && transformMatrix) {
77
+ const { x: playerX, y: playerY } = transformPoint(
78
+ event.clientX,
79
+ event.clientY,
80
+ transformMatrix
81
+ );
82
+
83
+ let hitNode = (corePlayer?.playback.currentScene as Scene2D).getNodeByPosition(playerX, playerY) as Shape;
84
+ while (hitNode) {
85
+ // We want to avoid getting TxtLeaf nodes, but only their parent Txt nodes
86
+ if (nodes.has(hitNode.key)) {
87
+ setDraggingNode(hitNode);
88
+ const node = nodes.get(hitNode.key);
89
+ setDragOffset({ x: playerX - node.x, y: playerY - node.y });
90
+
91
+ const position = hitNode.position();
92
+ const { x, y } = transformPoint(position.x+dimensions.x/2, position.y+dimensions.y/2, transformMatrix.inverse());
93
+
94
+ setSelectedNode({
95
+ key: hitNode.key,
96
+ x: x,
97
+ y: y,
98
+ width: selectedNode?.width || hitNode.width() / transformMatrix.a,
99
+ height: selectedNode?.height || hitNode.height() / transformMatrix.d
100
+ });
101
+ return;
102
+ }
103
+ hitNode = hitNode.parent() as Shape;
104
+ }
105
+ setSelectedNode(null);
106
+ };
107
+ }
108
+
109
+ const handlePointerMove = (event: React.PointerEvent<HTMLDivElement>) => {
110
+ if (draggingNode && playerRect && transformMatrix) {
111
+ const { x: playerX, y: playerY } = transformPoint(
112
+ event.clientX,
113
+ event.clientY,
114
+ transformMatrix
115
+ );
116
+
117
+ setNodes(prevNodes => {
118
+ const newNodes = new Map(prevNodes);
119
+ const node = newNodes.get(draggingNode.key);
120
+ if (node && dragOffset) {
121
+ node.x = playerX - dragOffset.x;
122
+ node.y = playerY - dragOffset.y;
123
+
124
+ const { x, y } = transformPoint(node.x+dimensions.x/2, node.y+dimensions.y/2, transformMatrix.inverse());
125
+ setSelectedNode({
126
+ key: draggingNode.key,
127
+ x: x,
128
+ y: y,
129
+ width: selectedNode?.width || draggingNode.width() / transformMatrix.a,
130
+ height: selectedNode?.height || draggingNode.height() / transformMatrix.d,
131
+ });
132
+
133
+ }
134
+ return newNodes;
135
+ });
136
+ }
137
+ };
138
+
139
+ function createTransformationMatrix(
140
+ playerRect: DOMRect,
141
+ dimensions: { x: number; y: number }
142
+ ): DOMMatrix {
143
+ const scaleX = dimensions.x / playerRect.width;
144
+ const scaleY = dimensions.y / playerRect.height;
145
+
146
+ const matrix = new DOMMatrix();
147
+ matrix.scaleSelf(scaleX, scaleY);
148
+ matrix.translateSelf(-playerRect.left, -playerRect.top);
149
+
150
+ return matrix;
151
+ }
152
+
153
+ function transformPoint(
154
+ x: number,
155
+ y: number,
156
+ matrix: DOMMatrix
157
+ ): { x: number; y: number } {
158
+ const point = new DOMPoint(x, y);
159
+ const transformedPoint = point.matrixTransform(matrix);
160
+ return { x: transformedPoint.x, y: transformedPoint.y };
161
+ }
162
+
163
+ /**
164
+ * Render the video.
165
+ */
166
+ async function render() {
167
+ setRenderLoading(true);
168
+ const res = await fetch('/api/render', {
169
+ method: 'POST',
170
+ headers: {
171
+ 'Content-Type': 'application/json',
172
+ },
173
+ body: JSON.stringify({
174
+ variables: {
175
+ nodes: Object.fromEntries(nodes)
176
+ },
177
+ streamProgress: true,
178
+ }),
179
+ }).catch((e) => console.log(e));
180
+
181
+ if (!res) {
182
+ alert('Failed to render video.');
183
+ return;
184
+ }
185
+
186
+ const downloadUrl = await parseStream(res.body!.getReader(), (p) => setProgress(p));
187
+ setRenderLoading(false);
188
+ setDownloadUrl(downloadUrl);
189
+ }
190
+
191
+ return (
192
+ <>
193
+ <div className="m-auto p-12 max-w-6xl flex flex-col gap-y-4">
194
+ <div
195
+ className="rounded-lg overflow-hidden w-[100%] py-20 bg-gray-100 flex items-center justify-center"
196
+ onPointerDown={handlePointerDown}
197
+ onPointerMove={handlePointerMove}
198
+ onPointerUp={() => {
199
+ setDraggingNode(null);
200
+ setDragOffset(null);
201
+ }}
202
+ >
203
+ <div className='w-[80%] h-[80%]'>
204
+ <Player
205
+ src="http://localhost:4000/player/"
206
+ controls={false}
207
+ playing={playing}
208
+ width={dimensions.x}
209
+ height={dimensions.y}
210
+ variables={{
211
+ nodes: Object.fromEntries(nodes),
212
+ }}
213
+ onPlayerReady={handlePlayerReady}
214
+ onPlayerResize={(rect: DOMRect) => {
215
+ setPlayerRect(rect);
216
+ }}
217
+ />
218
+ {(selectedNode && playerRect) && (
219
+ <div
220
+ className="absolute border-2 border-[#5bbad5] pointer-events-none"
221
+ style={{
222
+ left: `${selectedNode.x-selectedNode.width/2}px`,
223
+ top: `${selectedNode.y-selectedNode.height/2}px`,
224
+ width: `${selectedNode.width}px`,
225
+ height: `${selectedNode.height}px`,
226
+ }}
227
+ />
228
+ )}
229
+
230
+ </div>
231
+ </div>
232
+ <div className="flex gap-x-4">
233
+ {/* Progress bar */}
234
+ <div className="text-sm flex-1 bg-gray-100 rounded-md overflow-hidden">
235
+ <div
236
+ className="text-gray-600 bg-gray-400 h-full flex items-center px-4 transition-all transition-200"
237
+ style={{
238
+ width: `${Math.round(progress * 100)}%`,
239
+ }}
240
+ >
241
+ {Math.round(progress * 100)}%
242
+ </div>
243
+ </div>
244
+ {downloadUrl ? (
245
+ <a
246
+ href={downloadUrl}
247
+ download
248
+ className="text-sm flex items-center gap-x-2 rounded-md p-2 bg-green-200 text-gray-700 hover:bg-gray-300"
249
+ >
250
+ Download video
251
+ </a>
252
+ ) : (
253
+ <>
254
+ <Button
255
+ loading={false}
256
+ onClick={() => {
257
+ setPlaying(!playing);
258
+ setSelectedNode(null);
259
+ }}
260
+ >
261
+ {playing ? "Pause" : "Play"}
262
+ </Button>
263
+
264
+ <Button onClick={addTextNode} loading={false}>
265
+ Add Text
266
+ </Button>
267
+
268
+ <Button onClick={() => render()} loading={renderLoading}>
269
+ Render video
270
+ </Button>
271
+ </>
272
+ )}
273
+ </div>
274
+ </div>
275
+ </>
276
+ );
277
+ }
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/basic-features/typescript for more information.
@@ -0,0 +1,4 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {};
3
+
4
+ export default nextConfig;