diff --git a/apps/studio/components/layouts/AppLayout/NoticeBanner.tsx b/apps/studio/components/layouts/AppLayout/NoticeBanner.tsx
index ccd6fee5974..d4c42b213e4 100644
--- a/apps/studio/components/layouts/AppLayout/NoticeBanner.tsx
+++ b/apps/studio/components/layouts/AppLayout/NoticeBanner.tsx
@@ -1,43 +1,62 @@
-import { LOCAL_STORAGE_KEYS } from 'common'
+import { LOCAL_STORAGE_KEYS, useParams } from 'common'
+import dayjs from 'dayjs'
import { useRouter } from 'next/router'
-import {
- Button,
- cn,
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogSection,
- DialogSectionSeparator,
- DialogTitle,
- DialogTrigger,
-} from 'ui'
+import { TimestampInfo } from 'ui-patterns'
import { HeaderBanner } from '@/components/interfaces/Organization/HeaderBanner'
-import { InlineLink, InlineLinkClassName } from '@/components/ui/InlineLink'
import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
+import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
// Update this whenever the banner content below changes so old client bundles
// stop displaying outdated notices after the relevant date passes.
-const BANNER_EXPIRES_AT = new Date('2026-07-04T00:00:00Z')
+const BANNER_EXPIRES_AT = new Date('2026-06-01T15:00:00Z')
+
+const SUPAVISOR_UPDATE_REGIONS = {
+ 'eu-central-1': {
+ start: Date.UTC(2026, 4, 26, 13, 0, 0),
+ end: Date.UTC(2026, 4, 26, 15, 0, 0),
+ url: 'https://status.supabase.com/incidents/jy1tm4wfs68t',
+ },
+ 'eu-west-1': {
+ start: Date.UTC(2026, 4, 27, 13, 0, 0),
+ end: Date.UTC(2026, 4, 27, 15, 0, 0),
+ url: 'https://status.supabase.com/incidents/3t293hpd545z',
+ },
+ 'us-west-1': {
+ start: Date.UTC(2026, 4, 28, 13, 0, 0),
+ end: Date.UTC(2026, 4, 28, 15, 0, 0),
+ url: 'https://status.supabase.com/incidents/8f72bnv3xs8r',
+ },
+ 'us-east-1': {
+ start: Date.UTC(2026, 5, 1, 13, 0, 0),
+ end: Date.UTC(2026, 5, 1, 15, 0, 0),
+ url: 'https://status.supabase.com/incidents/7zgmgh2p343n',
+ },
+}
/**
* Used to display urgent notices that apply for all users, such as maintenance windows.
*/
export const NoticeBanner = () => {
const router = useRouter()
+ const { ref } = useParams()
+ const { data: project } = useSelectedProjectQuery()
const [bannerAcknowledged, setBannerAcknowledged, { isSuccess }] = useLocalStorageQuery(
- LOCAL_STORAGE_KEYS.TERMS_OF_SERVICE_UPDATE,
+ LOCAL_STORAGE_KEYS.SUPAVISOR_MAINTENANCE(ref ?? ''),
false
)
+ const region = project?.region ?? ''
+ const maintenanceWindow =
+ SUPAVISOR_UPDATE_REGIONS[region as keyof typeof SUPAVISOR_UPDATE_REGIONS]
+
if (
Date.now() >= BANNER_EXPIRES_AT.getTime() ||
router.pathname.includes('sign-in') ||
!isSuccess ||
+ !project ||
+ !maintenanceWindow ||
bannerAcknowledged
) {
return null
@@ -46,65 +65,23 @@ export const NoticeBanner = () => {
return (
setBannerAcknowledged(true)} />}
+ title="Upcoming maintenance"
+ description={
+ <>
+ Shared pooler maintenance in{' '}
+
+ {project.region}
+ {' '}
+ on{' '}
+
+ .
+ >
+ }
onDismiss={() => setBannerAcknowledged(true)}
/>
)
}
-
-const UpdatedTermsOfServiceDialog = ({ onDismiss }: { onDismiss: () => void }) => {
- return (
-
- )
-}
diff --git a/apps/studio/components/ui/BannerStack/BannerStackProvider.tsx b/apps/studio/components/ui/BannerStack/BannerStackProvider.tsx
index 2a9d5526b63..eef631513f0 100644
--- a/apps/studio/components/ui/BannerStack/BannerStackProvider.tsx
+++ b/apps/studio/components/ui/BannerStack/BannerStackProvider.tsx
@@ -7,6 +7,7 @@ export const BANNER_ID = {
RLS_EVENT_TRIGGER: 'rls-event-trigger-banner',
RLS_TESTER: 'rls-tester-banner',
FREE_MICRO_UPGRADE: 'free-micro-upgrade-banner',
+ TOS_UPDATE: 'tos-update-banner',
} as const
export type BannerId = (typeof BANNER_ID)[keyof typeof BANNER_ID]
diff --git a/apps/studio/components/ui/BannerStack/Banners/BannerTOSUpdate.tsx b/apps/studio/components/ui/BannerStack/Banners/BannerTOSUpdate.tsx
new file mode 100644
index 00000000000..582b07a8a14
--- /dev/null
+++ b/apps/studio/components/ui/BannerStack/Banners/BannerTOSUpdate.tsx
@@ -0,0 +1,123 @@
+import { LOCAL_STORAGE_KEYS } from 'common'
+import {
+ Badge,
+ Button,
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogSection,
+ DialogSectionSeparator,
+ DialogTitle,
+ DialogTrigger,
+} from 'ui'
+
+import { InlineLink } from '../../InlineLink'
+import { BannerCard } from '../BannerCard'
+import { useBannerStack } from '../BannerStackProvider'
+import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
+
+/**
+ * [Joshen] TOS update takes place from 6th June onwards, can remove from 4th July onwards as
+ * previously stated in the NoticeBanner
+ */
+
+export const BannerTOSUpdate = () => {
+ const { dismissBanner } = useBannerStack()
+ const [, setTOSUpdateAcknowledged] = useLocalStorageQuery(
+ LOCAL_STORAGE_KEYS.TERMS_OF_SERVICE_UPDATE,
+ false
+ )
+
+ return (
+ {
+ setTOSUpdateAcknowledged(true)
+ dismissBanner('tos-update-banner')
+ }}
+ >
+
+
+ Notice
+
+
+
+
We've updated our Terms of Service
+
+ Updates define the responsibilities of both you and Supabase in the use of AI.
+
+
+
+
+
+ )
+}
+
+const UpdatedTermsOfServiceDialog = () => {
+ const [, setTOSUpdateAcknowledged] = useLocalStorageQuery(
+ LOCAL_STORAGE_KEYS.TERMS_OF_SERVICE_UPDATE,
+ false
+ )
+
+ return (
+
+ )
+}
diff --git a/packages/common/constants/local-storage.ts b/packages/common/constants/local-storage.ts
index 0ba915243d4..2701f03f994 100644
--- a/packages/common/constants/local-storage.ts
+++ b/packages/common/constants/local-storage.ts
@@ -5,14 +5,12 @@ export const LOCAL_STORAGE_KEYS = {
AI_ASSISTANT_STATE: (projectRef: string | undefined) =>
`supabase-ai-assistant-state-${projectRef}`,
SIDEBAR_BEHAVIOR: 'supabase-sidebar-behavior',
- EDITOR_PANEL_STATE: 'supabase-editor-panel-state',
PROJECTS_VIEW: 'projects-view',
PROJECTS_FILTER: 'projects-filter',
PROJECTS_SORT: 'projects-sort',
FEEDBACK_WIDGET_CONTENT: 'feedback-widget-content',
FEEDBACK_WIDGET_SCREENSHOT: 'feedback-widget-screenshot',
INCIDENT_BANNER_DISMISSED_IDS: 'incident-banner-dismissed-ids',
- MAINTENANCE_BANNER_DISMISSED: (id: string) => `maintenance-banner-dismissed-${id}`,
DASHBOARD_PREFERENCES: (ref: string) => `dashboard-preferences-${ref}`,
UNIFIED_LOGS_DOCK: 'unified-logs-dock',
@@ -20,7 +18,6 @@ export const LOCAL_STORAGE_KEYS = {
UI_PREVIEW_CLS: 'supabase-ui-cls',
UI_PREVIEW_INLINE_EDITOR: 'supabase-ui-preview-inline-editor',
UI_PREVIEW_UNIFIED_LOGS: 'supabase-ui-preview-unified-logs',
- UI_ONBOARDING_NEW_PAGE_SHOWN: 'supabase-ui-onboarding-new-page-shown',
UI_PREVIEW_ADVISOR_RULES: 'supabase-ui-advisor-rules',
UI_PREVIEW_QUEUE_OPERATIONS: 'supabase-ui-queue-operations',
UI_PREVIEW_PG_DELTA_DIFF: 'supabase-ui-pg-delta-diff',
@@ -29,8 +26,6 @@ export const LOCAL_STORAGE_KEYS = {
UI_PREVIEW_RLS_TESTER: 'supabase-ui-rls-tester',
UI_PREVIEW_MARKETPLACE: 'supabase-ui-marketplace',
- NEW_LAYOUT_NOTICE_ACKNOWLEDGED: 'new-layout-notice-acknowledge',
- TABS_INTERFACE_ACKNOWLEDGED: 'tabs-interface-acknowledge',
AI_ASSISTANT_MCP_OPT_IN: 'ai-assistant-mcp-opt-in',
DASHBOARD_HISTORY: (ref: string) => `dashboard-history-${ref}`,
@@ -53,7 +48,6 @@ export const LOCAL_STORAGE_KEYS = {
SQL_EDITOR_SORT: (ref: string) => `sql-editor-sort-${ref}`,
LOG_EXPLORER_SPLIT_SIZE: 'supabase_log-explorer-split-size',
- GRAPHIQL_RLS_BYPASS_WARNING: 'graphiql-rls-bypass-warning-dismissed',
GRAPHQL_INTROSPECTION_NOTICE_COLLAPSED: (ref: string) =>
`graphql-introspection-notice-collapsed-${ref}`,
CLS_DIFF_WARNING: 'cls-diff-warning-dismissed',
@@ -78,6 +72,7 @@ export const LOCAL_STORAGE_KEYS = {
FLY_DEPRECATION_2026_05_31: 'fly-deprecation-2026-05-31-dismissed',
API_KEYS_FEEDBACK_DISMISSED: (ref: string) => `supabase-api-keys-feedback-dismissed-${ref}`,
TERMS_OF_SERVICE_UPDATE: 'terms-of-service-update-2026-06-06',
+ SUPAVISOR_MAINTENANCE: (ref: string) => `supavisor-maintenance-2026-05-21-${ref}`,
REPORT_DATERANGE: 'supabase-report-daterange',
PROJECT_PAUSING_STARTED_AT: (ref: string) => `supabase-project-pausing-started-at-${ref}`,
PROJECT_RESTORING_STARTED_AT: (ref: string) => `supabase-project-restoring-started-at-${ref}`,
@@ -119,7 +114,6 @@ export const LOCAL_STORAGE_KEYS = {
`free-micro-upgrade-banner-dismissed-${ref}`,
STORAGE_PUBLIC_BUCKET_SELECT_POLICY_WARNING_DISMISSED: (ref: string, bucketId: string) =>
`storage-public-bucket-select-policy-warning-dismissed-${ref}-${bucketId}`,
- PRIVACY_NOTICE_ACKNOWLEDGED: 'privacy-notice-acknowledged-2026-03',
/**
* COMMON