diff --git a/website/src/pages/webinars.module.css b/website/src/pages/webinars.module.css index 299d69c39..70ac4545c 100644 --- a/website/src/pages/webinars.module.css +++ b/website/src/pages/webinars.module.css @@ -70,10 +70,14 @@ justify-content: space-between; flex-wrap: wrap; gap: 0.6rem; - background: var(--ifm-color-primary); - color: #fff; + background: rgba(159, 98, 235, 0.1); + background: color-mix(in srgb, var(--event-accent) 10%, var(--ifm-background-surface-color) 90%); + color: var(--ifm-font-color-base); + border: 1px solid rgba(159, 98, 235, 0.22); + border: 1px solid color-mix(in srgb, var(--event-accent) 22%, var(--ifm-color-emphasis-200) 78%); + border-left: 4px solid var(--event-accent); border-radius: 6px; - padding: 0.55rem 1rem; + padding: 0.75rem 1rem; margin-bottom: 0.75rem; font-size: 0.82rem; } @@ -88,12 +92,14 @@ text-transform: uppercase; letter-spacing: 0.6px; font-size: 0.68rem; - background: rgba(255, 255, 255, 0.18); - padding: 0.12rem 0.4rem; + background: rgba(159, 98, 235, 0.14); + background: color-mix(in srgb, var(--event-accent) 14%, transparent); + color: var(--event-accent); + padding: 0.18rem 0.48rem; border-radius: 3px; } .callStripSchedule { - opacity: 0.92; + color: var(--ifm-color-emphasis-800); font-size: 0.8rem; } .callStripActions { @@ -104,41 +110,38 @@ } .calendarLink { font-size: 0.78rem; - color: rgba(255, 255, 255, 0.9); + color: var(--ifm-color-emphasis-800); text-decoration: underline; text-underline-offset: 2px; } .calendarLink:hover { - color: #fff; + color: var(--event-accent); +} +.linkDivider { + color: var(--ifm-color-emphasis-500); + font-size: 0.78rem; } -/* Prominent Join Now button */ .joinBtn { - background: #fff !important; - color: var(--ifm-color-primary) !important; - border: none !important; + background: var(--event-accent) !important; + color: #fff !important; + border: 1px solid var(--event-accent) !important; font-weight: 700 !important; - font-size: 0.85rem !important; - padding: 0.45rem 1.4rem !important; + font-size: 0.8rem !important; + padding: 0.4rem 1.1rem !important; border-radius: 4px; - box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.5); - animation: joinPulse 2s ease-in-out infinite; - transition: transform 0.15s ease, box-shadow 0.15s ease; -} -.joinBtn:hover { - transform: scale(1.06); - box-shadow: 0 2px 12px rgba(255, 255, 255, 0.35); + box-shadow: none; animation: none; - color: var(--ifm-color-primary-darker) !important; + transition: background-color 0.15s ease, border-color 0.15s ease; } -@keyframes joinPulse { - 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.45); } - 50% { box-shadow: 0 0 0 6px rgba(255, 255, 255, 0); } +.joinBtn:hover { + background: color-mix(in srgb, var(--event-accent) 88%, black 12%) !important; + border-color: color-mix(in srgb, var(--event-accent) 88%, black 12%) !important; + color: #fff !important; } @media (prefers-reduced-motion: reduce) { .joinBtn { - animation: none; transition: none; } } @@ -151,19 +154,18 @@ /* ── Agenda section ──────────────────────────────────────────────────────── */ .agendaSection { - max-width: 960px; - margin: 1.5rem auto 2.5rem; - padding: 0 1.5rem; + margin: 0; + padding: 0; } .sectionHeader { display: flex; align-items: baseline; gap: 0.5rem; - margin-bottom: 0.75rem; + margin-bottom: 0.5rem; } .sectionHeader h2 { font-family: var(--ifm-heading-font-family); - font-size: 1.15rem; + font-size: 0.95rem; font-weight: 700; color: var(--ifm-color-primary); margin: 0; @@ -174,81 +176,121 @@ color: var(--ifm-color-emphasis-600); } .emptyState { - font-size: 0.85rem; + font-size: 0.82rem; color: var(--ifm-color-emphasis-600); - padding: 1rem 0; + padding: 0.5rem 0; } -/* Card grid */ -.agendaGrid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - gap: 0.75rem; -} -.agendaCard { - background: var(--ifm-background-surface-color); - border: 1px solid var(--ifm-color-emphasis-200); - border-radius: 6px; - padding: 0.75rem 1rem; - transition: box-shadow 0.15s ease, border-color 0.15s ease; +/* Compact bullet-point agenda list */ +.agendaList { + list-style: none; + margin: 0; + padding: 0; + font-size: 0.82rem; + line-height: 1.5; } -.agendaCard:hover { - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); - border-color: var(--ifm-color-emphasis-300); +.agendaListItem { + padding: 0.3rem 0; + border-bottom: 1px solid var(--ifm-color-emphasis-100); } -.agendaCard.featured { - border-left: 3px solid var(--ifm-color-primary); +.agendaListItem:last-child { + border-bottom: none; } -.agendaCardTitle { - font-size: 0.88rem; +.agendaItemTitle { font-weight: 600; - margin: 0 0 0.25rem; + color: var(--ifm-font-color-base); +} +.agendaItemTitle.featured { color: var(--ifm-color-primary); - line-height: 1.3; } -.agendaPresenter { - font-size: 0.76rem; - color: var(--ifm-color-emphasis-700); - margin: 0 0 0.2rem; +.agendaItemMeta { + font-size: 0.74rem; + color: var(--ifm-color-emphasis-600); font-style: italic; } -.agendaDescription { - font-size: 0.76rem; - color: var(--ifm-color-emphasis-600); - margin: 0 0 0.3rem; - line-height: 1.35; +.agendaItemDescription { + display: block; } -.agendaBullets { - margin: 0.2rem 0 0 1rem; - padding: 0; +.agendaBulletList { + margin: 0.35rem 0 0; + padding-left: 1.1rem; font-size: 0.76rem; - line-height: 1.4; -} -.agendaBullets li { - margin-bottom: 0.15rem; + color: var(--ifm-color-emphasis-700); } - -@media screen and (max-width: 640px) { - .agendaGrid { grid-template-columns: 1fr; } - .agendaSection { margin: 1rem auto 2rem; padding: 0 1rem; } +.agendaBulletItem { + margin: 0.18rem 0; } /* ── Dark-mode tweaks ────────────────────────────────────────────────────── */ -[data-theme="dark"] .agendaCard { - background: var(--ifm-background-surface-color); +[data-theme="dark"] .eventBlock { border-color: var(--ifm-color-emphasis-400); } -[data-theme="dark"] .agendaCard:hover { - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5); -} -[data-theme="dark"] .agendaPresenter { - color: var(--ifm-color-emphasis-600); +[data-theme="dark"] .agendaListItem { + border-bottom-color: var(--ifm-color-emphasis-300); } -[data-theme="dark"] .agendaDescription { +[data-theme="dark"] .agendaItemMeta { color: var(--ifm-color-emphasis-500); } +[data-theme="dark"] .agendaBulletList { + color: var(--ifm-color-emphasis-300); +} [data-theme="dark"] .callStrip { - background: var(--ifm-color-primary-dark); + background: rgba(159, 98, 235, 0.2); + background: color-mix(in srgb, var(--event-accent) 20%, var(--ifm-background-surface-color) 80%); + border-color: rgba(159, 98, 235, 0.35); + border-color: color-mix(in srgb, var(--event-accent) 35%, var(--ifm-color-emphasis-400) 65%); +} +[data-theme="dark"] .callStripSchedule, +[data-theme="dark"] .calendarLink { + color: var(--ifm-color-emphasis-100); +} + +/* ── Events container (side-by-side on desktop) ─────────────────────────── */ +.eventsContainer { + max-width: 1100px; + margin: 0 auto; + padding: 1.5rem 1.5rem 2.5rem; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; +} +.eventBlock { + --event-accent: var(--ifm-color-primary); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + padding: 1.25rem; + background: var(--ifm-background-surface-color); +} +.communityBlock { + --event-accent: #2f6fed; + background: + linear-gradient(180deg, rgba(47, 111, 237, 0.08), transparent 110px), + var(--ifm-background-surface-color); +} +.reviewBlock { + --event-accent: #b96a16; + background: + linear-gradient(180deg, rgba(185, 106, 22, 0.09), transparent 110px), + var(--ifm-background-surface-color); +} +.eventBlockTitle { + font-size: 1.1rem; + font-weight: 700; + color: var(--event-accent); + margin: 0 0 0.35rem; +} +.eventBlockSummary { + margin: 0 0 0.9rem; + font-size: 0.84rem; + line-height: 1.5; + color: var(--ifm-color-emphasis-700); +} +.eventBlock .sectionHeader h2 { + color: var(--event-accent); +} + +@media screen and (max-width: 768px) { + .eventsContainer { grid-template-columns: 1fr; padding: 1rem; gap: 1.5rem; } } /* ── Utility ─────────────────────────────────────────────────────────────── */ diff --git a/website/src/pages/webinars.tsx b/website/src/pages/webinars.tsx index 1406d8d7b..2d5646681 100644 --- a/website/src/pages/webinars.tsx +++ b/website/src/pages/webinars.tsx @@ -1,16 +1,18 @@ // Maintenance overview: // Agenda content and its month label are sourced exclusively from markdown files: -// /website/static/webinars/agenda/YYYY-MM.md -// Frontmatter must include: month: Month YYYY +// Community Calls: /website/static/webinars/agenda/YYYY-MM.md (monthly files) +// Architecture Review Hour: /website/static/webinars/agenda/kube-and-tell.md (single file, updated in-place) +// Frontmatter must include: month: Month YYYY (or a label for the session) // Each agenda section uses a second-level heading (##) followed by optional lines: // Presenter: Name and title // Description: Text // Featured: true // - bullet point text (repeatable for bullets) -// If the current month file is missing, the code steps backwards (up to a -// configurable number of prior months) and uses the most recent available file. -// This ensures an agenda is always displayed, even before a new month's file is added. -// Timezone call card data is defined in the constant `timezoneCalls` below. +// Community Calls: If the current month file is missing, the code steps backwards +// (up to 6 prior months) and uses the most recent available file. +// Architecture Review Hour: Uses a single static file that is updated whenever +// a new session is scheduled. +// Event data is defined in the constant `eventTypes` below. import type { ReactNode } from "react"; import React, { useEffect, useState } from "react"; @@ -35,24 +37,126 @@ interface MonthlyAgendaResult { loading: boolean; } -interface TimezoneCall { - region: string; - schedule: string; // contains
+interface EventType { + id: string; + label: string; + description: string; + schedule: string; icsHref: string; joinHref: string; + agendaBasePath: string; + agendaMode: "monthly" | "static"; + getNextDate: () => Date; + pastRecordingsHref?: string; } -// Static timezone call info (edit here if schedules/links change) -const timezoneCalls: TimezoneCall[] = [ +// --- Event Definitions ----------------------------------------------------- + +const eventTypes: EventType[] = [ { - region: "Americas, Europe", + id: "community-calls", + label: "Community Calls", + description: + "Roadmap updates, product demos, and open Q&A with the AKS team.", schedule: - "Every 3rd Wednesday. 8 AM Pacific Time / 11 AM Eastern Time / 3 PM GMT / 8:30 PM IST", + "8 AM Pacific / 11 AM Eastern / 4 PM GMT / 8:30 PM IST", icsHref: "/webinars/calendar/AKS-Community-Roadmap-Call-US.ics", joinHref: "https://aka.ms/aks/communitycalls-us/roadmap/joinnow", + agendaBasePath: "/webinars/agenda", + agendaMode: "monthly", + getNextDate: getNextThirdWednesday, + pastRecordingsHref: "https://www.youtube.com/playlist?list=PLc3Ep462vVYu0eMSiORonzj3utqYu285z", + }, + { + id: "kube&tell-podcast", + label: "Kube & Tell", + description: + "Live, community-driven podcast for Kubernetes practitioners", + schedule: + "8 AM Pacific / 11 AM Eastern / 4 PM GMT / 8:30 PM IST", + icsHref: "/webinars/calendar/Kube & Tell _ Real Clusters, Real Conversations.ics", + joinHref: "https://aka.ms/aks/kubeandtell/joinnow", + agendaBasePath: "/webinars/agenda/kube-and-tell.md", + agendaMode: "static", + getNextDate: getNextKubeAndTellDate, }, ]; +// --- Date Helpers ---------------------------------------------------------- + +// Returns the upcoming 3rd Wednesday (or today if today is the 3rd Wednesday). +function getNextThirdWednesday(): Date { + const PST_OFFSET_MS = 8 * 60 * 60 * 1000; + const nowUTC = Date.now(); + const nowPST = new Date(nowUTC - PST_OFFSET_MS); + + const year = nowPST.getUTCFullYear(); + const month = nowPST.getUTCMonth(); + const today = nowPST.getUTCDate(); + + const thirdWed = (y: number, m: number): Date => { + const first = new Date(Date.UTC(y, m, 1)); + const offset = (3 - first.getUTCDay() + 7) % 7; + return new Date(Date.UTC(y, m, 1 + offset + 14)); + }; + + const candidate = thirdWed(year, month); + if (candidate.getUTCDate() >= today && candidate.getUTCMonth() === month) { + return new Date(candidate.getUTCFullYear(), candidate.getUTCMonth(), candidate.getUTCDate()); + } + const nextMonth = month + 1; + const result = thirdWed( + nextMonth > 11 ? year + 1 : year, + nextMonth % 12, + ); + return new Date(result.getUTCFullYear(), result.getUTCMonth(), result.getUTCDate()); +} + +// Returns the next Architecture Review Hour date. +// Known upcoming dates: June 11, 2026. After that, assume 2nd Thursday monthly. +function getNextKubeAndTellDate(): Date { + const PST_OFFSET_MS = 8 * 60 * 60 * 1000; + const nowUTC = Date.now(); + const nowPST = new Date(nowUTC - PST_OFFSET_MS); + const todayMs = Date.UTC(nowPST.getUTCFullYear(), nowPST.getUTCMonth(), nowPST.getUTCDate()); + + // Known fixed date + const knownMs = Date.UTC(2026, 5, 11); // June 11, 2026 + if (knownMs >= todayMs) { + return new Date(2026, 5, 11); + } + + // Fallback: 2nd Thursday of each month + const year = nowPST.getUTCFullYear(); + const month = nowPST.getUTCMonth(); + const today = nowPST.getUTCDate(); + + const secondThursday = (y: number, m: number): Date => { + const first = new Date(Date.UTC(y, m, 1)); + const offset = (4 - first.getUTCDay() + 7) % 7; + return new Date(Date.UTC(y, m, 1 + offset + 7)); + }; + + const candidate = secondThursday(year, month); + if (candidate.getUTCDate() >= today && candidate.getUTCMonth() === month) { + return new Date(candidate.getUTCFullYear(), candidate.getUTCMonth(), candidate.getUTCDate()); + } + const nextMonth = month + 1; + const result = secondThursday( + nextMonth > 11 ? year + 1 : year, + nextMonth % 12, + ); + return new Date(result.getUTCFullYear(), result.getUTCMonth(), result.getUTCDate()); +} + +function formatDate(d: Date): string { + const months = [ + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December", + ]; + return `${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`; +} + // --- Markdown Parsing Logic ----------------------------------------------- function parseAgendaMarkdown(raw: string): { @@ -117,13 +221,17 @@ function parseAgendaMarkdown(raw: string): { } // Hook to load agenda markdown for current month, falling back to latest prior month. -function useMonthlyAgenda(): MonthlyAgendaResult { +function useMonthlyAgenda(basePath: string): MonthlyAgendaResult { const [state, setState] = useState({ items: [], loading: true, }); useEffect(() => { + if (!basePath) { + setState({ items: [], loading: false }); + return; + } if (!ExecutionEnvironment.canUseDOM) { setState({ items: [], loading: false }); return; @@ -137,7 +245,7 @@ function useMonthlyAgenda(): MonthlyAgendaResult { const tryFetch = () => { const monthStr = `${year}-${String(monthIndex + 1).padStart(2, "0")}`; - const url = `/webinars/agenda/${monthStr}.md`; + const url = `${basePath}/${monthStr}.md`; fetch(url, { cache: "no-cache" }) .then(async (res) => { if (!res.ok) @@ -172,7 +280,42 @@ function useMonthlyAgenda(): MonthlyAgendaResult { return () => { cancelled = true; }; - }, []); + }, [basePath]); + return state; +} + +// Hook to load a single static agenda markdown file. +function useStaticAgenda(filePath: string): MonthlyAgendaResult { + const [state, setState] = useState({ + items: [], + loading: true, + }); + + useEffect(() => { + if (!filePath) { + setState({ items: [], loading: false }); + return; + } + if (!ExecutionEnvironment.canUseDOM) { + setState({ items: [], loading: false }); + return; + } + let cancelled = false; + fetch(filePath, { cache: "no-cache" }) + .then(async (res) => { + if (!res.ok) throw new Error(`Agenda not found (${res.status})`); + return res.text(); + }) + .then((text) => { + if (cancelled) return; + const parsed = parseAgendaMarkdown(text); + setState({ items: parsed.items, month: parsed.month, loading: false }); + }) + .catch(() => { + if (!cancelled) setState({ items: [], loading: false }); + }); + return () => { cancelled = true; }; + }, [filePath]); return state; } @@ -185,108 +328,58 @@ function Hero(): ReactNode { className={styles.heroOverlay} style={{ backgroundImage: `url(${bannerUrl})` }} role="img" - aria-label="AKS Community Calls Banner" + aria-label="AKS Community Events Banner" >
- AKS Community Calls + AKS Community Events

- Monthly public sessions to connect with the AKS product team, learn roadmap updates, and share feature deep dives. + Monthly public sessions with the AKS Product Team.

-
- - Past Recordings - - - Feature Roadmap - -
); } -// Returns the upcoming 3rd Wednesday (or today if today is the 3rd Wednesday). -function getNextThirdWednesday(): Date { - // Compute everything relative to PST (UTC-8) so the result is - // consistent regardless of the server's or visitor's local timezone. - const PST_OFFSET_MS = 8 * 60 * 60 * 1000; // UTC-8 - const nowUTC = Date.now(); - // Current date/time expressed as if the clock were in PST - const nowPST = new Date(nowUTC - PST_OFFSET_MS); - - const year = nowPST.getUTCFullYear(); - const month = nowPST.getUTCMonth(); - const today = nowPST.getUTCDate(); - - const thirdWed = (y: number, m: number): Date => { - // First day of the month in PST (represented as UTC for arithmetic) - const first = new Date(Date.UTC(y, m, 1)); - // Day-of-week for the 1st (0 = Sun … 6 = Sat); Wednesday = 3 - const offset = (3 - first.getUTCDay() + 7) % 7; // days until first Wednesday - // 3rd Wednesday = first Wednesday + 14 days - return new Date(Date.UTC(y, m, 1 + offset + 14)); - }; - - const candidate = thirdWed(year, month); - // If the 3rd Wednesday this month is still today or in the future (in PST), use it - if (candidate.getUTCDate() >= today && candidate.getUTCMonth() === month) { - // Return as a plain local-midnight Date so formatDate() keeps working - return new Date(candidate.getUTCFullYear(), candidate.getUTCMonth(), candidate.getUTCDate()); - } - // Otherwise, move to next month - const nextMonth = month + 1; - const result = thirdWed( - nextMonth > 11 ? year + 1 : year, - nextMonth % 12, - ); - return new Date(result.getUTCFullYear(), result.getUTCMonth(), result.getUTCDate()); -} - -function formatDate(d: Date): string { - const months = [ - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December", - ]; - return `${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`; -} - -function AgendaSection(): ReactNode { - const { month, items, loading } = useMonthlyAgenda(); +function EventSection({ event }: { event: EventType }): ReactNode { + const monthlyResult = useMonthlyAgenda(event.agendaMode === "monthly" ? event.agendaBasePath : ""); + const staticResult = useStaticAgenda(event.agendaMode === "static" ? event.agendaBasePath : ""); + const { month, items, loading } = event.agendaMode === "monthly" ? monthlyResult : staticResult; const label = month || "Latest"; const empty = !loading && items.length === 0; - const tz = timezoneCalls[0]; - const nextDate = getNextThirdWednesday(); + const nextDate = event.getNextDate(); + return (
- {tz && ( -
-
- Next call - - {formatDate(nextDate)} -
- {tz.schedule} -
-
-
- - Add to calendar - - - Join Now - -
+
+
+ Next session + + {formatDate(nextDate)} + {event.id === "community-calls" && " (Every 3rd Wednesday)"} +
+ {event.schedule} +
- )} +
+ {event.pastRecordingsHref && ( + <> + + Past recordings + + | + + )} + + Add to calendar + + + Join Now + +
+
Agenda - {label} @@ -302,31 +395,32 @@ function AgendaSection(): ReactNode {

)} {!empty && ( -
+
    {items.map((item, idx) => ( -
    -

    {item.title}

    - {item.presenter && ( -

    {item.presenter}

    - )} +
  • + + {item.title} + {item.description && ( -

    {item.description}

    + + {item.description} + + )} + {item.presenter && ( + Presenter: {item.presenter} )} - {item.bullets && ( -
      - {item.bullets.map((b, i) => ( -
    • {b}
    • + {item.bullets && item.bullets.length > 0 && ( +
        + {item.bullets.map((bullet, bulletIdx) => ( +
      • + {bullet} +
      • ))}
      )} -
  • + ))} -
+ )}
); @@ -335,12 +429,23 @@ function AgendaSection(): ReactNode { export default function Webinars(): ReactNode { return ( -
- +
+ {eventTypes.map((evt) => ( +
+
+ {evt.label} +
+

{evt.description}

+ +
+ ))}
); diff --git a/website/static/webinars/agenda/kube-and-tell.md b/website/static/webinars/agenda/kube-and-tell.md new file mode 100644 index 000000000..6c1be849f --- /dev/null +++ b/website/static/webinars/agenda/kube-and-tell.md @@ -0,0 +1,17 @@ +--- +month: June 2026 +--- + +# Agenda + +## Architecture Review Hour +Description: Platform Management at a large enterprise + +## Introduction +Presenter: Paul Yu, Host + +## Architecture Review: Platform management at a large enterprise +Description: Architecture Walkthrough, Review & Discussion. If we were doing it again, how would we do it? + +## Live Q&A +Description: Open discussion with the AKS architecture team diff --git a/website/static/webinars/calendar/Kube & Tell _ Real Clusters, Real Conversations.ics b/website/static/webinars/calendar/Kube & Tell _ Real Clusters, Real Conversations.ics new file mode 100644 index 000000000..efc6cb67a --- /dev/null +++ b/website/static/webinars/calendar/Kube & Tell _ Real Clusters, Real Conversations.ics @@ -0,0 +1,562 @@ +BEGIN:VCALENDAR +PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN +VERSION:2.0 +METHOD:PUBLISH +X-MS-OLK-FORCEINSPECTOROPEN:TRUE +BEGIN:VTIMEZONE +TZID:Eastern Standard Time +BEGIN:STANDARD +DTSTART:16011104T020000 +RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11 +TZOFFSETFROM:-0400 +TZOFFSETTO:-0500 +END:STANDARD +BEGIN:DAYLIGHT +DTSTART:16010311T020000 +RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3 +TZOFFSETFROM:-0500 +TZOFFSETTO:-0400 +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20260518T162825Z +DESCRIPTION:Kube & Tell is a live\, community-driven podcast for Kubernetes + practitioners who'd rather show than tell. Expect hands-on walkthroughs\, + deep technical dives\, and candid conversations spanning AKS\, upstream K + ubernetes\, self-hosted clusters\, and the wider cloud-native ecosystem.\n + Best of all\, we record it live. So as the audience\, you can bring in you + r questions\, your hot takes\, and your war stories. The mic is open.\n \n + Agenda and Join Link: https://aka.ms/aks/communitycalls\n \n +DTEND;TZID="Eastern Standard Time":20260611T120000 +DTSTAMP:20260518T162825Z +DTSTART;TZID="Eastern Standard Time":20260611T110000 +LAST-MODIFIED:20260518T162825Z +LOCATION:https://aka.ms/aks/communitycalls +PRIORITY:5 +RRULE:FREQ=MONTHLY;COUNT=13;BYDAY=TH;BYSETPOS=2 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-us:Kube & Tell : Real Clusters\, Real Conversations +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000107F8A2EC0E6DC01000000000000000 + 01000000016703DFC97238347814A90DC64C95A0D +X-ALT-DESC;FMTTYPE=text/html:

Kube &\; Tell is a live\, communi + ty-driven podcast for Kubernetes practitioners who'd rather show than tell + . Expect hands-on walkthroughs\, deep technical dives\, and candid convers + ations spanning AKS\, upstream Kubernetes\, self-hosted clusters\, and the + wider cloud-native ecosystem.

Best of al + l\, we record it live. So as the audience\, you can bring in your question + s\, your hot takes\, and your war stories. The mic is open.

+

 \;

Agenda and + Join Link: \;https://aka.ms/aks/communitycalls

 \;

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-AUTOFILLLOCATION:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +END:VCALENDAR