/** * Domain rules for the dashboard. * * Small, but it is the right home for them: a greeting derived from a clock is * a rule about time of day, not a rendering concern, and having it in the page * meant the one non-obvious thing about it (which clock) lived next to JSX. */ /** * The header greeting, derived from the SERVER's clock. * * Never Date.now(): calling it during render is impure, disagrees between the * SSR and hydration passes, and reports the wrong time of day to anyone whose * device clock is off. The instant arrives on every response's `meta`, and * getHours() resolves it in the viewer's own zone — the hour the merchant is * actually living in. * * Before the first response there is no instant to reason about, so the * greeting is the time-independent one. Both strings are a single line, so the * swap costs no layout shift. */ export function greetingFor(generatedAt?: string): string { if (!generatedAt) return 'Welcome back'; const hour = new Date(generatedAt).getHours(); if (hour < 12) return 'Good morning'; if (hour < 17) return 'Good afternoon'; return 'Good evening'; }