feat(console): add a top banner for the new Console - #3192
Conversation
Uses GradientBanner, the same component newDevUpgradePro uses, registered through headerAlert at importance 1 so it sits in the promo tier and can never outrank a payment or usage warning. Dismissal is keyed on the alert id in localStorage, matching newDevUpgradePro. Also makes GradientBanner stack-aware. It is position:fixed and offsets the shell itself, but AlertStack is fixed too and measures its children to do the same job. Inside a stack the banner measured as 0, so the stack reset the header offset the banner had just set and the banner covered the navigation until the next resize. It now stands down when a stack is in charge, mirroring headerAlert.svelte. This also fixes the same first-paint overlap for newDevUpgradePro and enterpriseTrial. The CTA carries utm_medium=banner so this surface can be compared against the promo card.
Console (appwrite/console)Project ID: Tip Schedule functions to run as often as every minute with cron expressions |
Greptile SummaryThis PR adds a dismissible cloud-only banner promoting the new Appwrite Console and adjusts GradientBanner positioning when rendered inside the shared alert stack.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains. No blocking failure remains. Important Files Changed
Reviews (2): Last reviewed commit: "fix(console): release the header alert s..." | Re-trigger Greptile |
| import { UsageRates } from '$lib/components/billing'; | ||
| import { canSeeProjects } from '$lib/stores/roles'; | ||
| import { BottomModalAlert } from '$lib/components'; | ||
| import NewConsoleBanner from '$lib/components/newConsoleBanner.svelte'; |
There was a problem hiding this comment.
Component imports bypass barrels
The new direct imports of newConsoleBanner.svelte here and billing/gradientBanner.svelte in the banner bypass the repository's required component barrel exports, weakening the centralized component API and making future relocation and export auditing harder.
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/routes/(console)/+layout.svelte
Line: 48
Comment:
**Component imports bypass barrels**
The new direct imports of `newConsoleBanner.svelte` here and `billing/gradientBanner.svelte` in the banner bypass the repository's required component barrel exports, weakening the centralized component API and making future relocation and export auditing harder.
**Context Used:** AGENTS.md ([source](https://github.com/appwrite/console/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
handleClose only hid the local component, leaving the store entry visible. headerAlert.get() compares importance and breaks ties by registration order, so the dismissed entry kept winning the importance-1 tie and rendered an empty slot, hiding newDevUpgradePro and the backup policy alert until a reload. Now calls headerAlert.updateShow(id, false) so activeHeaderAlert recomputes and the next eligible promo can take the slot. Verified: after dismissal the AlertStack unmounts and the header offset returns to 0 rather than leaving an empty banner mounted. Also routes NewConsoleBanner through the components barrel, per AGENTS.md.

Adds a top banner inviting users to the new Console, alongside the promo card from #3191.
Approach
Uses
GradientBanner— the same componentnewDevUpgradeProuses for the Cloud credits promo. Registered throughheaderAlertat importance 1, the promo tier, so it sits level withnewDevUpgradeProand the backup-policy warning and can never outrank a payment or usage alert. Dismissal is keyed on the alert id inlocalStorage, matchingnewDevUpgradePro.src/lib/components/newConsoleBanner.sveltesrc/routes/(console)/+layout.sveltesrc/lib/components/billing/gradientBanner.svelteAlso fixes a pre-existing layering bug
GradientBannerisposition: fixedand offsets the shell itself insetNavigationHeight. But it renders insideAlertStack, which is also fixed and measures its children to do the same job. Because the banner was out of flow, the stack measured 0px and itsResizeObserverfired last, resettingheader.style.top = 0— so the banner covered the navigation until the next resize.Measured on first paint, before and after:
positionfixedrelativeheader.topThe fix mirrors
headerAlert.svelte— readgetContext('isInAlertStack')and stand down when the stack is in charge. This also fixes the same first-paint overlap fornewDevUpgradeProandenterpriseTrial, which both go through the same path.Copy
CTA carries
utm_medium=banner, so this surface can be compared against the card'sutm_medium=promo_cardin the sources pipeline.Worth noting
With #3191 merged, the banner and the promo card both run and say the same thing on the same page. That's a deliberate call, not an oversight — flagging it so it's a decision rather than a surprise.
Test plan
bun run format— cleanbun run lint— 0 errorsbun run check— no errors in changed files