Proper SSR for time zones: solving the problem with @epic-web/client-hints πβ°
How @epic-web/client-hints passes time zones through cookies for correct server-rendered dates without flashes or hydration errors.

The perennial problem with server-rendering dates is that the server has no idea which time zone the user is in.
We usually end up with two less-than-ideal options:
- Render everything on the server in UTC, then βfixβ it on the client with
useEffect. The result is an unpleasant Flash of Incorrect Content (FOIC) or a hydration error. - Donβt render dates on the server at all, and show a skeleton/loading state instead. Goodbye, fast First Contentful Paint.
The @epic-web/client-hints library (from Kent Dodds and the Epic Web team) helps solve this problem.
How does it work?
The library uses the Client Hints through Cookies pattern:
- First visit: Before hydration, a tiny script runs on the client. It detects the userβs time zone through
Intl.DateTimeFormat().resolvedOptions().timeZone, writes it to a Cookie and reloads the page (this happens only once, on the very first visit). - All subsequent requests: The server reads the cookie in a
loader(for example, in React Router / Remix / Next) and immediately returns HTML with a date perfectly formatted for the userβs locale and time zone.
What are the benefits?
- Formatting in the loader: You can format dates directly on the backend in a
loaderand send ready-made strings to the client. Less client-side JS, better performance. - No hydration errors: Server and client HTML match perfectly.
- Not just time zones: With
getHintUtils, you can similarly pass color theme preferences (prefers-color-scheme), accessibility settings (prefers-reduced-motion) and screen dimensions to the server.
How do you handle local dates with SSR? Are you willing to accept a one-time reload on the first visit for perfect HTML, or are you still fixing dates on the client through hydration? π