Marked as helpful by the asker
You found it. Anything that differs between server and browser at render time (dates, Math.random, window) causes this. The year usually matches, but a timezone edge or a cached HTML from last year does not.
Either render it on the client only:
const [year, setYear] = useState<number>();
useEffect(() => setYear(new Date().getFullYear()), []);or hardcode the year in a constant you bump once a year. For a footer I'd hardcode it.