Skip to content
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

Pre render LandingPage for SEO #115

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open

Conversation

g-bar
Copy link
Contributor

@g-bar g-bar commented Mar 7, 2025

Currently the LandingPage fetches the content from sanity on the client, which means it's not getting pre-rendered which is not optimal for SEO.

To check this try disabling javascript on your browser and open the app on develop branch
No content gets displayed other than the menu and footer which are rendered in server components.

Capture d’écran 2025-03-07 à 09 00 33

Switch to this branch and reload.
Text renders for that SEO benefit.

Capture d’écran 2025-03-07 à 09 03 37

Comment on lines -31 to 50
export function useSanity<T>(
query: string,
typeGuard: (data: unknown) => data is T
): T | undefined | null {
const [data, setData] = React.useState<T | undefined | null>(undefined);
React.useEffect(() => {
fetchSanity(query, typeGuard)
.then(setData)
.catch((ex) => {
logError('There was an exception in this Sanity query:', query);
logError(ex);
setData(null);
});
}, [query, typeGuard]);
export function useSanity<T>(query: string, typeGuard: (data: unknown) => data is T) {
const data = useAtomValue(dataFamily({ query, typeGuard })) as T | undefined | null;
return data;
}
Copy link
Contributor Author

@g-bar g-bar Mar 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the main culprit. useEffect only runs client side, jotai's useAtom runs server and client side.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice job gil
i am not sure i understand the last part "jotai's useAtom runs server and client side."

Copy link
Contributor Author

@g-bar g-bar Mar 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jotai implements data fetching with suspense see here: https://dev.to/smitterhane/swap-out-useeffect-with-suspense-for-data-fetching-in-react-2leb

Suspense approach(Render-as-You-Fetch).

Suspense for Data Fetching is a new feature. It lets you also use <React.Suspense> to declaratively "wait" for anything else, including data. In this article, we focus on the data fetching use case, but it can also wait for images, scripts, or other asynchronous work.

With Suspense, we don’t wait to render before we can start fetching. In fact, we kick off the network request(fetching) and immediately start rendering

Which means when you use useAtom the content gets fetched in the body on the function not in an effect, therefore it runs during SSR.

Basically we get SSR by merely using atoms instead of fetching in useEffect. (Except where we use sessionAtom because nextAuth uses an effect internally to store the session, so we lose the benefit, but that's another story).

Downside is we fetch the data twice, once during SSR and again on the client, in the future we could refactor this to fetch in a RSC and pass to the client in props so we avoid double fetching.

@g-bar g-bar changed the title Pre render static pages for SEO Pre render LandingPage for SEO Mar 7, 2025
@g-bar g-bar marked this pull request as ready for review March 7, 2025 08:07
@g-bar g-bar requested review from tolokoban, pgetta and bilalesi March 7, 2025 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants