diff --git a/apps/web-roo-code/src/app/privacy/page.tsx b/apps/web-roo-code/src/app/privacy/page.tsx
index 005bb8cb7c95..d4531e972037 100644
--- a/apps/web-roo-code/src/app/privacy/page.tsx
+++ b/apps/web-roo-code/src/app/privacy/page.tsx
@@ -290,6 +290,12 @@ export default function Privacy() {
service‑related emails (such as password resets, billing notices, or security alerts) will
continue even if you opt out.
+
+ Marketing communications: You can unsubscribe from marketing and
+ promotional emails by clicking the unsubscribe link in those emails. Transactional or
+ service‑related emails (such as password resets, billing notices, or security alerts) will
+ continue even if you opt out.
+
6. Security Practices
diff --git a/packages/cloud/src/CloudService.ts b/packages/cloud/src/CloudService.ts
index ce9e34de8ce6..9944055460d8 100644
--- a/packages/cloud/src/CloudService.ts
+++ b/packages/cloud/src/CloudService.ts
@@ -170,9 +170,9 @@ export class CloudService extends EventEmitter implements Di
// AuthService
- public async login(): Promise {
+ public async login(landingPageSlug?: string): Promise {
this.ensureInitialized()
- return this.authService!.login()
+ return this.authService!.login(landingPageSlug)
}
public async logout(): Promise {
diff --git a/packages/cloud/src/WebAuthService.ts b/packages/cloud/src/WebAuthService.ts
index 934ca90b71d4..3c57508403d2 100644
--- a/packages/cloud/src/WebAuthService.ts
+++ b/packages/cloud/src/WebAuthService.ts
@@ -248,8 +248,10 @@ export class WebAuthService extends EventEmitter implements A
*
* This method initiates the authentication flow by generating a state parameter
* and opening the browser to the authorization URL.
+ *
+ * @param landingPageSlug Optional slug of a specific landing page (e.g., "supernova", "special-offer", etc.)
*/
- public async login(): Promise {
+ public async login(landingPageSlug?: string): Promise {
try {
const vscode = await importVscode()
@@ -267,11 +269,17 @@ export class WebAuthService extends EventEmitter implements A
state,
auth_redirect: `${vscode.env.uriScheme}://${publisher}.${name}`,
})
- const url = `${getRooCodeApiUrl()}/extension/sign-in?${params.toString()}`
+
+ // Use landing page URL if slug is provided, otherwise use default sign-in URL
+ const url = landingPageSlug
+ ? `${getRooCodeApiUrl()}/l/${landingPageSlug}?${params.toString()}`
+ : `${getRooCodeApiUrl()}/extension/sign-in?${params.toString()}`
+
await vscode.env.openExternal(vscode.Uri.parse(url))
} catch (error) {
- this.log(`[auth] Error initiating Roo Code Cloud auth: ${error}`)
- throw new Error(`Failed to initiate Roo Code Cloud authentication: ${error}`)
+ const context = landingPageSlug ? ` (landing page: ${landingPageSlug})` : ""
+ this.log(`[auth] Error initiating Roo Code Cloud auth${context}: ${error}`)
+ throw new Error(`Failed to initiate Roo Code Cloud authentication${context}: ${error}`)
}
}
diff --git a/packages/types/src/cloud.ts b/packages/types/src/cloud.ts
index 7ffb28ae5d67..b56a67464b00 100644
--- a/packages/types/src/cloud.ts
+++ b/packages/types/src/cloud.ts
@@ -239,7 +239,7 @@ export interface AuthService extends EventEmitter {
broadcast(): void
// Authentication methods
- login(): Promise
+ login(landingPageSlug?: string): Promise
logout(): Promise
handleCallback(code: string | null, state: string | null, organizationId?: string | null): Promise
diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts
index 281dac7f37dc..6ca718843cb8 100644
--- a/src/core/webview/ClineProvider.ts
+++ b/src/core/webview/ClineProvider.ts
@@ -152,7 +152,7 @@ export class ClineProvider
public isViewLaunched = false
public settingsImportedAt?: number
- public readonly latestAnnouncementId = "sep-2025-roo-code-cloud" // Roo Code Cloud announcement
+ public readonly latestAnnouncementId = "sep-2025-code-supernova" // Code Supernova stealth model announcement
public readonly providerSettingsManager: ProviderSettingsManager
public readonly customModesManager: CustomModesManager
diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts
index edd979c4f161..e13b5140a15e 100644
--- a/src/core/webview/webviewMessageHandler.ts
+++ b/src/core/webview/webviewMessageHandler.ts
@@ -2410,6 +2410,17 @@ export const webviewMessageHandler = async (
break
}
+ case "cloudLandingPageSignIn": {
+ try {
+ const landingPageSlug = message.text || "supernova"
+ TelemetryService.instance.captureEvent(TelemetryEventName.AUTHENTICATION_INITIATED)
+ await CloudService.instance.login(landingPageSlug)
+ } catch (error) {
+ provider.log(`CloudService#login failed: ${error}`)
+ vscode.window.showErrorMessage("Sign in failed.")
+ }
+ break
+ }
case "rooCloudSignOut": {
try {
await CloudService.instance.logout()
diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts
index a31458a76455..ca6027ecbc04 100644
--- a/src/shared/WebviewMessage.ts
+++ b/src/shared/WebviewMessage.ts
@@ -182,6 +182,7 @@ export interface WebviewMessage {
| "hasOpenedModeSelector"
| "cloudButtonClicked"
| "rooCloudSignIn"
+ | "cloudLandingPageSignIn"
| "rooCloudSignOut"
| "rooCloudManualUrl"
| "condenseTaskContextRequest"
diff --git a/webview-ui/src/components/chat/Announcement.tsx b/webview-ui/src/components/chat/Announcement.tsx
index 8c52c41e42ff..cfe41340bc96 100644
--- a/webview-ui/src/components/chat/Announcement.tsx
+++ b/webview-ui/src/components/chat/Announcement.tsx
@@ -6,12 +6,9 @@ import { Package } from "@roo/package"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { useExtensionState } from "@src/context/ExtensionStateContext"
import { vscode } from "@src/utils/vscode"
-import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@src/components/ui"
+import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@src/components/ui"
import { Button } from "@src/components/ui"
-// Define the production URL constant locally to avoid importing from cloud package in webview
-const PRODUCTION_ROO_CODE_API_URL = "https://app.roocode.com"
-
interface AnnouncementProps {
hideAnnouncement: () => void
}
@@ -28,8 +25,7 @@ interface AnnouncementProps {
const Announcement = ({ hideAnnouncement }: AnnouncementProps) => {
const { t } = useAppTranslation()
const [open, setOpen] = useState(true)
- const { cloudApiUrl } = useExtensionState()
- const cloudUrl = cloudApiUrl || PRODUCTION_ROO_CODE_API_URL
+ const { cloudIsAuthenticated } = useExtensionState()
return (