@revideo/create 0.5.8-beta.1082 → 0.5.9-alpha.1086

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 (175) hide show
  1. package/examples/README.md +43 -0
  2. package/examples/avatar-with-background/package-lock.json +3223 -0
  3. package/examples/avatar-with-background/package.json +27 -0
  4. package/examples/avatar-with-background/src/project.meta +31 -0
  5. package/examples/avatar-with-background/src/project.ts +6 -0
  6. package/examples/avatar-with-background/src/render.ts +14 -0
  7. package/examples/avatar-with-background/src/revideo.d.ts +1 -0
  8. package/examples/avatar-with-background/src/scenes/example.meta +5 -0
  9. package/examples/avatar-with-background/src/scenes/example.tsx +27 -0
  10. package/examples/avatar-with-background/tsconfig.json +9 -0
  11. package/examples/avatar-with-background/vite.config.ts +8 -0
  12. package/examples/default/package.json +24 -0
  13. package/examples/default/src/project.meta +31 -0
  14. package/examples/default/src/project.ts +7 -0
  15. package/examples/default/src/render.ts +15 -0
  16. package/examples/default/src/revideo.d.ts +1 -0
  17. package/examples/default/src/scenes/example.tsx +38 -0
  18. package/examples/default/tsconfig.json +9 -0
  19. package/examples/default/vite.config.ts +8 -0
  20. package/examples/github-stars-celebration/package-lock.json +3833 -0
  21. package/examples/github-stars-celebration/package.json +24 -0
  22. package/examples/github-stars-celebration/src/global.css +1 -0
  23. package/examples/github-stars-celebration/src/project.meta +28 -0
  24. package/examples/github-stars-celebration/src/project.ts +8 -0
  25. package/examples/github-stars-celebration/src/render.ts +15 -0
  26. package/examples/github-stars-celebration/src/revideo.d.ts +1 -0
  27. package/examples/github-stars-celebration/src/scenes/example.meta +5 -0
  28. package/examples/github-stars-celebration/src/scenes/example.tsx +51 -0
  29. package/examples/github-stars-celebration/tsconfig.json +9 -0
  30. package/examples/github-stars-celebration/vite.config.ts +8 -0
  31. package/examples/google-cloud-run-parallelized/README.md +127 -0
  32. package/examples/google-cloud-run-parallelized/render-orchestrator/Dockerfile +56 -0
  33. package/examples/google-cloud-run-parallelized/render-orchestrator/package.json +22 -0
  34. package/examples/google-cloud-run-parallelized/render-orchestrator/src/index.ts +72 -0
  35. package/examples/google-cloud-run-parallelized/render-orchestrator/src/revideo.d.ts +1 -0
  36. package/examples/google-cloud-run-parallelized/render-orchestrator/tsconfig.json +10 -0
  37. package/examples/google-cloud-run-parallelized/render-worker/.gcloudignore +17 -0
  38. package/examples/google-cloud-run-parallelized/render-worker/.puppeteerrc.cjs +9 -0
  39. package/examples/google-cloud-run-parallelized/render-worker/package.json +30 -0
  40. package/examples/google-cloud-run-parallelized/render-worker/src/index.ts +45 -0
  41. package/examples/google-cloud-run-parallelized/render-worker/src/project.meta +31 -0
  42. package/examples/google-cloud-run-parallelized/render-worker/src/project.ts +6 -0
  43. package/examples/google-cloud-run-parallelized/render-worker/src/render.ts +14 -0
  44. package/examples/google-cloud-run-parallelized/render-worker/src/revideo.d.ts +1 -0
  45. package/examples/google-cloud-run-parallelized/render-worker/src/scenes/example.tsx +30 -0
  46. package/examples/google-cloud-run-parallelized/render-worker/tsconfig.json +13 -0
  47. package/examples/google-cloud-run-parallelized/render-worker/vite.config.ts +9 -0
  48. package/examples/logo.svg +6 -0
  49. package/examples/logo_dark.svg +6 -0
  50. package/examples/marketing-templates/README.md +10 -0
  51. package/examples/marketing-templates/marketing-template/package-lock.json +3824 -0
  52. package/examples/marketing-templates/marketing-template/package.json +24 -0
  53. package/examples/marketing-templates/marketing-template/src/globals.css +0 -0
  54. package/examples/marketing-templates/marketing-template/src/project.meta +28 -0
  55. package/examples/marketing-templates/marketing-template/src/project.ts +9 -0
  56. package/examples/marketing-templates/marketing-template/src/render.ts +15 -0
  57. package/examples/marketing-templates/marketing-template/src/revideo.d.ts +1 -0
  58. package/examples/marketing-templates/marketing-template/src/scenes/example.meta +5 -0
  59. package/examples/marketing-templates/marketing-template/src/scenes/example.tsx +67 -0
  60. package/examples/marketing-templates/marketing-template/tsconfig.json +9 -0
  61. package/examples/marketing-templates/marketing-template/vite.config.ts +9 -0
  62. package/examples/marketing-templates/multiple-videos-in-one/package-lock.json +3824 -0
  63. package/examples/marketing-templates/multiple-videos-in-one/package.json +24 -0
  64. package/examples/marketing-templates/multiple-videos-in-one/src/project.meta +28 -0
  65. package/examples/marketing-templates/multiple-videos-in-one/src/project.ts +9 -0
  66. package/examples/marketing-templates/multiple-videos-in-one/src/render.ts +15 -0
  67. package/examples/marketing-templates/multiple-videos-in-one/src/revideo.d.ts +1 -0
  68. package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.meta +5 -0
  69. package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.tsx +122 -0
  70. package/examples/marketing-templates/multiple-videos-in-one/tsconfig.json +9 -0
  71. package/examples/marketing-templates/multiple-videos-in-one/vite.config.ts +9 -0
  72. package/examples/parallelized-aws-lambda/.dockerignore +3 -0
  73. package/examples/parallelized-aws-lambda/Dockerfile +21 -0
  74. package/examples/parallelized-aws-lambda/Dockerfile.base +64 -0
  75. package/examples/parallelized-aws-lambda/README.md +197 -0
  76. package/examples/parallelized-aws-lambda/revideo-project/.puppeteerrc.cjs +9 -0
  77. package/examples/parallelized-aws-lambda/revideo-project/package-lock.json +4133 -0
  78. package/examples/parallelized-aws-lambda/revideo-project/package.json +31 -0
  79. package/examples/parallelized-aws-lambda/revideo-project/src/lambda.ts +144 -0
  80. package/examples/parallelized-aws-lambda/revideo-project/src/project.meta +28 -0
  81. package/examples/parallelized-aws-lambda/revideo-project/src/project.ts +7 -0
  82. package/examples/parallelized-aws-lambda/revideo-project/src/render.ts +16 -0
  83. package/examples/parallelized-aws-lambda/revideo-project/src/revideo.d.ts +1 -0
  84. package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.meta +5 -0
  85. package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.tsx +29 -0
  86. package/examples/parallelized-aws-lambda/revideo-project/tsconfig.json +10 -0
  87. package/examples/parallelized-aws-lambda/revideo-project/vite.config.ts +9 -0
  88. package/examples/reddit-post-video/README.md +84 -0
  89. package/examples/reddit-post-video/package-lock.json +2941 -0
  90. package/examples/reddit-post-video/package.json +27 -0
  91. package/examples/reddit-post-video/src/global.css +1 -0
  92. package/examples/reddit-post-video/src/metadata.json +576 -0
  93. package/examples/reddit-post-video/src/project.meta +31 -0
  94. package/examples/reddit-post-video/src/project.ts +9 -0
  95. package/examples/reddit-post-video/src/render.ts +157 -0
  96. package/examples/reddit-post-video/src/revideo.d.ts +1 -0
  97. package/examples/reddit-post-video/src/scenes/example.meta +5 -0
  98. package/examples/reddit-post-video/src/scenes/example.tsx +74 -0
  99. package/examples/reddit-post-video/tsconfig.json +9 -0
  100. package/examples/reddit-post-video/vite.config.ts +6 -0
  101. package/examples/rive-explanation-video/README.md +9 -0
  102. package/examples/rive-explanation-video/package-lock.json +3706 -0
  103. package/examples/rive-explanation-video/package.json +25 -0
  104. package/examples/rive-explanation-video/src/global.css +1 -0
  105. package/examples/rive-explanation-video/src/project.meta +31 -0
  106. package/examples/rive-explanation-video/src/project.ts +8 -0
  107. package/examples/rive-explanation-video/src/render.ts +15 -0
  108. package/examples/rive-explanation-video/src/revideo.d.ts +1 -0
  109. package/examples/rive-explanation-video/src/scenes/example.meta +5 -0
  110. package/examples/rive-explanation-video/src/scenes/example.tsx +218 -0
  111. package/examples/rive-explanation-video/tsconfig.json +9 -0
  112. package/examples/rive-explanation-video/vite.config.ts +8 -0
  113. package/examples/saas-template/.prettierrc +9 -0
  114. package/examples/saas-template/README.md +28 -0
  115. package/examples/saas-template/next/app/actions.tsx +113 -0
  116. package/examples/saas-template/next/app/api/render/route.ts +22 -0
  117. package/examples/saas-template/next/app/globals.css +3 -0
  118. package/examples/saas-template/next/app/layout.tsx +25 -0
  119. package/examples/saas-template/next/app/page.tsx +187 -0
  120. package/examples/saas-template/next/next.config.mjs +4 -0
  121. package/examples/saas-template/next/package.json +34 -0
  122. package/examples/saas-template/next/postcss.config.js +6 -0
  123. package/examples/saas-template/next/public/favicon.ico +0 -0
  124. package/examples/saas-template/next/public/next.svg +1 -0
  125. package/examples/saas-template/next/public/vercel.svg +1 -0
  126. package/examples/saas-template/next/tailwind.config.ts +30 -0
  127. package/examples/saas-template/next/tsconfig.json +26 -0
  128. package/examples/saas-template/next/utils/parse.ts +35 -0
  129. package/examples/saas-template/revideo/package.json +24 -0
  130. package/examples/saas-template/revideo/src/global.css +1 -0
  131. package/examples/saas-template/revideo/src/project.meta +27 -0
  132. package/examples/saas-template/revideo/src/project.ts +9 -0
  133. package/examples/saas-template/revideo/src/render.ts +15 -0
  134. package/examples/saas-template/revideo/src/revideo.d.ts +1 -0
  135. package/examples/saas-template/revideo/src/scenes/example.meta +5 -0
  136. package/examples/saas-template/revideo/src/scenes/example.tsx +178 -0
  137. package/examples/saas-template/revideo/tsconfig.json +9 -0
  138. package/examples/saas-template/revideo/vite.config.ts +6 -0
  139. package/examples/stitching-videos/README.md +7 -0
  140. package/examples/stitching-videos/package-lock.json +2801 -0
  141. package/examples/stitching-videos/package.json +23 -0
  142. package/examples/stitching-videos/src/project.meta +28 -0
  143. package/examples/stitching-videos/src/project.ts +20 -0
  144. package/examples/stitching-videos/src/render.ts +26 -0
  145. package/examples/stitching-videos/src/revideo.d.ts +1 -0
  146. package/examples/stitching-videos/src/scenes/example.tsx +30 -0
  147. package/examples/stitching-videos/tsconfig.json +9 -0
  148. package/examples/stitching-videos/vite.config.ts +8 -0
  149. package/examples/three-js-example/README.md +8 -0
  150. package/examples/three-js-example/package-lock.json +2753 -0
  151. package/examples/three-js-example/package.json +25 -0
  152. package/examples/three-js-example/src/components/Three.ts +166 -0
  153. package/examples/three-js-example/src/global.css +1 -0
  154. package/examples/three-js-example/src/project.meta +31 -0
  155. package/examples/three-js-example/src/project.ts +8 -0
  156. package/examples/three-js-example/src/render.ts +15 -0
  157. package/examples/three-js-example/src/revideo.d.ts +1 -0
  158. package/examples/three-js-example/src/scenes/basic3D.meta +5 -0
  159. package/examples/three-js-example/src/scenes/basic3D.tsx +89 -0
  160. package/examples/three-js-example/tsconfig.json +9 -0
  161. package/examples/three-js-example/vite.config.ts +6 -0
  162. package/examples/youtube-shorts/README.md +65 -0
  163. package/examples/youtube-shorts/package-lock.json +3914 -0
  164. package/examples/youtube-shorts/package.json +30 -0
  165. package/examples/youtube-shorts/src/global.css +3 -0
  166. package/examples/youtube-shorts/src/metadata.json +635 -0
  167. package/examples/youtube-shorts/src/project.meta +28 -0
  168. package/examples/youtube-shorts/src/project.ts +9 -0
  169. package/examples/youtube-shorts/src/render.ts +43 -0
  170. package/examples/youtube-shorts/src/revideo.d.ts +1 -0
  171. package/examples/youtube-shorts/src/scenes/example.tsx +211 -0
  172. package/examples/youtube-shorts/src/utils.ts +123 -0
  173. package/examples/youtube-shorts/tsconfig.json +9 -0
  174. package/examples/youtube-shorts/vite.config.ts +8 -0
  175. package/package.json +9 -9
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "rive-explanation-docs",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "scripts": {
6
+ "start": "vite",
7
+ "serve": "vite",
8
+ "build": "tsc && vite build",
9
+ "render": "tsc && node dist/render.js"
10
+ },
11
+ "dependencies": {
12
+ "@lezer/javascript": "^1.4.17",
13
+ "@revideo/2d": "^0.5.2",
14
+ "@revideo/core": "^0.5.2",
15
+ "@revideo/ffmpeg": "^0.5.2",
16
+ "@revideo/renderer": "^0.5.2",
17
+ "@revideo/vite-plugin": "^0.5.2"
18
+ },
19
+ "devDependencies": {
20
+ "@revideo/cli": "^0.5.2",
21
+ "@revideo/ui": "^0.5.2",
22
+ "typescript": "5.5.4",
23
+ "vite": "^4.5"
24
+ }
25
+ }
@@ -0,0 +1 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Lexend:wght@100..900&display=swap');
@@ -0,0 +1,31 @@
1
+ {
2
+ "version": 0,
3
+ "shared": {
4
+ "background": "rgb(255,255,255)",
5
+ "range": [
6
+ 0,
7
+ null
8
+ ],
9
+ "size": {
10
+ "x": 1920,
11
+ "y": 1080
12
+ },
13
+ "audioOffset": 0
14
+ },
15
+ "preview": {
16
+ "fps": 30,
17
+ "resolutionScale": 1
18
+ },
19
+ "rendering": {
20
+ "fps": 30,
21
+ "resolutionScale": 1,
22
+ "colorSpace": "srgb",
23
+ "exporter": {
24
+ "name": "@revideo/core/wasm",
25
+ "options": {
26
+ "fastStart": true,
27
+ "includeAudio": true
28
+ }
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,8 @@
1
+ import {makeProject} from '@revideo/core';
2
+ import example from './scenes/example?scene';
3
+
4
+ import './global.css'
5
+
6
+ export default makeProject({
7
+ scenes: [example],
8
+ });
@@ -0,0 +1,15 @@
1
+ import {renderVideo} from '@revideo/renderer';
2
+
3
+ async function render() {
4
+ console.log('Rendering video...');
5
+
6
+ // This is the main function that renders the video
7
+ const file = await renderVideo({
8
+ projectFile: './src/project.ts',
9
+ settings: {logProgress: true},
10
+ });
11
+
12
+ console.log(`Rendered video to ${file}`);
13
+ }
14
+
15
+ render();
@@ -0,0 +1 @@
1
+ /// <reference types="@revideo/core/project" />
@@ -0,0 +1,5 @@
1
+ {
2
+ "version": 0,
3
+ "timeEvents": [],
4
+ "seed": 4079423384
5
+ }
@@ -0,0 +1,218 @@
1
+ import { waitFor, createRef, all, Reference, chain } from '@revideo/core';
2
+ import {
3
+ Img,
4
+ makeScene2D,
5
+ Rive,
6
+ Txt,
7
+ Layout,
8
+ LezerHighlighter, Code, word, lines, Rect,
9
+ View2D
10
+ } from '@revideo/2d';
11
+ import {parser} from '@lezer/javascript';
12
+ import {tags} from '@lezer/highlight';
13
+ import {HighlightStyle} from '@codemirror/language';
14
+
15
+ const MyStyle = HighlightStyle.define([
16
+ {
17
+ tag: tags.comment,
18
+ color: '#8E908C',
19
+ },
20
+ {
21
+ tag: [tags.variableName, tags.self, tags.propertyName, tags.attributeName, tags.regexp],
22
+ color: '#C82829',
23
+ },
24
+ {
25
+ tag: [tags.number, tags.bool, tags.null],
26
+ color: '#F5871F',
27
+ },
28
+ {
29
+ tag: [tags.className, tags.typeName, tags.definition(tags.typeName)],
30
+ color: '#C99E00',
31
+ },
32
+ {
33
+ tag: [tags.string, tags.special(tags.brace)],
34
+ color: '#718C00',
35
+ },
36
+ {
37
+ tag: tags.operator,
38
+ color: '#3E999F',
39
+ },
40
+ {
41
+ tag: [tags.definition(tags.propertyName), tags.function(tags.variableName)],
42
+ color: '#4271AE',
43
+ },
44
+ {
45
+ tag: tags.keyword,
46
+ color: '#8959A8',
47
+ },
48
+ {
49
+ tag: tags.derefOperator,
50
+ color: '#4D4D4C',
51
+ },
52
+ {
53
+ tag: tags.bracket,
54
+ color: "grey"
55
+ },
56
+ {
57
+ tag: tags.separator,
58
+ color: "grey"
59
+ },
60
+ {
61
+ tag: tags.punctuation,
62
+ color: "grey"
63
+ },
64
+ {
65
+ tag: tags.typeOperator,
66
+ color: "grey"
67
+ }
68
+ ]);
69
+
70
+ Code.defaultHighlighter = new LezerHighlighter(
71
+ parser.configure({
72
+ dialect: 'jsx ts',
73
+ }),
74
+ MyStyle
75
+ );
76
+
77
+
78
+ export default makeScene2D(function* (view) {
79
+
80
+ const textRef = createRef<Txt>();
81
+ view.add(
82
+ <Txt fontFamily={"Lexend"} fontSize={100} fontWeight={600} ref={textRef}/>
83
+ );
84
+
85
+ yield* all(textRef().text("Rive Animations in Revideo", 1.25))
86
+ yield* all(
87
+ textRef().scale(0.75, 0.75),
88
+ textRef().position.y(-400, 0.75)
89
+ )
90
+ yield* waitFor(0.25);
91
+
92
+ const codeRef= createRef<Code>();
93
+ const videoBoxRef = createRef<Layout>();
94
+ view.add(<Layout opacity={0} position={[550, 100]} size={[600, 600]} ref={videoBoxRef} />);
95
+ view.add(
96
+ <Code
97
+ ref={codeRef}
98
+ textAlign={"left"}
99
+ fontSize={35}
100
+ x={-400}
101
+ y={100}
102
+ opacity={0}
103
+ fontFamily={'JetBrains Mono, monospace'}
104
+ code={
105
+ `export default makeScene2D(function* (view){
106
+ yield view.add(
107
+ <Img
108
+ src={"/sf.png"}
109
+ size={["100%", "100%"]}
110
+ />
111
+ );
112
+
113
+ });
114
+ `
115
+ }/>);
116
+
117
+ videoBoxRef().add(
118
+ <Img
119
+ src={"https://revideo-example-assets.s3.amazonaws.com/sf.png"}
120
+ size={[videoBoxRef().width(), videoBoxRef().height()]}
121
+ />
122
+ );
123
+
124
+ yield* all(
125
+ codeRef().opacity(1, 0.75),
126
+ videoBoxRef().opacity(1, 0.75)
127
+ );
128
+ yield* waitFor(0.5);
129
+
130
+ const riveRef = createRef<Rive>();
131
+ videoBoxRef().add(
132
+ <Rive
133
+ src={"https://revideo-example-assets.s3.amazonaws.com/emoji.riv"}
134
+ animationId={1}
135
+ size={[600, 600]}
136
+ opacity={0}
137
+ ref={riveRef}
138
+ />
139
+ );
140
+ yield* all(codeRef().code.insert([8, 0],
141
+ `\n yield view.add(
142
+ <Rive
143
+ src={"/emoji.riv"}
144
+ animationId={1}
145
+ size={[600, 600]}
146
+ />
147
+ );\n`, 1),
148
+ riveRef().opacity(1, 1)
149
+ );
150
+
151
+ yield* waitFor(1);
152
+
153
+ yield* codeRef().selection(lines(11, 13), 1),
154
+ yield replaceRive(videoBoxRef, riveRef)
155
+ yield* all(
156
+ codeRef().code.replace(word(11, 17, 5), "dog", 2),
157
+ codeRef().code.replace(word(13, 17, 3), "900", 2),
158
+ );
159
+
160
+ yield* codeRef().selection(lines(0, 17), 1);
161
+
162
+ yield* waitFor(1);
163
+ yield* all(
164
+ codeRef().opacity(0, 1),
165
+ videoBoxRef().opacity(0, 1),
166
+ textRef().opacity(0, 1)
167
+ );
168
+
169
+ yield* waitFor(0.5);
170
+ yield* logoAnimation(view);
171
+ });
172
+
173
+ function* replaceRive(box: Reference<Layout>, rive: Reference<Rive>){
174
+ yield* rive().opacity(0, 1);
175
+ rive().remove();
176
+
177
+ const riveRef = createRef<Rive>();
178
+ box().add(
179
+ <Rive
180
+ src={"https://revideo-example-assets.s3.amazonaws.com/dog.riv"}
181
+ size={[1000, 600]}
182
+ opacity={0}
183
+ animationId={1}
184
+ ref={riveRef}
185
+ />
186
+ );
187
+
188
+ yield* riveRef().opacity(1, 1);
189
+ yield* waitFor(5);
190
+ }
191
+
192
+ function* logoAnimation(view: View2D){
193
+ const block1 = createRef<Rect>()
194
+ const block2 = createRef<Rect>()
195
+ const block3 = createRef<Rect>()
196
+ const blocks = createRef<Layout>();
197
+ const logoText = createRef<Txt>();
198
+ view.add(
199
+ <>
200
+ <Layout ref={blocks} x={-600}>
201
+ <Rect fill={"#151515"} height={60} y={-80} x={-620} width={180} radius={9.3} ref={block1} />
202
+ <Rect fill={"#151515"} height={60} width={180} x={-540} radius={9.3} ref={block2} />
203
+ <Rect fill={"#151515"} height={60} width={180} x={-460} y={80} radius={9.3} ref={block3} />
204
+ <Txt ref={logoText} fontFamily={"Lexend"} x={53+757.5} y={20} fontSize={300} letterSpacing={-4} fontWeight={700} text={""}/>
205
+ </Layout>
206
+ </>
207
+ );
208
+
209
+ yield* all(
210
+ block1().position.x(-80, 0.5),
211
+ chain(waitFor(0.1), block2().position.x(0, 0.4)),
212
+ chain(waitFor(0.2), block3().position.x(80, 0.3)),
213
+ )
214
+
215
+ yield* logoText().text("revideo", 1);
216
+
217
+ yield* waitFor(1);
218
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@revideo/2d/tsconfig.project.json",
3
+ "include": ["src"],
4
+ "compilerOptions": {
5
+ "noEmit": false,
6
+ "outDir": "dist",
7
+ "module": "CommonJS"
8
+ }
9
+ }
@@ -0,0 +1,8 @@
1
+ import {defineConfig} from 'vite';
2
+ import motionCanvas from '@revideo/vite-plugin';
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ motionCanvas(),
7
+ ],
8
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "useTabs": true,
3
+ "semi": true,
4
+ "singleQuote": true,
5
+ "quoteProps": "as-needed",
6
+ "trailingComma": "all",
7
+ "bracketSpacing": false,
8
+ "printWidth": 100
9
+ }
@@ -0,0 +1,28 @@
1
+ # Revideo Next.js Template
2
+
3
+ This is the [Revideo](https://github.com/redotvideo/revideo) NextJS starter
4
+ project bootstrapped with `npm init @revideo@latest`.
5
+
6
+ ## Getting Started
7
+
8
+ First, install the dependencies both in the next/ and the revideo/ directories:
9
+
10
+ ```bash
11
+ (cd next && npm install) &&
12
+ (cd revideo && npm install)
13
+ ```
14
+
15
+ Then, serve the Revideo project using the CLI:
16
+
17
+ ```bash
18
+ (cd revideo && npx revideo serve)
19
+ ```
20
+
21
+ Now you can start your NextJS app using the following command:
22
+
23
+ ```bash
24
+ (cd next && npm run dev)
25
+ ```
26
+
27
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
28
+ result. Happy developing!
@@ -0,0 +1,113 @@
1
+ 'use server';
2
+
3
+ import pLimit from 'p-limit';
4
+
5
+ const PER_PAGE = 30;
6
+
7
+ interface ReturnType {
8
+ stargazerTimes: number[];
9
+ status: 'success' | 'rate-limit' | 'error';
10
+ }
11
+
12
+ async function getStargazerTimesForPage(
13
+ repo: `${string}/${string}`,
14
+ page: number,
15
+ headers: HeadersInit,
16
+ ): Promise<ReturnType> {
17
+ const response = await fetch(
18
+ `https://api.github.com/repos/${repo}/stargazers?page=${page}&per_page=${PER_PAGE}`,
19
+ {
20
+ headers: {
21
+ Accept: 'application/vnd.github.v3.star+json',
22
+ ...headers,
23
+ },
24
+ },
25
+ );
26
+
27
+ if (response.status === 403) {
28
+ return {stargazerTimes: [], status: 'rate-limit'};
29
+ }
30
+
31
+ if (!response.ok) {
32
+ return {stargazerTimes: [], status: 'error'};
33
+ }
34
+
35
+ const data = await response.json();
36
+ const dates: Date[] = data.map((stargazer: any) => new Date(stargazer.starred_at));
37
+ const msTimes = dates.map((date) => date.getTime());
38
+
39
+ return {
40
+ stargazerTimes: msTimes,
41
+ status: 'success',
42
+ };
43
+ }
44
+
45
+ const limit = pLimit(10);
46
+
47
+ async function getTimes(
48
+ repo: `${string}/${string}`,
49
+ totalPages: number,
50
+ headers: HeadersInit,
51
+ ): Promise<ReturnType> {
52
+ const stargazerPromises: Promise<ReturnType>[] = [];
53
+
54
+ // Fetch all pages in parallel
55
+ for (let page = 1; page <= totalPages; page++) {
56
+ stargazerPromises.push(limit(() => getStargazerTimesForPage(repo, page, headers)));
57
+ }
58
+
59
+ const stargazerTimes = await Promise.all(stargazerPromises);
60
+
61
+ // In case of failure, return the first error
62
+ const objectsThatFailed = stargazerTimes.filter(({status}) => status !== 'success');
63
+ if (stargazerTimes.some(({status}) => status !== 'success')) {
64
+ return {
65
+ stargazerTimes: [],
66
+ status: objectsThatFailed[0].status,
67
+ };
68
+ }
69
+
70
+ const stargazerMs = stargazerTimes.map(({stargazerTimes}) => stargazerTimes).flat();
71
+ const sortedMs = stargazerMs.sort((a, b) => a - b);
72
+
73
+ const firstMs = sortedMs[0];
74
+ const relativeMs = sortedMs.map((ms) => ms - firstMs);
75
+
76
+ return {
77
+ stargazerTimes: relativeMs,
78
+ status: 'success',
79
+ };
80
+ }
81
+
82
+ export async function getGithubRepositoryInfo(
83
+ repoName: `${string}/${string}`,
84
+ key?: string,
85
+ ): Promise<ReturnType & {repoImage: string}> {
86
+ const headers: HeadersInit = {};
87
+
88
+ if (key) {
89
+ headers.Authorization = `token ${key}`;
90
+ }
91
+
92
+ const response = await fetch(`https://api.github.com/repos/${repoName}`, {
93
+ headers,
94
+ });
95
+
96
+ if (response.status === 403) {
97
+ return {stargazerTimes: [], repoImage: '', status: 'rate-limit'};
98
+ }
99
+
100
+ if (!response.ok) {
101
+ return {stargazerTimes: [], repoImage: '', status: 'error'};
102
+ }
103
+
104
+ const responseParsed = await response.json();
105
+ const pages = Math.ceil(responseParsed.stargazers_count / PER_PAGE);
106
+ const info = await getTimes(repoName, pages, headers);
107
+
108
+ return {
109
+ stargazerTimes: info.stargazerTimes,
110
+ repoImage: responseParsed.owner.avatar_url,
111
+ status: info.status,
112
+ };
113
+ }
@@ -0,0 +1,22 @@
1
+ const RENDER_URL = 'http://localhost:4000/render';
2
+
3
+ async function getResponse(body: string) {
4
+ return await fetch(RENDER_URL, {
5
+ method: 'POST',
6
+ headers: {
7
+ 'Content-Type': 'application/json',
8
+ },
9
+ body,
10
+ });
11
+ }
12
+
13
+ export async function POST(request: Request) {
14
+ const body = await request.json();
15
+
16
+ const response = await getResponse(JSON.stringify(body));
17
+ if (!response.ok) {
18
+ return new Response('Failed to render', {status: 500});
19
+ }
20
+
21
+ return new Response(response.body, {status: 200});
22
+ }
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -0,0 +1,25 @@
1
+ import type {Metadata} from 'next';
2
+ import {Inter} from 'next/font/google';
3
+ import './globals.css';
4
+
5
+ const inter = Inter({subsets: ['latin']});
6
+
7
+ export const metadata: Metadata = {
8
+ title: 'Create Next App',
9
+ description: 'Generated by create next app',
10
+ };
11
+
12
+ export default function RootLayout({
13
+ children,
14
+ }: Readonly<{
15
+ children: React.ReactNode;
16
+ }>) {
17
+ return (
18
+ <html lang="en">
19
+ <head>
20
+ <link rel="stylesheet" href="http://localhost:4000/player/project.css" />
21
+ </head>
22
+ <body className={inter.className}>{children}</body>
23
+ </html>
24
+ );
25
+ }