Skip to content

Commit 20766d5

Browse files
authored
improve fcp (#72)
1 parent 3a48f61 commit 20766d5

File tree

2 files changed

+76
-59
lines changed

2 files changed

+76
-59
lines changed

app/layout.tsx

Lines changed: 41 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { Analytics } from "@vercel/analytics/react";
44
import { SpeedInsights } from "@vercel/speed-insights/next";
55
import { ReactFlowProvider } from "@xyflow/react";
66
import { Provider } from "jotai";
7-
import type { ReactNode } from "react";
7+
import { type ReactNode, Suspense } from "react";
88
import { AuthProvider } from "@/components/auth/provider";
9+
import { GitHubStarsLoader } from "@/components/github-stars-loader";
910
import { GitHubStarsProvider } from "@/components/github-stars-provider";
1011
import { ThemeProvider } from "@/components/theme-provider";
1112
import { Toaster } from "@/components/ui/sonner";
@@ -27,69 +28,50 @@ export const viewport: Viewport = {
2728
viewportFit: "cover",
2829
};
2930

30-
const GITHUB_REPO = "vercel-labs/workflow-builder-template";
31-
32-
async function getGitHubStars(): Promise<number | null> {
33-
try {
34-
const response = await fetch(
35-
`https://api.github.com/repos/${GITHUB_REPO}`,
36-
{
37-
headers: {
38-
Accept: "application/vnd.github.v3+json",
39-
...(process.env.GITHUB_TOKEN && {
40-
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
41-
}),
42-
},
43-
next: { revalidate: 3600 }, // Cache for 1 hour
44-
}
45-
);
46-
47-
if (!response.ok) {
48-
return null;
49-
}
50-
51-
const data = await response.json();
52-
return data.stargazers_count;
53-
} catch {
54-
return null;
55-
}
56-
}
57-
5831
type RootLayoutProps = {
5932
children: ReactNode;
6033
};
6134

62-
const RootLayout = async ({ children }: RootLayoutProps) => {
63-
const stars = await getGitHubStars();
64-
35+
// Inner content wrapped by GitHubStarsProvider (used for both loading and loaded states)
36+
function LayoutContent({ children }: { children: ReactNode }) {
6537
return (
66-
<html lang="en" suppressHydrationWarning>
67-
<body className={cn(sans.variable, mono.variable, "antialiased")}>
68-
<ThemeProvider
69-
attribute="class"
70-
defaultTheme="system"
71-
disableTransitionOnChange
72-
enableSystem
73-
>
74-
<Provider>
75-
<AuthProvider>
76-
<GitHubStarsProvider stars={stars}>
77-
<ReactFlowProvider>
78-
<PersistentCanvas />
79-
<div className="pointer-events-none relative z-10">
80-
{children}
81-
</div>
82-
</ReactFlowProvider>
83-
</GitHubStarsProvider>
84-
<Toaster />
85-
</AuthProvider>
86-
</Provider>
87-
</ThemeProvider>
88-
<Analytics />
89-
<SpeedInsights />
90-
</body>
91-
</html>
38+
<ReactFlowProvider>
39+
<PersistentCanvas />
40+
<div className="pointer-events-none relative z-10">{children}</div>
41+
</ReactFlowProvider>
9242
);
93-
};
43+
}
44+
45+
const RootLayout = ({ children }: RootLayoutProps) => (
46+
<html lang="en" suppressHydrationWarning>
47+
<body className={cn(sans.variable, mono.variable, "antialiased")}>
48+
<ThemeProvider
49+
attribute="class"
50+
defaultTheme="system"
51+
disableTransitionOnChange
52+
enableSystem
53+
>
54+
<Provider>
55+
<AuthProvider>
56+
<Suspense
57+
fallback={
58+
<GitHubStarsProvider stars={null}>
59+
<LayoutContent>{children}</LayoutContent>
60+
</GitHubStarsProvider>
61+
}
62+
>
63+
<GitHubStarsLoader>
64+
<LayoutContent>{children}</LayoutContent>
65+
</GitHubStarsLoader>
66+
</Suspense>
67+
<Toaster />
68+
</AuthProvider>
69+
</Provider>
70+
</ThemeProvider>
71+
<Analytics />
72+
<SpeedInsights />
73+
</body>
74+
</html>
75+
);
9476

9577
export default RootLayout;

components/github-stars-loader.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { ReactNode } from "react";
2+
import { GitHubStarsProvider } from "@/components/github-stars-provider";
3+
4+
const GITHUB_REPO = "vercel-labs/workflow-builder-template";
5+
6+
async function getGitHubStars(): Promise<number | null> {
7+
try {
8+
const response = await fetch(
9+
`https://api.github.com/repos/${GITHUB_REPO}`,
10+
{
11+
headers: {
12+
Accept: "application/vnd.github.v3+json",
13+
...(process.env.GITHUB_TOKEN && {
14+
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
15+
}),
16+
},
17+
next: { revalidate: 3600 }, // Cache for 1 hour
18+
}
19+
);
20+
21+
if (!response.ok) {
22+
return null;
23+
}
24+
25+
const data = await response.json();
26+
return data.stargazers_count;
27+
} catch {
28+
return null;
29+
}
30+
}
31+
32+
export async function GitHubStarsLoader({ children }: { children: ReactNode }) {
33+
const stars = await getGitHubStars();
34+
return <GitHubStarsProvider stars={stars}>{children}</GitHubStarsProvider>;
35+
}

0 commit comments

Comments
 (0)