-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Upgrade Next.js + enable Turbo #1033
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Note Reviews pausedUse the following commands to manage reviews:
WalkthroughThe PR upgrades dependencies (Next/React/Effect), enables TypeScript strictNullChecks, converts many page/route props to Promise-wrapped params/searchParams and awaits cookies()/headers(), widens several RefObject types to allow null, and applies small API route export/type adjustments. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant NextApp as Next App Router
participant Page as Page/Route Module
participant Svc as Data/Service
User->>NextApp: HTTP Request
NextApp->>Page: Invoke handler/component with props (params/searchParams as Promise)
Note right of Page: Await props.params / props.searchParams
Page->>Svc: Fetch data using resolved params
Svc-->>Page: Data/Result
Page-->>NextApp: Response/JSX/Redirect
NextApp-->>User: HTML/JSON
sequenceDiagram
autonumber
participant RC as Server Component/Action
participant NH as next/headers
RC->>NH: cookies()
NH-->>RC: Promise<CookieStore>
RC->>RC: await cookies() → cookieStore
RC->>RC: cookieStore.get/set/delete(...)
RC->>NH: headers()
NH-->>RC: Promise<Headers>
RC->>RC: await headers() → read header values
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
apps/web/app/api/utils.ts (1)
11-14: Remove sensitive logs (Authorization header and full user object).Logging bearer tokens and user objects is a security/compliance risk.
Apply:
- console.log("auth header: ", c.req.header("authorization")); + // removed @@ - console.log("User: ", user); + // removedAlso applies to: 39-41
packages/database/auth/auth-options.ts (1)
98-103: Do not log verification codes or email contentsLogging identifier/token (and rendered email) is a secrets/PII leak risk in production.
- console.log({ identifier, token }); const { OTPEmail } = await import("../emails/otp-email"); const email = OTPEmail({ code: token, email: identifier }); - console.log({ email }); await sendEmail({ email: identifier, subject: `Your Cap Verification Code`, react: email, });apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx (1)
310-315: Duplicate event listener registration causes double-calls and leaksloadedmetadata is added twice; only one remove occurs in cleanup. Remove the duplicate add.
video.addEventListener("loadeddata", handleLoadedData); video.addEventListener("canplay", handleCanPlay); video.addEventListener("loadedmetadata", handleLoadedMetadataWithTracks); video.addEventListener("load", handleLoad); video.addEventListener("play", handlePlay); video.addEventListener("error", handleError as EventListener); - video.addEventListener("loadedmetadata", handleLoadedMetadataWithTracks);apps/web/app/api/playlist/route.ts (2)
245-247: Remove any-casts on route handlers; type to Request -> Promise.Avoid any per project guidelines.
-export const GET = handler as any; -export const HEAD = handler as any; +export const GET: (req: Request) => Promise<Response> = handler; +export const HEAD: (req: Request) => Promise<Response> = handler;
169-180: Guard mp4 requests when source isn’t desktopMP4.When videoType === "mp4" but the source isn’t desktopMP4, prefix remains undefined and listObjects may run on an unintended path.
Add an early guard:
} else if (video.source.type === "desktopMP4") { yield* Effect.log( `Returning path ${`${video.ownerId}/${video.id}/result.mp4`}`, ); return yield* s3 .getSignedObjectUrl(`${video.ownerId}/${video.id}/result.mp4`) .pipe(Effect.map(HttpServerResponse.redirect)); } + if (urlParams.videoType === "mp4") { + return yield* Effect.fail(new HttpApiError.NotFound()); + }apps/web/app/api/releases/macos/route.ts (1)
5-7: Align with API route guidelines (HttpApi + handler export).Per repo guidelines, implement routes with @effect/platform HttpApi/HttpApiBuilder, translate errors with HttpApiError.*, and export only the handler from apiToHandler(ApiLive). This route is hand-rolled and bypasses middleware/dependency provisioning.
I can sketch an HttpApi route that wraps the Octokit call and maps failures to transport errors if you want to migrate this endpoint now.
Also applies to: 9-12
apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
72-73: Type error: removetypeofon a type-only import.
userSelectPropsis imported as a type;typeof userSelectPropsis invalid. Cast to the type directly.- user={user as typeof userSelectProps | null} + user={user as userSelectProps | null}
🧹 Nitpick comments (34)
apps/web/app/s/[videoId]/page.tsx (4)
98-101: Narrow Props types for better safety (encode videoId, use Record for searchParams).Avoid broad index signatures and the downstream cast. This tightens types where they’re consumed.
type Props = { - params: Promise<{ [key: string]: string | string[] | undefined }>; - searchParams: Promise<{ [key: string]: string | string[] | undefined }>; + params: Promise<{ videoId: string }>; + searchParams: Promise<Record<string, string | string[] | undefined>>; };
129-133: Prefer a single headers() call and fall back to the standard Referer header.Reduces duplicate awaits and improves robustness when x-referrer isn’t present.
- const referrer = (await headers()).get("x-referrer") || ""; + const h = await headers(); + const referrer = h.get("x-referrer") ?? h.get("referer") ?? "";
313-319: Confirm Effect.flatten semantics (Option → NoSuchElementException).This relies on flatten converting None to a NoSuchElementException (caught below). If flatten doesn’t do this in your Effect version, this could pass an undefined video through and crash later.
If needed, replace with an explicit Option → Effect conversion for clarity and type safety (example approach):
- Convert Option to Effect explicitly (e.g., Effect.fromOption / someOrFail)
- Then map to the { needsPassword: false, video } shape
Would you like me to propose an exact patch tailored to your Effect version?
345-347: Don’t rethrow notFound(); return an Effect instead.Throwing is redundant since notFound() already throws. Returning an Effect keeps the pipeline consistent.
- NoSuchElementException: () => { - throw notFound(); - }, + NoSuchElementException: () => Effect.sync(notFound),apps/web/components/pages/HomePage/Features.tsx (3)
105-116: Avoid shadowing component name with local aliasThe inner destructuring aliases RiveComponent to CapAIArt, shadowing the component’s own identifier and inviting mistakes. Rename the alias.
-const CapAIArt = memo(() => { - const { RiveComponent: CapAIArt } = useRive({ +const CapAIArt = memo(() => { + const { RiveComponent: CapAIRive } = useRive({ src: "/rive/bento.riv", artboard: "capai", animations: ["in"], autoplay: true, layout: new Layout({ fit: Fit.Contain, }), }); - return <CapAIArt className="w-full max-w-[550px] mx-auto h-[300px]" />; + return <CapAIRive className="w-full max-w-[550px] mx-auto h-[300px]" />; });
157-158: Remove inline JSX comments per repo guidelinesInline JSX comments violate the no-comments guideline for TS/JS files. Please remove them.
Also applies to: 172-173, 186-187, 201-203
1-1: Optional: Rename file to kebab-caseFile path uses PascalCase segments. The repo guideline prefers kebab-case filenames for TS/JS modules (components stay PascalCase in code). Consider features.tsx (and directory names likewise) for consistency.
apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx (1)
105-106: Ref type should not include null in the generic parameterWith strictNullChecks, React.RefObject already exposes current: T | null. Using RefObject<FolderHandle | null> makes current’s type (FolderHandle | null) | null and can break compatibility with React.Ref parameters.
- {} as Record< - (typeof FolderOptions)[number]["value"], - React.RefObject<FolderHandle | null> - >, + {} as Record< + (typeof FolderOptions)[number]["value"], + React.RefObject<FolderHandle> + >,Confirm NormalFolder/BlueFolder/RedFolder/YellowFolder forwardRef typings accept React.Ref. If any were changed to Ref<FolderHandle | null>, align them back to Ref.
apps/web/tsconfig.json (1)
17-17: strictNullChecks is redundant when strict is trueTypeScript enables strictNullChecks under "strict": true. Keeping both can be confusing.
- "strictNullChecks": true,packages/ui/package.json (1)
18-26: Treat React as a peerDependency in UI libraryFor @cap/ui, depend on the app’s React to avoid duplicate bundles and mismatched hooks. Move react and react-dom to peerDependencies (keep them in devDependencies for local builds).
Run the same workspace version audit script shared earlier to confirm single React/React‑DOM versions across the repo after this change.
packages/database/package.json (1)
29-47: Unify React/Next versions and use peerDependencies in libraries
- Ensure React, React-DOM and Next are declared with the exact same version across all package.json (apps/web pins “19.1.1” vs “^19.1.1” elsewhere).
- In library packages (e.g. @cap/database, @cap/ui, @cap/utils), move react/react-dom (and next if only for types) into peerDependencies —and keep them in devDependencies for local builds.
apps/web/app/api/video/delete/route.ts (1)
31-34: Map PolicyDenied to Forbidden to match declared errors.Declared errors include Forbidden; handler currently returns Unauthorized.
Apply:
- PolicyDenied: () => new HttpApiError.Unauthorized(), + PolicyDenied: () => new HttpApiError.Forbidden(),apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx (2)
41-45: Align ref types across components (accept null)The FolderOptions component signatures should accept React.Ref<FolderHandle | null> to match folderRefs’ type and avoid type friction.
- (riveFile: RiveFile | undefined, - ref: React.Ref<FolderHandle>, + (riveFile: RiveFile | undefined, + ref: React.Ref<FolderHandle | null>, ) => <NormalFolder riveFile={riveFile} ref={ref} />, ... - (riveFile: RiveFile | undefined, - ref: React.Ref<FolderHandle>, + (riveFile: RiveFile | undefined, + ref: React.Ref<FolderHandle | null>, ) => <BlueFolder riveFile={riveFile} ref={ref} />, ... - (riveFile: RiveFile | undefined, - ref: React.Ref<FolderHandle>, + (riveFile: RiveFile | undefined, + ref: React.Ref<FolderHandle | null>, ) => <RedFolder riveFile={riveFile} ref={ref} />, ... - (riveFile: RiveFile | undefined, - ref: React.Ref<FolderHandle>, + (riveFile: RiveFile | undefined, + ref: React.Ref<FolderHandle | null>, ) => <YellowFolder riveFile={riveFile} ref={ref} />,Also applies to: 51-53, 59-61, 67-69
172-175: Avoid unnecessary non-null castThe option.component expects RiveFile | undefined, so casting forces a stronger type than needed.
- riveFile as RiveFile, + riveFile,apps/web/app/(org)/dashboard/layout.tsx (1)
66-68: Reuse a single cookie store instanceMinor perf/readability improvement: avoid multiple awaits to cookies().
- const theme = (await cookies()).get("theme")?.value ?? "light"; - const sidebar = (await cookies()).get("sidebarCollapsed")?.value ?? "false"; - const referClicked = (await cookies()).get("referClicked")?.value ?? "false"; + const cookieStore = await cookies(); + const theme = cookieStore.get("theme")?.value ?? "light"; + const sidebar = cookieStore.get("sidebarCollapsed")?.value ?? "false"; + const referClicked = cookieStore.get("referClicked")?.value ?? "false";packages/database/auth/auth-options.ts (1)
140-144: Reuse cookie store; confirm deletions take effect in this contextConsolidate cookie access, and verify that delete() here actually persists (NextAuth event handlers may not attach to a response).
const { cookies } = await import("next/headers"); - const dubId = (await cookies()).get("dub_id")?.value; - const dubPartnerData = (await cookies()).get( - "dub_partner_data", - )?.value; + const cookieStore = await cookies(); + const dubId = cookieStore.get("dub_id")?.value; + const dubPartnerData = cookieStore.get("dub_partner_data")?.value; ... - (await cookies()).delete("dub_id"); + cookieStore.delete("dub_id"); if (dubPartnerData) { - (await cookies()).delete("dub_partner_data"); + cookieStore.delete("dub_partner_data"); }Please verify cookie deletions persist for clients after sign-in completes (e.g., by checking Set-Cookie headers or observing cookie presence post-redirect).
Also applies to: 159-162
apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx (2)
66-67: Use ReturnType for browser-safe timeout refsAvoid NodeJS.Timeout in browser bundles.
- const retryTimeout = useRef<NodeJS.Timeout | null>(null); + const retryTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
97-114: Remove inline comments per codebase conventionThe repository disallows inline comments in TS/TSX. Please remove these comment lines.
Also applies to: 198-214, 216-220, 262-267, 320-331
apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx (3)
35-35: Drop unused RefObject import (and use React.Ref for icon prop)RefObject isn’t needed if the icon prop accepts a generic React.Ref.
-import { cloneElement, RefObject, useRef, useState } from "react"; +import { cloneElement, useRef, useState } from "react";
456-460: Loosen icon ref typing to React.Ref to match useRefThis avoids friction between RefObject vs MutableRefObject from useRef.
- icon: React.ReactElement<{ - ref: RefObject<CogIconHandle | null>; + icon: React.ReactElement<{ + ref: React.Ref<CogIconHandle | null>; className: string; size: number; }>;
465-465: Optional: make local ref nullableAlign with the prop type and typical forwardRef patterns.
- const iconRef = useRef<CogIconHandle>(null); + const iconRef = useRef<CogIconHandle | null>(null);apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx (2)
31-32: Remove unused RefObject importNot needed if MenuItem icon prop uses React.Ref.
- useRef, - useState, - RefObject, + useRef, + useState,
322-326: Loosen MenuItem icon ref typing to React.RefConsistent with useRef and various icon components.
- icon: React.ReactElement<{ - ref: RefObject<DownloadIconHandle | null>; + icon: React.ReactElement<{ + ref: React.Ref<DownloadIconHandle | null>; className: string; size: number; }>;apps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsx (1)
54-58: Remove inline comments per repository rulesInline and block comments are disallowed in TS/TSX; please remove these lines.
- // Reset spaceName when dialog opens or space changes ... - // If the user removed the icon, send a removeIcon flag ... - {/* Space Members Input */}Also applies to: 186-189, 235-235
apps/web/app/api/videos/[videoId]/retry-transcription/route.ts (1)
10-19: PreserveVideoIdbranding instead of casting.Casting the awaited params to
{ videoId: Video.VideoId }sidesteps the branding check we previously had when the type flowed directly from the handler signature. We can keep the stronger type guarantees by re-branding the string returned from the params promise before proceeding.Apply this diff to restore the branded validation:
- const { videoId } = (await props.params) as { videoId: Video.VideoId }; + const params = await props.params; + const videoId = Video.VideoId.make(params.videoId);apps/web/components/pages/_components/ComparePlans.tsx (1)
59-61: Tighten RefObject types; adjust useRef generics to include null.RefObject already models current: T | null. Prefer RefObject and make useRef generic include null for strictNullChecks.
- commercialArtRef: React.RefObject<CommercialArtRef | null>; - proArtRef: React.RefObject<ProArtRef | null>; + commercialArtRef: React.RefObject<CommercialArtRef>; + proArtRef: React.RefObject<ProArtRef>;Also update initial refs:
- const commercialArtRef = useRef<CommercialArtRef>(null); - const proArtRef = useRef<ProArtRef>(null); + const commercialArtRef = useRef<CommercialArtRef | null>(null); + const proArtRef = useRef<ProArtRef | null>(null);apps/web/app/(org)/dashboard/folder/[id]/page.tsx (1)
17-21: Signature migration to Promise-based params looks correct.Consider branding the id once locally before use if downstream APIs expect FolderId brands.
const id = Folder.FolderId.make(params.id);apps/web/package.json (1)
6-9: Be cautious enabling turbopack for production builds.next build --turbopack is still evolving; confirm it’s stable for your deployment targets or gate behind an env flag.
apps/web/app/(org)/verify-otp/page.tsx (1)
16-22: Validate and constrain next redirect target to prevent open redirects.Limit next to same-origin relative paths (e.g., starting with "/").
- redirect(searchParams.next || "/dashboard"); + const next = (searchParams.next && searchParams.next.startsWith("/")) ? searchParams.next : "/dashboard"; + redirect(next);apps/web/app/api/releases/macos/route.ts (3)
21-46: Select the correct macOS asset by architecture and remove unused arch normalization.Currently, arch is normalized but never used; the code picks the first .dmg, which can return the wrong build. Prefer deterministic selection (Apple Silicon first), then fall back.
Apply:
- if (params.arch === "x86_64") { - params.arch = "x64"; - } + const preferredArchOrder = ["aarch64", "arm64", "universal", "x86_64", "x64"]; @@ - const asset = release.assets.find((asset) => asset.name.endsWith(".dmg")); + const asset = + release.assets.find( + (a) => + a.name.endsWith(".dmg") && + preferredArchOrder.some((arch) => a.name.toLowerCase().includes(arch)), + ) ?? release.assets.find((a) => a.name.endsWith(".dmg"));
47-50: Return a more accurate error status/message.400 suggests a client error; this is a backend fetch failure. Use 502 and a clearer message.
- return Response.json({ error: "Missing required fields" }, { status: 400 }); + return Response.json( + { error: "Failed to fetch latest release" }, + { status: 502 }, + );
9-12: Remove theas anyby giving GET an explicit type.This avoids
anyand keeps strict TypeScript.-export const GET = (async ( - req: Request, - props: { - params: Promise<{ - version: string; - target: string; - arch: string; - }>; - }, -) => { +export async function GET( + req: Request, + props: { + params: Promise<{ + version: string; + target: string; + arch: string; + }>; + }, +) { @@ -}) as any; +}Also applies to: 51-51
apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
14-14: Normalize import path.Double slash is unnecessary and can confuse tooling; use a single slash.
-import { InviteAccept } from ".//InviteAccept"; +import { InviteAccept } from "./InviteAccept";apps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsx (1)
142-142: PreferReturnType<typeof setInterval>for browser timers.Line 142: In the browser,
setIntervalresolves tonumber, so storing it asNodeJS.Timeoutcan produce type friction when DOM libs take precedence. Swapping toReturnType<typeof setInterval>keeps both Node and DOM signatures happy.- const pollInterval = useRef<NodeJS.Timeout | undefined>(undefined); + const pollInterval = useRef<ReturnType<typeof setInterval> | undefined>(undefined);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (61)
apps/desktop/package.json(1 hunks)apps/web/actions/videos/password.ts(1 hunks)apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx(2 hunks)apps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx(2 hunks)apps/web/app/(org)/dashboard/_components/actions.ts(1 hunks)apps/web/app/(org)/dashboard/caps/components/FoldersDropdown.tsx(1 hunks)apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/caps/page.tsx(1 hunks)apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/folder/[id]/page.tsx(1 hunks)apps/web/app/(org)/dashboard/layout.tsx(1 hunks)apps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsx(1 hunks)apps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsx(2 hunks)apps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsx(1 hunks)apps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsx(1 hunks)apps/web/app/(org)/invite/[inviteId]/page.tsx(2 hunks)apps/web/app/(org)/verify-otp/page.tsx(1 hunks)apps/web/app/(site)/[slug]/page.tsx(2 hunks)apps/web/app/(site)/blog/[slug]/page.tsx(2 hunks)apps/web/app/(site)/docs/[...slug]/page.tsx(2 hunks)apps/web/app/(site)/docs/[slug]/page.tsx(2 hunks)apps/web/app/(site)/download/[platform]/route.ts(1 hunks)apps/web/app/(site)/page.tsx(1 hunks)apps/web/app/(site)/tools/convert/[conversionPath]/page.tsx(2 hunks)apps/web/app/api/erpc/route.ts(1 hunks)apps/web/app/api/playlist/route.ts(2 hunks)apps/web/app/api/releases/macos/route.ts(2 hunks)apps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.ts(1 hunks)apps/web/app/api/utils.ts(1 hunks)apps/web/app/api/video/comment/route.ts(1 hunks)apps/web/app/api/video/delete/route.ts(1 hunks)apps/web/app/api/videos/[videoId]/retry-transcription/route.ts(1 hunks)apps/web/app/embed/[videoId]/page.tsx(3 hunks)apps/web/app/robots.ts(1 hunks)apps/web/app/s/[videoId]/_components/CapVideoPlayer.tsx(1 hunks)apps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsx(1 hunks)apps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsx(1 hunks)apps/web/app/s/[videoId]/_components/tabs/Activity/index.tsx(1 hunks)apps/web/app/s/[videoId]/page.tsx(5 hunks)apps/web/components/features/FeaturePage.tsx(1 hunks)apps/web/components/forms/NewOrganization.tsx(1 hunks)apps/web/components/pages/HomePage/Features.tsx(1 hunks)apps/web/components/pages/HomePage/RecordingModes.tsx(1 hunks)apps/web/components/pages/_components/ComparePlans.tsx(1 hunks)apps/web/components/seo/types.ts(1 hunks)apps/web/lib/features/transform.ts(1 hunks)apps/web/lib/server.ts(3 hunks)apps/web/next.config.mjs(0 hunks)apps/web/package.json(5 hunks)apps/web/tsconfig.json(1 hunks)apps/web/utils/getBootstrapData.ts(1 hunks)apps/workflow-manager/package.json(1 hunks)apps/workflow-runner/package.json(1 hunks)packages/database/auth/auth-options.ts(3 hunks)packages/database/package.json(2 hunks)packages/ui/package.json(1 hunks)packages/utils/package.json(1 hunks)packages/web-api-contract-effect/package.json(1 hunks)packages/web-backend/package.json(1 hunks)packages/web-domain/package.json(1 hunks)
💤 Files with no reviewable changes (1)
- apps/web/next.config.mjs
🧰 Additional context used
📓 Path-based instructions (10)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/(site)/tools/convert/[conversionPath]/page.tsxapps/web/components/pages/HomePage/RecordingModes.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/(org)/dashboard/caps/components/FoldersDropdown.tsxapps/web/app/(org)/dashboard/folder/[id]/page.tsxapps/web/app/(site)/download/[platform]/route.tsapps/web/components/pages/HomePage/Features.tsxapps/web/app/api/video/comment/route.tsapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsxapps/web/app/api/utils.tsapps/web/actions/videos/password.tsapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(site)/blog/[slug]/page.tsxapps/web/lib/features/transform.tsapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsxapps/web/app/s/[videoId]/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/(site)/[slug]/page.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsxapps/web/app/embed/[videoId]/page.tsxapps/web/lib/server.tsapps/web/app/robots.tsapps/web/app/(org)/verify-otp/page.tsxapps/web/components/seo/types.tsapps/web/components/forms/NewOrganization.tsxapps/web/app/(site)/docs/[...slug]/page.tsxapps/web/app/(org)/dashboard/_components/actions.tsapps/web/components/features/FeaturePage.tsxapps/web/utils/getBootstrapData.tsapps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsxapps/web/app/(org)/invite/[inviteId]/page.tsxapps/web/app/api/releases/macos/route.tsapps/web/app/(site)/page.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.tsapps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.tsapps/web/app/api/videos/[videoId]/retry-transcription/route.tsapps/web/app/(org)/dashboard/_components/Navbar/Top.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsxapps/web/components/pages/_components/ComparePlans.tsxapps/web/app/(site)/docs/[slug]/page.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/(site)/tools/convert/[conversionPath]/page.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/(org)/dashboard/caps/components/FoldersDropdown.tsxapps/web/app/(org)/dashboard/folder/[id]/page.tsxapps/web/app/(site)/download/[platform]/route.tsapps/web/app/api/video/comment/route.tsapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsxapps/web/app/api/utils.tsapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(site)/blog/[slug]/page.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsxapps/web/app/s/[videoId]/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/(site)/[slug]/page.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsxapps/web/app/embed/[videoId]/page.tsxapps/web/app/robots.tsapps/web/app/(org)/verify-otp/page.tsxapps/web/app/(site)/docs/[...slug]/page.tsxapps/web/app/(org)/dashboard/_components/actions.tsapps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsxapps/web/app/(org)/invite/[inviteId]/page.tsxapps/web/app/api/releases/macos/route.tsapps/web/app/(site)/page.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.tsapps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.tsapps/web/app/api/videos/[videoId]/retry-transcription/route.tsapps/web/app/(org)/dashboard/_components/Navbar/Top.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsxapps/web/app/(site)/docs/[slug]/page.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/(site)/tools/convert/[conversionPath]/page.tsxapps/web/components/pages/HomePage/RecordingModes.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/(org)/dashboard/caps/components/FoldersDropdown.tsxapps/web/app/(org)/dashboard/folder/[id]/page.tsxapps/web/app/(site)/download/[platform]/route.tsapps/web/components/pages/HomePage/Features.tsxapps/web/app/api/video/comment/route.tsapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsxapps/web/app/api/utils.tsapps/web/actions/videos/password.tsapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(site)/blog/[slug]/page.tsxapps/web/lib/features/transform.tsapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsxapps/web/app/s/[videoId]/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsxpackages/database/auth/auth-options.tsapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/(site)/[slug]/page.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsxapps/web/app/embed/[videoId]/page.tsxapps/web/lib/server.tsapps/web/app/robots.tsapps/web/app/(org)/verify-otp/page.tsxapps/web/components/seo/types.tsapps/web/components/forms/NewOrganization.tsxapps/web/app/(site)/docs/[...slug]/page.tsxapps/web/app/(org)/dashboard/_components/actions.tsapps/web/components/features/FeaturePage.tsxapps/web/utils/getBootstrapData.tsapps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsxapps/web/app/(org)/invite/[inviteId]/page.tsxapps/web/app/api/releases/macos/route.tsapps/web/app/(site)/page.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.tsapps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.tsapps/web/app/api/videos/[videoId]/retry-transcription/route.tsapps/web/app/(org)/dashboard/_components/Navbar/Top.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsxapps/web/components/pages/_components/ComparePlans.tsxapps/web/app/(site)/docs/[slug]/page.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/(site)/tools/convert/[conversionPath]/page.tsxapps/web/components/pages/HomePage/RecordingModes.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/(org)/dashboard/caps/components/FoldersDropdown.tsxapps/web/app/(org)/dashboard/folder/[id]/page.tsxapps/web/app/(site)/download/[platform]/route.tsapps/web/components/pages/HomePage/Features.tsxapps/web/app/api/video/comment/route.tsapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsxapps/web/app/api/utils.tsapps/web/actions/videos/password.tsapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(site)/blog/[slug]/page.tsxapps/web/lib/features/transform.tsapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsxapps/web/app/s/[videoId]/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsxpackages/database/auth/auth-options.tsapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/(site)/[slug]/page.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsxapps/web/app/embed/[videoId]/page.tsxapps/web/lib/server.tsapps/web/app/robots.tsapps/web/app/(org)/verify-otp/page.tsxapps/web/components/seo/types.tsapps/web/components/forms/NewOrganization.tsxapps/web/app/(site)/docs/[...slug]/page.tsxapps/web/app/(org)/dashboard/_components/actions.tsapps/web/components/features/FeaturePage.tsxapps/web/utils/getBootstrapData.tsapps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsxapps/web/app/(org)/invite/[inviteId]/page.tsxapps/web/app/api/releases/macos/route.tsapps/web/app/(site)/page.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.tsapps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.tsapps/web/app/api/videos/[videoId]/retry-transcription/route.tsapps/web/app/(org)/dashboard/_components/Navbar/Top.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsxapps/web/components/pages/_components/ComparePlans.tsxapps/web/app/(site)/docs/[slug]/page.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/(site)/tools/convert/[conversionPath]/page.tsxapps/web/components/pages/HomePage/RecordingModes.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/(org)/dashboard/caps/components/FoldersDropdown.tsxapps/web/app/(org)/dashboard/folder/[id]/page.tsxapps/web/app/(site)/download/[platform]/route.tsapps/web/components/pages/HomePage/Features.tsxapps/web/app/api/video/comment/route.tsapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsxapps/web/app/api/utils.tsapps/web/actions/videos/password.tsapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(site)/blog/[slug]/page.tsxapps/web/lib/features/transform.tsapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsxapps/web/app/s/[videoId]/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsxpackages/database/auth/auth-options.tsapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/(site)/[slug]/page.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsxapps/web/app/embed/[videoId]/page.tsxapps/web/lib/server.tsapps/web/app/robots.tsapps/web/app/(org)/verify-otp/page.tsxapps/web/components/seo/types.tsapps/web/components/forms/NewOrganization.tsxapps/web/app/(site)/docs/[...slug]/page.tsxapps/web/app/(org)/dashboard/_components/actions.tsapps/web/components/features/FeaturePage.tsxapps/web/utils/getBootstrapData.tsapps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsxapps/web/app/(org)/invite/[inviteId]/page.tsxapps/web/app/api/releases/macos/route.tsapps/web/app/(site)/page.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.tsapps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.tsapps/web/app/api/videos/[videoId]/retry-transcription/route.tsapps/web/app/(org)/dashboard/_components/Navbar/Top.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsxapps/web/components/pages/_components/ComparePlans.tsxapps/web/app/(site)/docs/[slug]/page.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/(site)/tools/convert/[conversionPath]/page.tsxapps/web/components/pages/HomePage/RecordingModes.tsxapps/web/app/s/[videoId]/_components/CapVideoPlayer.tsxapps/web/app/(org)/dashboard/caps/components/FoldersDropdown.tsxapps/web/app/(org)/dashboard/folder/[id]/page.tsxapps/web/app/(site)/download/[platform]/route.tsapps/web/components/pages/HomePage/Features.tsxapps/web/app/api/video/comment/route.tsapps/web/app/(org)/dashboard/caps/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsxapps/web/app/api/utils.tsapps/web/actions/videos/password.tsapps/web/app/s/[videoId]/_components/HLSVideoPlayer.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsxapps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsxapps/web/app/(site)/blog/[slug]/page.tsxapps/web/lib/features/transform.tsapps/web/app/s/[videoId]/_components/tabs/Activity/Comments.tsxapps/web/app/s/[videoId]/page.tsxapps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsxapps/web/app/(org)/dashboard/_components/Navbar/Items.tsxapps/web/app/(site)/[slug]/page.tsxapps/web/app/(org)/dashboard/layout.tsxapps/web/app/(org)/dashboard/settings/organization/components/CustomDomainDialog/CustomDomainDialog.tsxapps/web/app/embed/[videoId]/page.tsxapps/web/lib/server.tsapps/web/app/robots.tsapps/web/app/(org)/verify-otp/page.tsxapps/web/components/seo/types.tsapps/web/components/forms/NewOrganization.tsxapps/web/app/(site)/docs/[...slug]/page.tsxapps/web/app/(org)/dashboard/_components/actions.tsapps/web/components/features/FeaturePage.tsxapps/web/utils/getBootstrapData.tsapps/web/app/(org)/dashboard/_components/Navbar/SpaceDialog.tsxapps/web/app/(org)/invite/[inviteId]/page.tsxapps/web/app/api/releases/macos/route.tsapps/web/app/(site)/page.tsxapps/web/app/s/[videoId]/_components/tabs/Activity/index.tsxapps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.tsapps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.tsapps/web/app/api/videos/[videoId]/retry-transcription/route.tsapps/web/app/(org)/dashboard/_components/Navbar/Top.tsxapps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsxapps/web/components/pages/_components/ComparePlans.tsxapps/web/app/(site)/docs/[slug]/page.tsx
apps/web/app/api/**/route.ts
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/api/**/route.ts: Place API routes only under apps/web/app/api and implement each route in a route.ts file
Construct API routes with @effect/platform HttpApi/HttpApiBuilder and export only the handler from apiToHandler(ApiLive)
Map domain errors to transport errors with HttpApiError.* and keep error translation exhaustive
Use HttpAuthMiddleware for required auth and provideOptionalAuth for guest routes; avoid duplicate session lookups
Provide dependencies via Layer.provide in API routes instead of manual provideService calls
Files:
apps/web/app/api/video/comment/route.tsapps/web/app/api/releases/macos/route.tsapps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.tsapps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.tsapps/web/app/api/videos/[videoId]/retry-transcription/route.ts
apps/web/app/api/*
📄 CodeRabbit inference engine (AGENTS.md)
apps/web/app/api/*: API routes in Next.js (apps/web/app/api/*) must use@effect/platform'sHttpApibuilder and follow the existing class/group/endpoint pattern; avoid ad-hoc handlers.
Convert effectful APIs to Next.js handlers usingapiToHandler(ApiLive)and export only the returnedhandler; avoid callingrunPromisedirectly in route files.
Acquire backend services insideEffect.genand wire them usingLayer.provide/HttpApiBuilder.group, translating errors toHttpApiErroras appropriate.
On the server, always run effects throughEffectRuntime.runPromiseafterprovideOptionalAuthto ensure cookies and per-request context are attached.
Files:
apps/web/app/api/utils.ts
apps/web/actions/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
All Groq/OpenAI calls must be implemented in Next.js Server Actions under apps/web/actions; do not place AI calls elsewhere
Files:
apps/web/actions/videos/password.ts
packages/web-api-contract-effect/**
📄 CodeRabbit inference engine (CLAUDE.md)
Update shared HTTP contracts in packages/web-api-contract-effect alongside any API route changes to keep schemas in sync
Files:
packages/web-api-contract-effect/package.json
🧠 Learnings (6)
📚 Learning: 2025-09-22T14:17:47.380Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-22T14:17:47.380Z
Learning: Applies to **/*.{ts,tsx} : Use strict TypeScript and avoid any; leverage shared types from packages
Applied to files:
apps/web/tsconfig.json
📚 Learning: 2025-09-22T14:19:55.985Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: AGENTS.md:0-0
Timestamp: 2025-09-22T14:19:55.985Z
Learning: Applies to apps/web/app/api/* : On the server, always run effects through `EffectRuntime.runPromise` after `provideOptionalAuth` to ensure cookies and per-request context are attached.
Applied to files:
apps/web/lib/server.ts
📚 Learning: 2025-09-22T14:19:55.985Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: AGENTS.md:0-0
Timestamp: 2025-09-22T14:19:55.985Z
Learning: Applies to apps/web/app/api/* : API routes in Next.js (`apps/web/app/api/*`) must use `effect/platform`'s `HttpApi` builder and follow the existing class/group/endpoint pattern; avoid ad-hoc handlers.
Applied to files:
apps/web/lib/server.ts
📚 Learning: 2025-09-22T14:17:47.380Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-22T14:17:47.380Z
Learning: Applies to apps/web/app/api/**/route.ts : Construct API routes with effect/platform HttpApi/HttpApiBuilder and export only the handler from apiToHandler(ApiLive)
Applied to files:
apps/web/app/api/erpc/route.tsapps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.ts
📚 Learning: 2025-09-22T14:19:55.985Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: AGENTS.md:0-0
Timestamp: 2025-09-22T14:19:55.985Z
Learning: Applies to apps/web/app/api/* : Convert effectful APIs to Next.js handlers using `apiToHandler(ApiLive)` and export only the returned `handler`; avoid calling `runPromise` directly in route files.
Applied to files:
apps/web/app/api/video/delete/route.tsapps/web/app/api/playlist/route.ts
📚 Learning: 2025-09-22T14:17:47.380Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-22T14:17:47.380Z
Learning: Applies to packages/web-api-contract-effect/** : Update shared HTTP contracts in packages/web-api-contract-effect alongside any API route changes to keep schemas in sync
Applied to files:
packages/web-api-contract-effect/package.jsonpackages/web-backend/package.jsonpackages/web-domain/package.json
🧬 Code graph analysis (21)
apps/web/app/(site)/tools/convert/[conversionPath]/page.tsx (5)
apps/web/app/(site)/docs/[...slug]/page.tsx (1)
generateMetadata(22-74)apps/web/app/embed/[videoId]/page.tsx (1)
generateMetadata(35-113)apps/web/app/(site)/blog/[slug]/page.tsx (1)
generateMetadata(24-68)apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
generateMetadata(20-33)apps/web/app/(site)/[slug]/page.tsx (1)
generateMetadata(10-32)
apps/web/app/(org)/dashboard/folder/[id]/page.tsx (1)
packages/web-domain/src/Folder.ts (3)
Folder(19-27)FolderId(8-8)FolderId(9-9)
apps/web/app/api/video/comment/route.ts (2)
apps/web/app/api/erpc/route.ts (1)
POST(18-18)apps/web/utils/helpers.ts (1)
rateLimitMiddleware(30-64)
apps/web/actions/videos/password.ts (1)
packages/database/crypto.ts (1)
encrypt(63-96)
apps/web/app/(org)/dashboard/caps/components/NewFolderDialog.tsx (1)
apps/web/app/(org)/dashboard/caps/components/Folders.tsx (1)
FolderHandle(7-10)
apps/web/app/(site)/blog/[slug]/page.tsx (5)
apps/web/app/(site)/docs/[...slug]/page.tsx (1)
generateMetadata(22-74)apps/web/app/embed/[videoId]/page.tsx (1)
generateMetadata(35-113)apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
generateMetadata(20-33)apps/web/app/(site)/[slug]/page.tsx (1)
generateMetadata(10-32)apps/web/app/(site)/docs/[slug]/page.tsx (1)
generateMetadata(14-49)
apps/web/app/s/[videoId]/page.tsx (3)
apps/web/app/(site)/docs/[...slug]/page.tsx (1)
generateMetadata(22-74)apps/web/app/embed/[videoId]/page.tsx (1)
generateMetadata(35-113)apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
generateMetadata(20-33)
apps/web/app/(org)/dashboard/spaces/[spaceId]/folder/[folderId]/page.tsx (1)
packages/web-domain/src/Folder.ts (3)
Folder(19-27)FolderId(8-8)FolderId(9-9)
apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx (1)
apps/web/app/(org)/dashboard/_components/AnimatedIcons/Cog.tsx (1)
CogIconHandle(8-11)
apps/web/app/(site)/[slug]/page.tsx (4)
apps/web/app/(site)/docs/[...slug]/page.tsx (1)
generateMetadata(22-74)apps/web/app/embed/[videoId]/page.tsx (1)
generateMetadata(35-113)apps/web/app/(site)/blog/[slug]/page.tsx (1)
generateMetadata(24-68)apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
generateMetadata(20-33)
apps/web/app/embed/[videoId]/page.tsx (2)
apps/web/app/(site)/docs/[...slug]/page.tsx (1)
generateMetadata(22-74)apps/web/app/s/[videoId]/page.tsx (1)
generateMetadata(125-254)
apps/web/app/robots.ts (1)
apps/web/lib/seo-pages.ts (1)
seoPages(31-66)
apps/web/app/(site)/docs/[...slug]/page.tsx (6)
apps/web/app/embed/[videoId]/page.tsx (1)
generateMetadata(35-113)apps/web/app/s/[videoId]/page.tsx (1)
generateMetadata(125-254)apps/web/app/(site)/blog/[slug]/page.tsx (1)
generateMetadata(24-68)apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
generateMetadata(20-33)apps/web/app/(site)/[slug]/page.tsx (1)
generateMetadata(10-32)apps/web/app/(site)/tools/convert/[conversionPath]/page.tsx (1)
generateMetadata(17-55)
apps/web/app/(org)/invite/[inviteId]/page.tsx (2)
apps/web/app/(site)/docs/[...slug]/page.tsx (1)
generateMetadata(22-74)apps/web/app/embed/[videoId]/page.tsx (1)
generateMetadata(35-113)
apps/web/app/api/releases/macos/route.ts (4)
apps/web/app/api/erpc/route.ts (1)
GET(17-17)apps/web/app/api/playlist/route.ts (1)
GET(245-245)apps/web/app/(site)/download/[platform]/route.ts (1)
GET(8-45)apps/web/app/api/releases/tauri/[version]/[target]/[arch]/route.ts (1)
GET(9-71)
apps/web/app/api/erpc/route.ts (3)
apps/web/app/api/playlist/route.ts (1)
GET(245-245)apps/web/app/api/releases/macos/route.ts (1)
GET(9-51)apps/web/app/api/video/comment/route.ts (2)
GET(96-98)POST(91-94)
apps/web/app/api/playlist/route.ts (4)
apps/web/app/embed/[videoId]/page.tsx (1)
dynamic(26-26)apps/web/app/s/[videoId]/page.tsx (1)
dynamic(37-37)apps/web/app/api/settings/billing/usage/route.ts (2)
dynamic(7-7)GET(9-47)apps/web/app/api/erpc/route.ts (1)
GET(17-17)
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx (1)
apps/web/app/(org)/dashboard/_components/AnimatedIcons/Download.tsx (1)
DownloadIconHandle(9-12)
apps/web/app/(org)/dashboard/folder/[id]/components/SubfolderDialog.tsx (1)
apps/web/app/(org)/dashboard/caps/components/Folders.tsx (1)
FolderHandle(7-10)
apps/web/components/pages/_components/ComparePlans.tsx (2)
apps/web/components/pages/HomePage/Pricing/CommercialArt.tsx (1)
CommercialArtRef(5-8)apps/web/components/pages/HomePage/Pricing/ProArt.tsx (1)
ProArtRef(5-8)
apps/web/app/(site)/docs/[slug]/page.tsx (7)
apps/web/app/(site)/docs/[...slug]/page.tsx (2)
generateMetadata(22-74)DocPage(76-201)apps/web/app/embed/[videoId]/page.tsx (1)
generateMetadata(35-113)apps/web/app/s/[videoId]/page.tsx (1)
generateMetadata(125-254)apps/web/app/(site)/blog/[slug]/page.tsx (1)
generateMetadata(24-68)apps/web/app/(org)/invite/[inviteId]/page.tsx (1)
generateMetadata(20-33)apps/web/app/(site)/[slug]/page.tsx (1)
generateMetadata(10-32)apps/web/app/(site)/tools/convert/[conversionPath]/page.tsx (1)
generateMetadata(17-55)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Vercel Agent Review
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
apps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsx
Show resolved
Hide resolved
|
@coderabbitai don't review this pr |
|
Tip For best results, initiate chat on the files or code changes. @oscartbeaumont Understood! I won't review this PR. The automated review will be skipped for PR #1033. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx(2 hunks)apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx(2 hunks)apps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/web/app/(org)/dashboard/spaces/[spaceId]/components/VirtualizedVideoGrid.tsx
- apps/web/app/(org)/dashboard/_components/Navbar/Items.tsx
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx
🧬 Code graph analysis (1)
apps/web/app/(org)/dashboard/_components/Navbar/Top.tsx (1)
apps/web/app/(org)/dashboard/_components/AnimatedIcons/Download.tsx (1)
DownloadIconHandle(9-12)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Vercel Agent Review
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
|
@oscartbeaumont I understand. I'll pause the automatic reviews for this PR as requested. ✅ Actions performedReviews paused. |
Me don't like waiting for Next.js to compile. Upgrade to the latest version so we can potentially enable Turbopack in a follow up PR?
This upgrade was mostly done via the Next.js codemod.
Summary by CodeRabbit
Chores
Performance
Bug Fixes
Refactor