🐛 Bug: docs.copilotkit.ai: the announcement banner renders only after hydration, so the header and content jump down 40px on every load · Issue #7825 · CopilotKit/CopilotKit · GitHub
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
🐛 Bug: docs.copilotkit.ai: the announcement banner renders only after hydration, so the header and content jump down 40px on every load #7825
Open https://docs.copilotkit.ai/quickstart in a fresh browser profile (banner not dismissed), at any width. It's most visible below 1280px, where the fixed MobileTopNav is shown.
Watch the first seconds of the load. DevTools network throttling makes it easier to see.
Measured with headless Chromium on the live site, iPhone 13 viewport (positions in CSS px):
Unthrottled (3 runs): first paint at ~0.1 s with no banner, MobileTopNav at y = 8, page title at y = 136. At 2.2–3.5 s the banner appears, MobileTopNav moves to y = 40 and the title to y = 176.
The first paint already has the final layout: the banner (or the space for it), with the header and content where they end up. A reader who dismissed the banner doesn't see it flash in.
❌ Actual Behavior
src/components/banners.tsx returns null until a useEffect has run (if (!hydrated || dismissed) return null), because it reads the dismissed state from localStorage. The same effect is what sets --fd-banner-height on (40px or 0px). So:
Before hydration, there's no banner and --fd-banner-height is unset. MobileTopNav's top-(--fd-banner-height) has no fallback, so the fixed nav falls back to its static position (y = 8 below md, 12 at md).
After hydration, the banner renders, the variable becomes 40px, and the header and everything below it move down by about 32–40px.
The jump happens on every page load for readers who haven't dismissed the banner. For readers who have, the variable goes from unset to 0px, which also moves the fixed nav by 8–12px.
Chrome's Layout Instability API reports no layout-shift entries for this jump (CLS 0 in the same runs, layout-shift supported), so Lighthouse and Web Vitals won't flag it. The positions above come from getBoundingClientRect sampling.
Possible fix:
Render the banner on the server, so it's in the first paint.
Decide dismissal before paint with a small inline script in that reads the localStorage flags and sets --fd-banner-height (or a class on that hides the banner). That's the same approach next-themes uses to avoid a theme flash.
Give top-(--fd-banner-height) a fallback, e.g. top-[var(--fd-banner-height,0px)].
I'm happy to open a PR.
Screenshots
𝌚 CopilotKit Version
docs.copilotkit.ai (showcase/shell-docs @ main 500b40efb): next 16.2.6, fumadocs-core/ui 16.8.12, react 19.2
This is a docs-site layout issue, not a CopilotKit SDK bug — nothing in the retrieved sources covers banners.tsx, --fd-banner-height, or the MobileTopNav positioning logic you've described, so I don't have enough to comment on the internals or validate the fix paths.
Your analysis is thorough and the PR offer is the right next step — engineering will need to verify and pick the approach. I'm escalating this to the team.
🤖 Generated by CopilotKit AI Support · Documentation
Hi! I'd like to work on this if it's still available.
@Laptopmini, I saw you offered to open a PR. If you're already working on it, I'll step back.
Otherwise, my plan:
Add a small inline script in <head> that reads the dismissal flags from localStorage and sets --fd-banner-height before the first paint (the same trick next-themes uses to avoid a theme flash).
Render the banner on the server so it's part of the first paint, and hide it with CSS when it was dismissed.
Add a 0px fallback to MobileTopNav's top-(--fd-banner-height).
Activity
copilotkit-outpost-bot commentedon Oct 14, 2026
This is a docs-site layout issue, not a CopilotKit SDK bug — nothing in the retrieved sources covers
banners.tsx,--fd-banner-height, or theMobileTopNavpositioning logic you've described, so I don't have enough to comment on the internals or validate the fix paths.Your analysis is thorough and the PR offer is the right next step — engineering will need to verify and pick the approach. I'm escalating this to the team.
🤖 Generated by CopilotKit AI Support · Documentation
Was this helpful? React with 👍 or 👎
choudhary-lokeshh commentedon Oct 21, 2026
Hi! I'd like to work on this if it's still available.
@Laptopmini, I saw you offered to open a PR. If you're already working on it, I'll step back.
Otherwise, my plan:
<head>that reads the dismissal flags from localStorage and sets--fd-banner-heightbefore the first paint (the same trick next-themes uses to avoid a theme flash).0pxfallback toMobileTopNav'stop-(--fd-banner-height).Does this approach sound good to the maintainers?