From 5987fdce7dbe1a7f40f107e578b934b57db1a7a6 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Tue, 29 Sep 2026 15:13:03 -0400 Subject: [PATCH] chore(videos): delete Remotion video app and adjust docs description --- AGENTS.md | 4 +- apps/videos/.gitignore | 7 -- apps/videos/.prettierrc | 5 -- apps/videos/README.md | 54 ---------------- apps/videos/eslint.config.mjs | 3 - apps/videos/package.json | 35 ---------- apps/videos/remotion.config.ts | 12 ---- apps/videos/src/HelloWorld.tsx | 74 --------------------- apps/videos/src/HelloWorld/Arc.tsx | 55 ---------------- apps/videos/src/HelloWorld/Atom.tsx | 36 ----------- apps/videos/src/HelloWorld/Logo.tsx | 85 ------------------------- apps/videos/src/HelloWorld/Subtitle.tsx | 26 -------- apps/videos/src/HelloWorld/Title.tsx | 58 ----------------- apps/videos/src/HelloWorld/constants.ts | 5 -- apps/videos/src/Root.tsx | 45 ------------- apps/videos/src/index.css | 1 - apps/videos/src/index.ts | 7 -- apps/videos/tsconfig.json | 16 ----- 18 files changed, 2 insertions(+), 526 deletions(-) delete mode 100644 apps/videos/.gitignore delete mode 100644 apps/videos/.prettierrc delete mode 100644 apps/videos/README.md delete mode 100644 apps/videos/eslint.config.mjs delete mode 100644 apps/videos/package.json delete mode 100644 apps/videos/remotion.config.ts delete mode 100644 apps/videos/src/HelloWorld.tsx delete mode 100644 apps/videos/src/HelloWorld/Arc.tsx delete mode 100644 apps/videos/src/HelloWorld/Atom.tsx delete mode 100644 apps/videos/src/HelloWorld/Logo.tsx delete mode 100644 apps/videos/src/HelloWorld/Subtitle.tsx delete mode 100644 apps/videos/src/HelloWorld/Title.tsx delete mode 100644 apps/videos/src/HelloWorld/constants.ts delete mode 100644 apps/videos/src/Root.tsx delete mode 100644 apps/videos/src/index.css delete mode 100644 apps/videos/src/index.ts delete mode 100644 apps/videos/tsconfig.json diff --git a/AGENTS.md b/AGENTS.md index e04d574..ecd1958 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -46,7 +46,7 @@ flowchart LR |---|---| | `work/<1\|3\|7>///..{js,py}` | Solutions, e.g. `work/1/Easy/Array/1.two-sum.py`. The top directory is the spaced-repetition bucket: `1` = first solve, `3`/`7` = the blind re-solves of that problem 3 and 7 days later. Machine-parsed header comment (title / `Difficulty:` / URL / `─` rule / statement) — preserve its exact shape | | `apps/cli/` | Flat Bun TS workspace: automation entries (shebang + top-level await) and libraries (no shebang, side-effect-free on import). Root `bun run` scripts delegate here | -| `apps/docs/` | Blume site (`blume.config.ts`, `content/`, `components/` + `components.ts`, `islands/`, `public/`). `content/(0N-)//-.mdx` plus one `meta.ts` per phase and per topic folder, all generated by sync: the phase folder is a `(group)` (sidebar section, no route segment), the topic folder is the README campaign topic slug (`tree-dfs/`, `heap-priority-queue/`) and a real route segment (`/tree-dfs/invert-binary-tree`), the `meta.ts` files carry the exact labels, phase/topic numbers and icons so the sidebar reads in curriculum order with each topic a collapsible group. A problem page's badge row (above the title) is rendered, not written: the `PageHeader` slot (`components/ProblemBadges.astro`, wired in `components.ts`) reads the page's `topics:` (LeetCode's topic tags, from sync) and `video:` (NeetCode YouTube id, from `bun run videos`) frontmatter — both declared via `frontmatter.extend` in `blume.config.ts`, hand-rolled Standard Schemas, no zod — and links a tag the campaign teaches to its topic landing page (accent), any other tag to its guide page `/guides/` (neutral; LeetCode's problem list if the guide is gone), and the video as a red `Explanation` badge. Which tags the campaign teaches is ONE map, `apps/docs/topic-landings.ts` (tag slug → landing routes), read by both that component and sync. `content/guides/.mdx` (the `Guides` header tab) is one page per tag outside that map: sync creates a placeholder when the file is missing or empty and never touches it again (hand-owned; a guide whose tag no page carries any more is left alone), with frontmatter `list:` — the tag's LeetCode problem list, rendered by the same slot as an orange `LeetCode list` badge; sync also writes `guides/meta.ts`. A hand-written `(0N-)//index.mdx` (`hidden: true`) is that topic's landing page: Blume ≥ 1.7.3 links the sidebar group row to it (`sliding-window/index.mdx` → `/sliding-window`) and the hidden flag drops the duplicate row. Two kinds of custom MDX component, both import-free on every page: `islands/.tsx` is hydrated React (auto-discovered; `ProgressDashboard`, `DependencySpine` — the README topic map as data, zoom/pan, nodes link to whatever route Blume's `/api/docs/navigation.json` reports for the topic folder, inert until a topic has pages), `components/.astro` registered in `components.ts` is static markup plus a custom element for behaviour, the way Blume's own `Frame` is built (`Carousel`/`CarouselImage`: `src` takes a URL, `/file.png`, or the page-relative `../../public/file.png`) | +| `apps/docs/` | Blume site (`blume.config.ts`, `content/`, `components/` + `components.ts`, `islands/`, `public/`). `content/(0N-)//-.mdx` plus one `meta.ts` per phase and per topic folder, all generated by sync (a phase's once, then hand-owned): the phase folder is a `(group)` (sidebar section, no route segment), the topic folder is the README campaign topic slug (`tree-dfs/`, `heap-priority-queue/`) and a real route segment (`/tree-dfs/invert-binary-tree`), the `meta.ts` files carry the exact labels, phase/topic numbers and icons so the sidebar reads in curriculum order with each topic a collapsible group. A problem page's badge row (above the title) is rendered, not written: the `PageHeader` slot (`components/ProblemBadges.astro`, wired in `components.ts`) reads the page's `topics:` (LeetCode's topic tags, from sync) and `video:` (NeetCode YouTube id, from `bun run videos`) frontmatter — both declared via `frontmatter.extend` in `blume.config.ts`, hand-rolled Standard Schemas, no zod — and links a tag the campaign teaches to its topic landing page (accent), any other tag to its guide page `/guides/` (neutral; LeetCode's problem list if the guide is gone), and the video as a red `Explanation` badge. The reverse direction is the `PageFooter` slot (`components/BacklinksList.astro`): an Obsidian-style ` ` list under every topic landing and guide page of the problems whose badges link there, plus a topic's own folder members (so a topic no tag names, `hybrid-structures`, still lists its problems); problem pages are recognised by their `. ` title and render no list. Which tags the campaign teaches is ONE map, `apps/docs/topic-landings.ts` (tag slug → landing routes), and where a badge points is ONE function beside it, `tagTarget()` — read by both components (so badges and backlinks cannot disagree) and the map by sync. `content/guides/.mdx` (the `Guides` header tab) is one page per tag outside that map: sync creates a placeholder when the file is missing or empty and never touches it again (hand-owned; a guide whose tag no page carries any more is left alone), with frontmatter `list:` — the tag's LeetCode problem list, rendered by the same slot as an orange `LeetCode list` badge; sync also writes `guides/meta.ts`. A hand-written `(0N-)//index.mdx` (`hidden: true`) is that topic's landing page: Blume ≥ 1.7.3 links the sidebar group row to it (`sliding-window/index.mdx` → `/sliding-window`) and the hidden flag drops the duplicate row. Two kinds of custom MDX component, both import-free on every page: `islands/.tsx` is hydrated React (auto-discovered; `ProgressDashboard`, `DependencySpine` — the README topic map as data, zoom/pan, nodes link to whatever route Blume's `/api/docs/navigation.json` reports for the topic folder, inert until a topic has pages), `components/.astro` registered in `components.ts` is static markup plus a custom element for behaviour, the way Blume's own `Frame` is built (`Carousel`/`CarouselImage`: `src` takes a URL, `/file.png`, or the page-relative `../../public/file.png`) | | `apps/api/` | Cloudflare Worker workspace: `src/` modules, `data/schedule.json` (the plan: `date → { topics | problems | gate | sweep }`, human-edited, bundled at deploy), `migrations/` (append-only; `0002` is the +3/+7 ladder rebuild) | | `.github/workflows/` | deploy (docs → Pages with `GITHUB_TOKEN` for the releases-backed changelog, Worker → Cloudflare, on every main push), close-solved (issues + `/admin/solved` + Project `Set`/`Difficulty`, needs `SRS_ADMIN_KEY` and `PROJECT_PAT`; then the `release` job: timever tag + release per finished topic, `contents: write`), close-topics, sync-d1 (issue edits → `/admin/reconcile`), spaced-repetition (daily 06:00 ET cron → today's review issue; `GITHUB_TOKEN` only, no secrets) | | `.githooks/` | Tracked git hooks; `bun install` points `core.hooksPath` here (root `prepare` script, no husky). `pre-commit` runs `bun run sync` and stages only what sync changed (pages, `apps/docs/redirects.ts`), so a solution, its page and its `/` short link land in one commit; it refuses to run while `work/1` has anything unstaged (sync reads the tree, so the page would not match the commit), and leaves pre-existing dirt under `apps/docs/content` (in-progress `## Approach` prose) unstaged. `git commit --no-verify` for a deliberate partial commit | @@ -110,7 +110,7 @@ curl -X POST -H "Authorization: Bearer $LINK_KEY" \ - `apps/api/src/index.ts` — router + cron dispatch; `apps/api/wrangler.jsonc` — bindings (`DB`, `EMAIL`), crons, vars; secrets `GH_PAT`/`WEBHOOK_SECRET`/`LINK_KEY` via `wrangler secret put`. - `apps/api/src/digest.ts` / `apps/api/src/email.tsx` — the daily digest, split data/presentation. `digest.ts` reads D1 into a `DigestData`; `email.tsx` owns every colour and every sentence, and renders both the HTML and (via its own `plainDigest`, not React Email's `plainText` mode, which flattens the tables) the text alternative. The retrieval rules hold by construction: `DigestRow` has no title and no issue field, so a review or drill line *cannot* leak the topic or a solution link. Subject is `(Day N/56) LeetCode Daily Digest`. - `apps/api/src/png.ts` — hand-rolled PNG encoder (RGB8, one IDAT, zlib via `CompressionStream("deflate")`, CRC32, 5×7 bitmap font). It exists because every major email client refuses remote SVG, so `/chart/heatmap.png` rasters the heatmap for the digest while `/chart/heatmap.svg` keeps serving the README byte-for-byte. Both come from one `heatmapCells()` so the two pictures cannot drift. -- `apps/cli/sync.ts` — work→docs contract: on existing pages only the frontmatter `icon:` and the `## Solution` section are regenerated, and `topics:` (LeetCode's `topicTags` as `{ name, slug }`, fetched by GraphQL) is filled once — on create, or on any run that finds it missing — never refreshed (delete the key to refetch; offline, the page is written without it and the next sync retries). `## Solution` is the latter bounded by `solutionEnd()` at the next unfenced top-level heading; human prose before it and any sections after it are never touched. Never hand-write solution pages or edit inside `## Solution`. Two classifications, two homes: the sidebar group is the README topic (`readmeTopics()`, first listing wins for a problem under two topics; a warm-up outside the plan groups under its category at `order: 0`, ahead of topic 1) and the `work/1///` category, which only places an unplanned problem — the page's topic badges are LeetCode's tags, not either classification. Topics nest under their README phase (`## Phase N — Name` headings, shortened via `PHASE_ALIASES`): `content/(0N-)//`, both `meta.ts` script-owned and rewritten every run (phase: `Phase N: Name`, `order: N`; topic: label, curriculum order, `TOPIC_ICONS` icon, `display: "group"`). The phase folder is a Blume `(group)` — no route segment, so `/tree-dfs` is unchanged and a landing page there is one level deep, never at `/` — and the topic folder is the real segment; never put a topic `index.mdx` directly inside a `(group)`. A page is `rename`d when its topic or phase changes; a folder every page has left is deleted (climbing into an emptied phase folder) unless it still holds a hand-written `index.mdx` (sync never writes, moves, or deletes one — so page-relative asset paths in a moved landing page are yours to fix). Slugs come from `slugify()`, which glues a leading number to the next token (`1d-dynamic-programming`) because Blume strips `-` prefixes from routes. The hand-owned parts have their own owners: `## Approach` (a Mermaid flowchart tracing the page's code, placed *before* `## Solution` so a re-sync keeps it) is written per the `problem-approach` skill (`/problem-approach` fills every page missing one); the frontmatter `video:` (the NeetCode walkthrough, rendered as the red `Explanation` badge) is added by `bun run videos --write` (`apps/cli/videos.ts`). +- `apps/cli/sync.ts` — work→docs contract: on existing pages only the frontmatter `icon:` and the `## Solution` section are regenerated, and `topics:` (LeetCode's `topicTags` as `{ name, slug }`, fetched by GraphQL) is filled once — on create, or on any run that finds it missing — never refreshed (delete the key to refetch; offline, the page is written without it and the next sync retries). `## Solution` is the latter bounded by `solutionEnd()` at the next unfenced top-level heading; human prose before it and any sections after it are never touched. Never hand-write solution pages or edit inside `## Solution`. Two classifications, two homes: the sidebar group is the README topic (`readmeTopics()`, first listing wins for a problem under two topics; a warm-up outside the plan groups under its category at `order: 0`, ahead of topic 1) and the `work/1///` category, which only places an unplanned problem — the page's topic badges are LeetCode's tags, not either classification. Topics nest under their README phase (`## Phase N — Name` headings, shortened via `PHASE_ALIASES`): `content/(0N-)//`. The topic `meta.ts` is script-owned and rewritten every run (label, curriculum order, `TOPIC_ICONS` icon, `display: "group"`); the phase `meta.ts` is written once when missing (`Phase N: Name`, `order: N`) and hand-owned after — rename its title freely. Never rewriting it loses nothing: its order and name are also the folder name, so a README change to either lands in a new folder with a fresh meta. The phase folder is a Blume `(group)` — no route segment, so `/tree-dfs` is unchanged and a landing page there is one level deep, never at `/` — and the topic folder is the real segment; never put a topic `index.mdx` directly inside a `(group)`. A page is `rename`d when its topic or phase changes; a folder every page has left is deleted (climbing into an emptied phase folder) unless it still holds a hand-written `index.mdx` (sync never writes, moves, or deletes one — so page-relative asset paths in a moved landing page are yours to fix). Slugs come from `slugify()`, which glues a leading number to the next token (`1d-dynamic-programming`) because Blume strips `-` prefixes from routes. The hand-owned parts have their own owners: `## Approach` (a Mermaid flowchart tracing the page's code, placed *before* `## Solution` so a re-sync keeps it) is written per the `problem-approach` skill (`/problem-approach` fills every page missing one); the frontmatter `video:` (the NeetCode walkthrough, rendered as the red `Explanation` badge) is added by `bun run videos --write` (`apps/cli/videos.ts`). - `apps/cli/work.ts` — the `work/` layout: bucket paths, `isSolution()`/`solvedInBucket()` (the stub test, shared with `close-solved.ts`), `firstSolved()` (one `git log`, ET dates, keyed by LC number so past layout moves don't matter), and `reviewQueues()` (what each window still owes). Everything that needs to know where a solution file lives, or when it was solved, goes through here. - `apps/api/src/stats.ts` / `apps/cli/stats.ts` / `apps/cli/tui.ts` / `apps/cli/api.ts` — the read side. `buildStats()` is the ONE aggregation: phases, ladder, difficulty, per-topic temperature, gates, the 14-day due queue, and `heat` (every campaign day, zeros and future days included — the docs page windows the tail off it rather than asking a second question). Two readers consume it, the docs island and `bun run stats`, so its shape is both their contract: change all three together. `tui.ts` is hand-rolled ANSI (bars, sparklines, heat cells, alternate screen) on charts.ts's palette, and every chart differs by GLYPH as well as by colour so a piped or `NO_COLOR` dashboard still reads. The TUI recomputes nothing: the only local fact it shows is the `work/` solution count, which is inventory, not schedule. - `README.md` live charts are Worker endpoints (`/chart/*.svg`, `/badge/gate.svg`, 5-min Camo cache); the docs `/progress` page fetches `/api/stats` client-side (`apps/docs/islands/ProgressDashboard.tsx`). diff --git a/apps/videos/.gitignore b/apps/videos/.gitignore deleted file mode 100644 index b62197b..0000000 --- a/apps/videos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules -dist -.DS_Store -.env - -# Ignore the output video from Git but not videos you import into src/. -out diff --git a/apps/videos/.prettierrc b/apps/videos/.prettierrc deleted file mode 100644 index 37d5071..0000000 --- a/apps/videos/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "useTabs": false, - "bracketSpacing": true, - "tabWidth": 2 -} diff --git a/apps/videos/README.md b/apps/videos/README.md deleted file mode 100644 index 3132845..0000000 --- a/apps/videos/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# Remotion video - -

- - - - Animated Remotion Logo - - -

- -Welcome to your Remotion project! - -## Commands - -**Install Dependencies** - -```console -npm i -``` - -**Start Preview** - -```console -npm run dev -``` - -**Render video** - -```console -npx remotion render -``` - -**Upgrade Remotion** - -```console -npx remotion upgrade -``` - -## Docs - -Get started with Remotion by reading the [fundamentals page](https://www.remotion.dev/docs/the-fundamentals). - -## Help - -We provide help on our [Discord server](https://discord.gg/6VzzNDwUwV). - -## Issues - -Found an issue with Remotion? [File an issue here](https://github.com/remotion-dev/remotion/issues/new). - -## License - -Note that for some entities a company license is needed. [Read the terms here](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md). diff --git a/apps/videos/eslint.config.mjs b/apps/videos/eslint.config.mjs deleted file mode 100644 index 13b44a0..0000000 --- a/apps/videos/eslint.config.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import { config } from "@remotion/eslint-config-flat"; - -export default config; diff --git a/apps/videos/package.json b/apps/videos/package.json deleted file mode 100644 index 05f7d48..0000000 --- a/apps/videos/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "videos", - "version": "1.0.0", - "description": "My Remotion video", - "repository": {}, - "license": "UNLICENSED", - "private": true, - "dependencies": { - "@remotion/cli": "4.0.528", - "@remotion/zod-types": "4.0.528", - "react": "19.2.3", - "react-dom": "19.2.3", - "remotion": "4.0.528", - "zod": "4.5.4", - "@remotion/tailwind-v4": "4.0.528", - "tailwindcss": "4.0.0" - }, - "devDependencies": { - "@remotion/eslint-config-flat": "4.0.528", - "@types/react": "19.2.7", - "@types/web": "0.0.166", - "eslint": "9.19.0", - "prettier": "3.8.1", - "typescript": "5.9.3" - }, - "scripts": { - "dev": "remotion studio", - "build": "remotion bundle", - "upgrade": "remotion upgrade", - "lint": "eslint src && tsc" - }, - "sideEffects": [ - "*.css" - ] -} \ No newline at end of file diff --git a/apps/videos/remotion.config.ts b/apps/videos/remotion.config.ts deleted file mode 100644 index c1c8afe..0000000 --- a/apps/videos/remotion.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -// See all configuration options: https://remotion.dev/docs/config -// Each option also is available as a CLI flag: https://remotion.dev/docs/cli - -// Note: When using the Node.JS APIs, the config file doesn't apply. Instead, pass options directly to the APIs - -import { Config } from "@remotion/cli/config"; -import { enableTailwind } from '@remotion/tailwind-v4'; - -Config.setRspack(true); -Config.setVideoImageFormat("jpeg"); -Config.setOverwriteOutput(true); -Config.overrideBundlerConfig(enableTailwind); diff --git a/apps/videos/src/HelloWorld.tsx b/apps/videos/src/HelloWorld.tsx deleted file mode 100644 index 803c33b..0000000 --- a/apps/videos/src/HelloWorld.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { - AbsoluteFill, - interpolate, - Sequence, - spring, - useCurrentFrame, - useVideoConfig, -} from "remotion"; -import { Logo } from "./HelloWorld/Logo"; -import { Subtitle } from "./HelloWorld/Subtitle"; -import { Title } from "./HelloWorld/Title"; - -export type HelloWorldProps = { - readonly titleText: string; - readonly titleColor: string; - readonly logoColor1: string; - readonly logoColor2: string; -}; - -export const HelloWorld: React.FC = ({ - titleText: propOne, - titleColor: propTwo, - logoColor1, - logoColor2, -}) => { - const frame = useCurrentFrame(); - const { durationInFrames, fps } = useVideoConfig(); - - // Animate from 0 to 1 after 25 frames - const logoTranslationProgress = spring({ - frame: frame - 25, - fps, - config: { - damping: 100, - }, - }); - - // Move the logo up by 150 pixels once the transition starts - const logoTranslation = interpolate( - logoTranslationProgress, - [0, 1], - [0, -150], - ); - - // Fade out the animation at the end - const opacity = interpolate( - frame, - [durationInFrames - 25, durationInFrames - 15], - [1, 0], - { - extrapolateLeft: "clamp", - extrapolateRight: "clamp", - }, - ); - - // A is just a absolutely positioned
! - return ( - - - - - - {/* Sequences can shift the time for its children! */} - - - </Sequence> - {/* The subtitle will only enter on the 75th frame. */} - <Sequence from={75}> - <Subtitle /> - </Sequence> - </AbsoluteFill> - </AbsoluteFill> - ); -}; diff --git a/apps/videos/src/HelloWorld/Arc.tsx b/apps/videos/src/HelloWorld/Arc.tsx deleted file mode 100644 index e580b47..0000000 --- a/apps/videos/src/HelloWorld/Arc.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useState } from "react"; -import { random, useVideoConfig } from "remotion"; - -const getCircumferenceOfArc = (rx: number, ry: number) => { - return Math.PI * 2 * Math.sqrt((rx * rx + ry * ry) / 2); -}; - -const rx = 135; -const ry = 300; -const cx = 960; -const cy = 540; -const arcLength = getCircumferenceOfArc(rx, ry); -const strokeWidth = 30; - -export const Arc: React.FC<{ - progress: number; - rotation: number; - rotateProgress: number; - color1: string; - color2: string; -}> = ({ progress, rotation, rotateProgress, color1, color2 }) => { - const { width, height } = useVideoConfig(); - - // Each svg Id must be unique to not conflict with each other - const [gradientId] = useState(() => String(random(null))); - - return ( - <svg - viewBox={`0 0 ${width} ${height}`} - style={{ - position: "absolute", - transform: `rotate(${rotation * rotateProgress}deg)`, - }} - > - <defs> - <linearGradient id={gradientId} x1="0%" y1="0%" x2="0%" y2="100%"> - <stop offset="0%" stopColor={color1} /> - <stop offset="100%" stopColor={color2} /> - </linearGradient> - </defs> - <ellipse - cx={cx} - cy={cy} - rx={rx} - ry={ry} - fill="none" - stroke={`url(#${gradientId})`} - strokeDasharray={arcLength} - strokeDashoffset={arcLength - arcLength * progress} - strokeLinecap="round" - strokeWidth={strokeWidth} - /> - </svg> - ); -}; diff --git a/apps/videos/src/HelloWorld/Atom.tsx b/apps/videos/src/HelloWorld/Atom.tsx deleted file mode 100644 index 5fdb507..0000000 --- a/apps/videos/src/HelloWorld/Atom.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { useState } from "react"; -import { random, useVideoConfig } from "remotion"; - -export const Atom: React.FC<{ - scale: number; - color1: string; - color2: string; -}> = ({ scale, color1, color2 }) => { - const config = useVideoConfig(); - - // Each SVG ID must be unique to not conflict with each other - const [gradientId] = useState(() => String(random(null))); - - return ( - <svg - viewBox={`0 0 ${config.width} ${config.height}`} - style={{ - position: "absolute", - transform: `scale(${scale})`, - }} - > - <defs> - <linearGradient id={gradientId} x1="0%" y1="0%" x2="100%" y2="0%"> - <stop offset="0%" stopColor={color1} /> - <stop offset="100%" stopColor={color2} /> - </linearGradient> - </defs> - <circle - r={70} - cx={config.width / 2} - cy={config.height / 2} - fill={`url(#${gradientId})`} - /> - </svg> - ); -}; diff --git a/apps/videos/src/HelloWorld/Logo.tsx b/apps/videos/src/HelloWorld/Logo.tsx deleted file mode 100644 index 4afabf2..0000000 --- a/apps/videos/src/HelloWorld/Logo.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { - AbsoluteFill, - interpolate, - spring, - useCurrentFrame, - useVideoConfig, -} from "remotion"; -import { Arc } from "./Arc"; -import { Atom } from "./Atom"; - -export type LogoProps = { - readonly logoColor1: string; - readonly logoColor2: string; -}; - -export const Logo: React.FC<LogoProps> = ({ - logoColor1: color1, - logoColor2: color2, -}) => { - const videoConfig = useVideoConfig(); - const frame = useCurrentFrame(); - - const development = spring({ - config: { - damping: 100, - mass: 0.5, - }, - fps: videoConfig.fps, - frame, - }); - - const rotationDevelopment = spring({ - config: { - damping: 100, - mass: 0.5, - }, - fps: videoConfig.fps, - frame, - }); - - const scale = spring({ - frame, - config: { - mass: 0.5, - }, - fps: videoConfig.fps, - }); - - const logoRotation = interpolate( - frame, - [0, videoConfig.durationInFrames], - [0, 360], - ); - - return ( - <AbsoluteFill - style={{ - transform: `scale(${scale}) rotate(${logoRotation}deg)`, - }} - > - <Arc - rotateProgress={rotationDevelopment} - progress={development} - rotation={30} - color1={color1} - color2={color2} - /> - <Arc - rotateProgress={rotationDevelopment} - rotation={90} - progress={development} - color1={color1} - color2={color2} - /> - <Arc - rotateProgress={rotationDevelopment} - rotation={-30} - progress={development} - color1={color1} - color2={color2} - /> - <Atom scale={rotationDevelopment} color1={color1} color2={color2} /> - </AbsoluteFill> - ); -}; diff --git a/apps/videos/src/HelloWorld/Subtitle.tsx b/apps/videos/src/HelloWorld/Subtitle.tsx deleted file mode 100644 index 9ccbe5d..0000000 --- a/apps/videos/src/HelloWorld/Subtitle.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from "react"; -import { interpolate, useCurrentFrame } from "remotion"; -import { COLOR_1, FONT_FAMILY } from "./constants"; - -const subtitle: React.CSSProperties = { - fontFamily: FONT_FAMILY, - fontSize: 40, - textAlign: "center", - position: "absolute", - bottom: 140, - width: "100%", -}; - -const codeStyle: React.CSSProperties = { - color: COLOR_1, -}; - -export const Subtitle: React.FC = () => { - const frame = useCurrentFrame(); - const opacity = interpolate(frame, [0, 30], [0, 1]); - return ( - <div style={{ ...subtitle, opacity }}> - Edit <code style={codeStyle}>src/Root.tsx</code> and save to reload. - </div> - ); -}; diff --git a/apps/videos/src/HelloWorld/Title.tsx b/apps/videos/src/HelloWorld/Title.tsx deleted file mode 100644 index d691214..0000000 --- a/apps/videos/src/HelloWorld/Title.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from "react"; -import { spring, useCurrentFrame, useVideoConfig } from "remotion"; -import { FONT_FAMILY } from "./constants"; - -const title: React.CSSProperties = { - fontFamily: FONT_FAMILY, - fontWeight: "bold", - fontSize: 100, - textAlign: "center", - position: "absolute", - bottom: 160, - width: "100%", -}; - -const word: React.CSSProperties = { - marginLeft: 10, - marginRight: 10, - display: "inline-block", -}; - -export const Title: React.FC<{ - readonly titleText: string; - readonly titleColor: string; -}> = ({ titleText, titleColor }) => { - const videoConfig = useVideoConfig(); - const frame = useCurrentFrame(); - - const words = titleText.split(" "); - - return ( - <h1 style={title}> - {words.map((t, i) => { - const delay = i * 5; - - const scale = spring({ - fps: videoConfig.fps, - frame: frame - delay, - config: { - damping: 200, - }, - }); - - return ( - <span - key={t} - style={{ - ...word, - color: titleColor, - transform: `scale(${scale})`, - }} - > - {t} - </span> - ); - })} - </h1> - ); -}; diff --git a/apps/videos/src/HelloWorld/constants.ts b/apps/videos/src/HelloWorld/constants.ts deleted file mode 100644 index e20c050..0000000 --- a/apps/videos/src/HelloWorld/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Change any of these to update your video live. - -export const COLOR_1 = "#86A8E7"; - -export const FONT_FAMILY = "SF Pro Text, Helvetica, Arial, sans-serif"; diff --git a/apps/videos/src/Root.tsx b/apps/videos/src/Root.tsx deleted file mode 100644 index 5b12652..0000000 --- a/apps/videos/src/Root.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import "./index.css"; -import { Composition } from "remotion"; -import { HelloWorld } from "./HelloWorld"; -import { Logo } from "./HelloWorld/Logo"; - -// Each <Composition> is an entry in the sidebar! - -export const RemotionRoot: React.FC = () => { - return ( - <> - <Composition - // You can take the "id" to render a video: - // npx remotion render HelloWorld - id="HelloWorld" - component={HelloWorld} - durationInFrames={150} - fps={30} - width={1920} - height={1080} - // You can override these props for each render: - // https://www.remotion.dev/docs/parametrized-rendering - defaultProps={{ - titleText: "Welcome to Remotion", - titleColor: "#000000", - logoColor1: "#91EAE4", - logoColor2: "#86A8E7", - }} - /> - - {/* Mount any React component to make it show up in the sidebar and work on it individually! */} - <Composition - id="OnlyLogo" - component={Logo} - durationInFrames={150} - fps={30} - width={1920} - height={1080} - defaultProps={{ - logoColor1: "#91dAE2", - logoColor2: "#86A8E7", - }} - /> - </> - ); -}; diff --git a/apps/videos/src/index.css b/apps/videos/src/index.css deleted file mode 100644 index f1d8c73..0000000 --- a/apps/videos/src/index.css +++ /dev/null @@ -1 +0,0 @@ -@import "tailwindcss"; diff --git a/apps/videos/src/index.ts b/apps/videos/src/index.ts deleted file mode 100644 index 14dff4c..0000000 --- a/apps/videos/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// This is your entry file! Refer to it when you render: -// npx remotion render <entry-file> HelloWorld out/video.mp4 - -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; - -registerRoot(RemotionRoot); diff --git a/apps/videos/tsconfig.json b/apps/videos/tsconfig.json deleted file mode 100644 index 7bfaf1a..0000000 --- a/apps/videos/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2018", - "module": "Preserve", - "moduleResolution": "Bundler", - "jsx": "react-jsx", - "strict": true, - "noEmit": true, - "lib": ["es2015"], - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "noUnusedLocals": true - }, - "exclude": ["remotion.config.ts"] -}