From e6bbab1e4eaa30b6c8332568b729e1103f47fb3c Mon Sep 17 00:00:00 2001 From: Minit Jain Date: Thu, 29 Oct 2026 16:31:23 +0530 Subject: [PATCH 1/4] fix(web): scope dashboard loading skeletons to their own pages Next prefetches a dynamic route down to the first loading.tsx on its path, so child routes flashed their parent's skeleton (caps grid on /caps/record, General form on org settings tabs, space grid on space folders) before their own. Move those pages and skeletons into route groups so each loading.tsx covers only its page, and give the Content and Billing settings tabs skeletons that match their layout. --- .../unit/dashboard-video-count.test.ts | 4 +- .../unit/space-page-round-trips.test.ts | 2 +- .../dashboard/caps/{ => (list)}/loading.tsx | 0 .../dashboard/caps/{ => (list)}/page.tsx | 2 +- .../{ => (general)}/GeneralPage.tsx | 4 +- .../organization/{ => (general)}/loading.tsx | 0 .../organization/{ => (general)}/page.tsx | 0 .../settings/organization/billing/loading.tsx | 59 +++++++++++++++++++ .../settings/organization/content/loading.tsx | 54 +++++++++++++++++ .../organization/integrations/loading.tsx | 1 + .../organization/preferences/loading.tsx | 1 + .../organization/security/loading.tsx | 1 + .../[spaceId]/{ => (space)}/loading.tsx | 0 .../spaces/[spaceId]/{ => (space)}/page.tsx | 2 +- 14 files changed, 123 insertions(+), 7 deletions(-) rename apps/web/app/(org)/dashboard/caps/{ => (list)}/loading.tsx (100%) rename apps/web/app/(org)/dashboard/caps/{ => (list)}/page.tsx (99%) rename apps/web/app/(org)/dashboard/settings/organization/{ => (general)}/GeneralPage.tsx (66%) rename apps/web/app/(org)/dashboard/settings/organization/{ => (general)}/loading.tsx (100%) rename apps/web/app/(org)/dashboard/settings/organization/{ => (general)}/page.tsx (100%) create mode 100644 apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx create mode 100644 apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx create mode 100644 apps/web/app/(org)/dashboard/settings/organization/integrations/loading.tsx create mode 100644 apps/web/app/(org)/dashboard/settings/organization/preferences/loading.tsx create mode 100644 apps/web/app/(org)/dashboard/settings/organization/security/loading.tsx rename apps/web/app/(org)/dashboard/spaces/[spaceId]/{ => (space)}/loading.tsx (100%) rename apps/web/app/(org)/dashboard/spaces/[spaceId]/{ => (space)}/page.tsx (99%) diff --git a/apps/web/__tests__/unit/dashboard-video-count.test.ts b/apps/web/__tests__/unit/dashboard-video-count.test.ts index 991854bc824..4efb064d046 100644 --- a/apps/web/__tests__/unit/dashboard-video-count.test.ts +++ b/apps/web/__tests__/unit/dashboard-video-count.test.ts @@ -1,8 +1,8 @@ import type { Database, ImageUploads, Spaces } from "@cap/web-backend"; import { Effect, Layer } from "effect"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import CapsPage from "@/app/(org)/dashboard/caps/page"; -import SharedCapsPage from "@/app/(org)/dashboard/spaces/[spaceId]/page"; +import CapsPage from "@/app/(org)/dashboard/caps/(list)/page"; +import SharedCapsPage from "@/app/(org)/dashboard/spaces/[spaceId]/(space)/page"; const mocks = vi.hoisted(() => ({ query: vi.fn() })); diff --git a/apps/web/__tests__/unit/space-page-round-trips.test.ts b/apps/web/__tests__/unit/space-page-round-trips.test.ts index c59957b0542..8eeeed3e5d4 100644 --- a/apps/web/__tests__/unit/space-page-round-trips.test.ts +++ b/apps/web/__tests__/unit/space-page-round-trips.test.ts @@ -9,7 +9,7 @@ import { import { drizzle } from "drizzle-orm/mysql-proxy"; import { Effect, Layer, Option } from "effect"; import { beforeEach, describe, expect, it, vi } from "vitest"; -import SharedCapsPage from "@/app/(org)/dashboard/spaces/[spaceId]/page"; +import SharedCapsPage from "@/app/(org)/dashboard/spaces/[spaceId]/(space)/page"; import { getVideosByFolderId } from "@/lib/folder"; import { Database as BackendDatabase, diff --git a/apps/web/app/(org)/dashboard/caps/loading.tsx b/apps/web/app/(org)/dashboard/caps/(list)/loading.tsx similarity index 100% rename from apps/web/app/(org)/dashboard/caps/loading.tsx rename to apps/web/app/(org)/dashboard/caps/(list)/loading.tsx diff --git a/apps/web/app/(org)/dashboard/caps/page.tsx b/apps/web/app/(org)/dashboard/caps/(list)/page.tsx similarity index 99% rename from apps/web/app/(org)/dashboard/caps/page.tsx rename to apps/web/app/(org)/dashboard/caps/(list)/page.tsx index 52fcf06a30b..8099efb3306 100644 --- a/apps/web/app/(org)/dashboard/caps/page.tsx +++ b/apps/web/app/(org)/dashboard/caps/(list)/page.tsx @@ -23,7 +23,7 @@ import { type Array, Effect } from "effect"; import type { Metadata } from "next"; import { redirect } from "next/navigation"; import { runPromise } from "@/lib/server"; -import { Caps } from "./Caps"; +import { Caps } from "../Caps"; export const metadata: Metadata = { title: "My Caps — Cap", diff --git a/apps/web/app/(org)/dashboard/settings/organization/GeneralPage.tsx b/apps/web/app/(org)/dashboard/settings/organization/(general)/GeneralPage.tsx similarity index 66% rename from apps/web/app/(org)/dashboard/settings/organization/GeneralPage.tsx rename to apps/web/app/(org)/dashboard/settings/organization/(general)/GeneralPage.tsx index e6eb7fc73fe..ebb3b86ead4 100644 --- a/apps/web/app/(org)/dashboard/settings/organization/GeneralPage.tsx +++ b/apps/web/app/(org)/dashboard/settings/organization/(general)/GeneralPage.tsx @@ -1,7 +1,7 @@ "use client"; -import DeleteOrg from "./components/DeleteOrg"; -import { OrganizationDetailsCard } from "./components/OrganizationDetailsCard"; +import DeleteOrg from "../components/DeleteOrg"; +import { OrganizationDetailsCard } from "../components/OrganizationDetailsCard"; export function GeneralPage() { return ( diff --git a/apps/web/app/(org)/dashboard/settings/organization/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/(general)/loading.tsx similarity index 100% rename from apps/web/app/(org)/dashboard/settings/organization/loading.tsx rename to apps/web/app/(org)/dashboard/settings/organization/(general)/loading.tsx diff --git a/apps/web/app/(org)/dashboard/settings/organization/page.tsx b/apps/web/app/(org)/dashboard/settings/organization/(general)/page.tsx similarity index 100% rename from apps/web/app/(org)/dashboard/settings/organization/page.tsx rename to apps/web/app/(org)/dashboard/settings/organization/(general)/page.tsx diff --git a/apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx new file mode 100644 index 00000000000..a1063246e3e --- /dev/null +++ b/apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx @@ -0,0 +1,59 @@ +"use client"; + +import { SkeletonPage } from "@cap/ui"; + +export default function Loading() { + return ( + ( +
+
+
+ + +
+ +
+
+
+ + +
+
+ {Array(5) + .fill(0) + .map((_, index) => ( + + ))} +
+
+
+ )} + /> + ); +} diff --git a/apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx new file mode 100644 index 00000000000..19ad0d77dff --- /dev/null +++ b/apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx @@ -0,0 +1,54 @@ +"use client"; + +import { SkeletonPage } from "@cap/ui"; + +export default function Loading() { + return ( + ( +
+
+
+ + +
+
+ {["source", "destination"].map((column) => ( +
+ + + + +
+ ))} +
+
+
+ )} + /> + ); +} diff --git a/apps/web/app/(org)/dashboard/settings/organization/integrations/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/integrations/loading.tsx new file mode 100644 index 00000000000..c9b364e9f79 --- /dev/null +++ b/apps/web/app/(org)/dashboard/settings/organization/integrations/loading.tsx @@ -0,0 +1 @@ +export { default } from "../(general)/loading"; diff --git a/apps/web/app/(org)/dashboard/settings/organization/preferences/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/preferences/loading.tsx new file mode 100644 index 00000000000..c9b364e9f79 --- /dev/null +++ b/apps/web/app/(org)/dashboard/settings/organization/preferences/loading.tsx @@ -0,0 +1 @@ +export { default } from "../(general)/loading"; diff --git a/apps/web/app/(org)/dashboard/settings/organization/security/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/security/loading.tsx new file mode 100644 index 00000000000..c9b364e9f79 --- /dev/null +++ b/apps/web/app/(org)/dashboard/settings/organization/security/loading.tsx @@ -0,0 +1 @@ +export { default } from "../(general)/loading"; diff --git a/apps/web/app/(org)/dashboard/spaces/[spaceId]/loading.tsx b/apps/web/app/(org)/dashboard/spaces/[spaceId]/(space)/loading.tsx similarity index 100% rename from apps/web/app/(org)/dashboard/spaces/[spaceId]/loading.tsx rename to apps/web/app/(org)/dashboard/spaces/[spaceId]/(space)/loading.tsx diff --git a/apps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsx b/apps/web/app/(org)/dashboard/spaces/[spaceId]/(space)/page.tsx similarity index 99% rename from apps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsx rename to apps/web/app/(org)/dashboard/spaces/[spaceId]/(space)/page.tsx index 62d23a93af0..2ed1e5da918 100644 --- a/apps/web/app/(org)/dashboard/spaces/[spaceId]/page.tsx +++ b/apps/web/app/(org)/dashboard/spaces/[spaceId]/(space)/page.tsx @@ -33,7 +33,7 @@ import { Effect } from "effect"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { runPromise } from "@/lib/server"; -import { SharedCaps } from "./SharedCaps"; +import { SharedCaps } from "../SharedCaps"; export const metadata: Metadata = { title: "Shared Caps — Cap", From 0c9bcef6a9ffc1258400b2b1c94c95130a3b1084 Mon Sep 17 00:00:00 2001 From: Minit Jain Date: Thu, 29 Oct 2026 16:35:19 +0530 Subject: [PATCH 2/4] fix(web): keep settings skeleton bars inside their card on small screens --- .../(org)/dashboard/settings/organization/billing/loading.tsx | 4 ++-- .../(org)/dashboard/settings/organization/content/loading.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx index a1063246e3e..d9b010731a5 100644 --- a/apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx +++ b/apps/web/app/(org)/dashboard/settings/organization/billing/loading.tsx @@ -17,7 +17,7 @@ export default function Loading() {
diff --git a/apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx b/apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx index 19ad0d77dff..64f517a084b 100644 --- a/apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx +++ b/apps/web/app/(org)/dashboard/settings/organization/content/loading.tsx @@ -17,7 +17,7 @@ export default function Loading() {
From 6cc300122b8d0b2aa686c9185e7614a4fba9ca5f Mon Sep 17 00:00:00 2001 From: Minit Jain Date: Thu, 29 Oct 2026 16:40:20 +0530 Subject: [PATCH 3/4] fix(web): update SpaceMemberData imports after moving space page --- apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx | 2 +- .../dashboard/spaces/[spaceId]/components/MembersIndicator.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx b/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx index b2079583bdd..2455421cb20 100644 --- a/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx +++ b/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx @@ -43,7 +43,7 @@ import { type OrganizationMemberData, } from "./components/OrganizationIndicator"; import { SharedCapCard } from "./components/SharedCapCard"; -import type { SpaceMemberData } from "./page"; +import type { SpaceMemberData } from "./(space)/page"; type SharedVideoData = { id: Video.VideoId; diff --git a/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx b/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx index 03cdbbd591b..59390364b46 100644 --- a/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx +++ b/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx @@ -30,7 +30,7 @@ import { } from "@/lib/permissions/roles"; import { useDashboardContext } from "../../../Contexts"; import { setSpaceMembers } from "../actions"; -import type { SpaceMemberData } from "../page"; +import type { SpaceMemberData } from "../(space)/page"; import { MemberSelect } from "./MemberSelect"; type MembersIndicatorProps = { From c34b5fe3ac69ad8cc3d0d1424627348f8de4f312 Mon Sep 17 00:00:00 2001 From: Minit Jain Date: Thu, 29 Oct 2026 16:43:02 +0530 Subject: [PATCH 4/4] style(web): sort imports after space page move --- apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx | 2 +- .../dashboard/spaces/[spaceId]/components/MembersIndicator.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx b/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx index 2455421cb20..d9f0aa70079 100644 --- a/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx +++ b/apps/web/app/(org)/dashboard/spaces/[spaceId]/SharedCaps.tsx @@ -34,6 +34,7 @@ import type { FolderDataType } from "../../caps/components/Folder"; import { FoldersSection } from "../../caps/components/FoldersSection"; import { NewFolderDialog } from "../../caps/components/NewFolderDialog"; import { SelectedCapsBar } from "../../caps/components/SelectedCapsBar"; +import type { SpaceMemberData } from "./(space)/page"; import { AddVideosDialog } from "./components/AddVideosDialog"; import { AddVideosToOrganizationDialog } from "./components/AddVideosToOrganizationDialog"; import { EmptySharedCapState } from "./components/EmptySharedCapState"; @@ -43,7 +44,6 @@ import { type OrganizationMemberData, } from "./components/OrganizationIndicator"; import { SharedCapCard } from "./components/SharedCapCard"; -import type { SpaceMemberData } from "./(space)/page"; type SharedVideoData = { id: Video.VideoId; diff --git a/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx b/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx index 59390364b46..b1148457db6 100644 --- a/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx +++ b/apps/web/app/(org)/dashboard/spaces/[spaceId]/components/MembersIndicator.tsx @@ -29,8 +29,8 @@ import { spaceRoleLabel, } from "@/lib/permissions/roles"; import { useDashboardContext } from "../../../Contexts"; -import { setSpaceMembers } from "../actions"; import type { SpaceMemberData } from "../(space)/page"; +import { setSpaceMembers } from "../actions"; import { MemberSelect } from "./MemberSelect"; type MembersIndicatorProps = {