diff --git a/src/vertex/app/changelog.md b/src/vertex/app/changelog.md
index 5d24b8520a..9554b8bf15 100644
--- a/src/vertex/app/changelog.md
+++ b/src/vertex/app/changelog.md
@@ -4,6 +4,50 @@
---
+## Version 1.23.41
+**Released:** May 16, 2026
+
+### Scoped Banner System Migration, Login UX Fixes & Dead Code Cleanup
+
+Migrated auth-flow feedback from imperative toast notifications to scoped `InfoBanner` components, hardened the banner-context state management to prevent silent message drops, fixed post-login banner render timing, and removed the defunct local forgot-password page.
+
+
+Auth UX — Scoped Banner Migration (3)
+
+- **Login Page Banners**: Replaced all `ReusableToast` calls in the login flow (`app/login/page.tsx`) with scoped `showBanner` / `BannerSlot` calls. Success, error, and validation feedback is now rendered inline within the login form card rather than as floating toasts, giving users precise contextual feedback without losing their place.
+- **Google Auth Section Banners**: Migrated `components/features/auth/google-auth-section.tsx` to use scoped `InfoBanner` for OAuth error states, replacing previous inline alert elements and ensuring visual consistency across all sign-in paths.
+- **Login Render Timing Fix**: Fixed a race condition where the success banner was not visible before the page redirected after a successful credential login. Resolved by removing an extraneous `setTimeout` that was interfering with React's paint cycle, ensuring the welcome banner renders correctly before navigation occurs.
+
+
+
+
+Banner Context Hardening (1)
+
+- **Full Props Stored in State**: Refactored `context/banner-context.tsx` to store the complete banner props object in state rather than individual fields. This prevents silent message drops that occurred when rapid successive `showBanner` calls partially overwrote state before the component re-rendered, resulting in blank or stale banners being displayed.
+
+
+
+
+Dead Code Removal (1)
+
+- **Forgot Password Page Deleted**: Removed the local `/forgot-password` Next.js route (`app/forgot-password/page.tsx`), which was a dead stub that only `console.log`ed submitted emails without calling any API. The "Forgot password?" link in the login page continues to redirect users directly to AirQo Analytics (`NEXT_PUBLIC_ANALYTICS_URL/user/forgotPwd`) where actual password reset is handled. Cleaned up the middleware route matcher and `authProvider` auth-routes list accordingly.
+
+
+
+
+Files Modified/Deleted (5)
+
+- `src/vertex/app/forgot-password/page.tsx` [DELETED]
+- `src/vertex/app/login/page.tsx` [MODIFIED]
+- `src/vertex/components/features/auth/google-auth-section.tsx` [MODIFIED]
+- `src/vertex/context/banner-context.tsx` [MODIFIED]
+- `src/vertex/core/auth/authProvider.tsx` [MODIFIED]
+- `src/vertex/middleware.ts` [MODIFIED]
+
+
+
+---
+
## Version 1.23.40
**Released:** May 16, 2026
diff --git a/src/vertex/app/forgot-password/page.tsx b/src/vertex/app/forgot-password/page.tsx
deleted file mode 100644
index 1a7eba5d3b..0000000000
--- a/src/vertex/app/forgot-password/page.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-"use client";
-
-import { useState } from "react";
-import { useForm } from "react-hook-form";
-import { zodResolver } from "@hookform/resolvers/zod";
-import * as z from "zod";
-import Link from "next/link";
-import { Button } from "@/components/ui/button";
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form";
-import { Input } from "@/components/ui/input";
-import {
- Card,
- CardContent,
- CardDescription,
- CardFooter,
- CardHeader,
- CardTitle,
-} from "@/components/ui/card";
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
-import {
- ExclamationTriangleIcon,
- CheckCircledIcon,
-} from "@radix-ui/react-icons";
-
-const forgotPasswordSchema = z.object({
- email: z.string().email({ message: "Please enter a valid email address" }),
-});
-
-export default function ForgotPasswordPage() {
- const [status, setStatus] = useState<"idle" | "success" | "error">("idle");
-
- const form = useForm>({
- resolver: zodResolver(forgotPasswordSchema),
- defaultValues: {
- email: "",
- },
- });
-
- async function onSubmit(values: z.infer) {
- setStatus("idle");
- try {
- // Here you would typically send a request to your API to initiate the password reset process
- console.log(values);
- setStatus("success");
- } catch (error) {
- console.error(error);
- setStatus("error");
- }
- }
-
- return (
-
-
-
- Forgot Password
-
- Enter your email to receive a password reset link.
-
-
-
-
-
-
-
-
- Back to Login
-
-
-
-