Skip to content

Add New Tab rebrand feature flag wiring - #2844

Merged
borgateo merged 4 commits into
mainfrom
matteo/rebrand/new-tab-page-feature-flag
Jul 20, 2026
Merged

Add New Tab rebrand feature flag wiring#2844
borgateo merged 4 commits into
mainfrom
matteo/rebrand/new-tab-page-feature-flag

Conversation

@borgateo

@borgateo borgateo commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Asana Task/Github Issue: https://app.asana.com/1/137249556945/project/72649045549333/task/1216270925937865?focus=true

TD:

Related PRs:

Description

Adds NTP rebrand flag wiring to the New Tab Page settings contract.

This introduces settings.newTabPageRebranding, defaults it to disabled when absent, allows it through withFeatureState, exposes useNewTabPageRebranding(), and sets document.body.dataset.rebrand for CSS gating. Also adds ?rebrand=enabled mock support and integration coverage for the body data attribute.

Testing Steps

Screenshot 2026-07-07 at 12 30 34

Checklist

Please tick all that apply:

  • I have tested this change locally
  • I have tested this change locally in all supported browsers
  • This change will be visible to users
  • I have added automated tests that cover this change
  • I have ensured the change is gated by config
  • This change was covered by a ship review
  • This change was covered by a tech design
  • Any dependent config has been merged

Note

Low Risk
Flag plumbing and a body data attribute only; no user-visible rebrand UI yet and behavior stays off unless native config or mock enables it.

Overview
Adds config-driven wiring for a New Tab Page rebrand rollout: newTabPageRebranding is part of the initialSetup settings contract (JSON schema + generated types), merged via Settings / withFeatureState with a disabled default, and surfaced as useNewTabPageRebranding().

On init, the flag sets body[data-rebrand] to "true" or "false" so future rebrand CSS can gate on body[data-rebrand="true"] (placeholder rule added in App.module.css). Mock/dev flows support ?rebrand=enabled, and Playwright tests assert the body attribute default and when the mock param is on.

Reviewed by Cursor Bugbot for commit 2255ab0. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added the semver-minor New feature — triggers minor version bump label Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

[Beta] Generated file diff

Time updated: Mon, 20 Jul 2026 01:34:54 GMT

Apple
    - apple/pages/new-tab/dist/index.css
  • apple/pages/new-tab/dist/index.js

File has changed

Integration
    - integration/pages/new-tab/dist/index.css
  • integration/pages/new-tab/dist/index.js

File has changed

Windows
    - windows/pages/new-tab/dist/index.css
  • windows/pages/new-tab/dist/index.js

File has changed

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Cursor review was not successful.

This PR requires a manual review and approval from a member of one of the following teams:

  • @duckduckgo/content-scope-scripts-owners
  • @duckduckgo/apple-devs
  • @duckduckgo/android-devs
  • @duckduckgo/team-windows-development
  • @duckduckgo/extension-owners
  • @duckduckgo/config-aor
  • @duckduckgo/breakage-aor
  • @duckduckgo/breakage

@borgateo
borgateo force-pushed the matteo/rebrand/new-tab-page-feature-flag branch from 80008eb to 9a506ab Compare July 7, 2026 20:17
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Build Branch

Branch pr-releases/matteo/rebrand/new-tab-page-feature-flag
Commit d80c6c0cd7
Updated July 20, 2026 at 1:34:14 AM UTC

Static preview entry points

QR codes (mobile preview)
Entry point QR code
Docs QR for docs preview
Static pages QR for static pages preview
Integration pages QR for integration pages preview

Integration commands

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#pr-releases/matteo/rebrand/new-tab-page-feature-flag

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", branch: "pr-releases/matteo/rebrand/new-tab-page-feature-flag")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/matteo/rebrand/new-tab-page-feature-flag
git -C submodules/content-scope-scripts checkout origin/pr-releases/matteo/rebrand/new-tab-page-feature-flag
Pin to exact commit

npm (Android / Extension):

npm i github:duckduckgo/content-scope-scripts#d80c6c0cd76c63814f596cf6ffdf3d618cb47f4b

Swift Package Manager (Apple):

.package(url: "https://github.com/duckduckgo/content-scope-scripts.git", revision: "d80c6c0cd76c63814f596cf6ffdf3d618cb47f4b")

git submodule (Windows):

git -C submodules/content-scope-scripts fetch origin pr-releases/matteo/rebrand/new-tab-page-feature-flag
git -C submodules/content-scope-scripts checkout d80c6c0cd76c63814f596cf6ffdf3d618cb47f4b

@borgateo
borgateo force-pushed the matteo/rebrand/new-tab-page-feature-flag branch 2 times, most recently from bddc078 to 2440ca0 Compare July 7, 2026 20:19

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility Assessment

No injected (injected/) or page-world API changes in this PR. All changes are confined to the special-pages New Tab app (settings wiring, a data-rebrand body attribute, an empty CSS placeholder, mock transport, and integration tests). From a web-compatibility perspective for third-party sites, this PR is a no-op — it does not run on arbitrary web pages.

File Lines Severity Finding
special-pages/pages/new-tab/app/index.js 179 info data-rebrand follows the same installGlobalSideEffects pattern as existing data-platform-name / data-display / data-animation attributes. document.body is available after initialSetup() resolves. Default is "false".
special-pages/pages/new-tab/app/components/App.module.css 30–32 info Empty body[data-rebrand="true"] rule block has no layout or rendering impact today. Future styles added here should be tested across platforms (iOS/Android WebView quirks, reduced motion, theme variants).
special-pages/pages/new-tab/app/settings.provider.js 42–45 info useNtpRebrand() is exported but not yet consumed by components. Safe scaffolding; no runtime side effects until future PRs use it.
special-pages/pages/new-tab/app/settings.js 21, 49–61 info Default ntpRebrand: { state: 'disabled' } and withFeatureState enum validation mirror adBlocking. Invalid or missing native values safely fall back to disabled.

No warnings or errors for web compatibility.


Security Assessment

No changes to messaging transports, message bridge, captured-globals, API overrides, or injected initialization. Security surface is limited to native→NTP settings delivery (existing trust boundary).

File Lines Severity Finding
special-pages/pages/new-tab/messages/types/settings.json 30–38 info ntpRebrand.state restricted to "enabled" / "disabled" enum — consistent with adBlocking.
special-pages/pages/new-tab/app/mock-transport.js 617–619 info ?rebrand=enabled URL param only affects local dev / Playwright mock transport, not production native builds.
special-pages/pages/new-tab/app/index.js 179 info data-rebrand is a non-sensitive UI flag exposed on <body>. Same exposure model as other data-* attributes already set by NTP. No nativeData forwarding.

No warnings, errors, or critical findings for security.


Risk Level

Low Risk — Special-pages-only feature-flag scaffolding with safe defaults, schema validation, and integration test coverage; zero injected or messaging security surface changes.


Recommendations

  1. (info) When rebrand CSS is populated in follow-up PRs, run visual QA across theme variants (themeVariant param), light/dark, and reduced-motion — the empty placeholder is harmless now but future rules could affect layout.
  2. (info) Consider documenting ?rebrand=enabled in special-pages/pages/new-tab/readme.md alongside other feature URL params for local dev consistency (optional; other settings flags like ad-blocking are also undocumented).
  3. (info) Verify native clients send ntpRebrand in initialSetup.settings before enabling the flag in production — C-S-S defaults to disabled when absent, which is the correct safe fallback.

Integration tests for the rebrand data attribute (defaults rebrand data attribute to false, sets rebrand data attribute from mock url param) pass locally.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@borgateo
borgateo force-pushed the matteo/rebrand/new-tab-page-feature-flag branch from 2440ca0 to 462bcd6 Compare July 7, 2026 23:32

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Injected PR Evaluation: Web Compatibility & Security

PR: Add New Tab rebrand feature flag wiring (462bcd69)
Scope: special-pages/pages/new-tab/ only — zero injected/, messaging/, or captured-globals changes.


Web Compatibility Assessment

File Lines Severity Finding
(all) info No injected page-world code changes. This PR does not touch browser API overrides, prototype chains, or third-party script interaction surfaces. Web-compat evaluation categories for injected scripts are not applicable.
special-pages/pages/new-tab/app/index.js 179 info data-rebrand body attribute follows the established NTP pattern (data-platformName, data-display, data-animation). Safe CSS hook for gated rebrand styles.
special-pages/pages/new-tab/app/settings.provider.js 42–45 info useNewTabPageRebranding() hook is wired but not yet consumed by components — expected for a flag-wiring PR; no runtime behavior change until follow-up styling lands.
special-pages/pages/new-tab/app/components/App.module.css 30–32 info Empty body[data-rebrand="true"] placeholder block. No layout/viewport impact.
special-pages/pages/new-tab/app/settings.js 55–61 info withFeatureState() rejects non-enabled/disabled state values (same guard as adBlocking). Malformed native payloads are safely ignored.

Security Assessment

File Lines Severity Finding
(all) info Special-pages NTP runs in a privileged embedded browser context (duck://), not hostile third-party pages. Injected security threat models (captured globals, message bridge, prototype attacks) are not applicable.
special-pages/pages/new-tab/messages/types/settings.json 30–38 info JSON Schema constrains newTabPageRebranding.state to enabled | disabled. Referenced by initialSetup.response.json for native→web validation.
special-pages/pages/new-tab/app/settings.js 21, 55–61 info Defaults to { state: 'disabled' }; withFeatureState() double-checks state enum before applying native override. Fail-safe when flag is absent or invalid.
special-pages/pages/new-tab/app/index.js 179 info data-rebrand is a static "true"/"false" string derived from validated settings — no page-controlled input, no URL/data exfiltration vector.
special-pages/pages/new-tab/app/mock-transport.js 617–619 info ?rebrand=enabled URL param is dev/test mock transport only; not a production trust boundary.

No nativeData leakage, messaging transport changes, postMessage usage, dynamic code execution, or uncaptured-global concerns identified.


Risk Level

Low Risk — Special-pages-only feature-flag wiring with safe defaults, schema validation, and integration test coverage; no injected runtime, API shim, or messaging security surface changes.


Recommendations

  1. (info) Coordinate native platform wiring so initialSetup.settings.newTabPageRebranding is populated in production builds (out of scope for this repo PR, but required for the flag to take effect).
  2. (info) When rebrand styles land, consume useNewTabPageRebranding() in components and/or add rules under body[data-rebrand="true"] — the hook and attribute are ready.
  3. (info) Integration tests for default/disabled and mock-enabled states pass locally (2/2 rebrand specs green).
Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@borgateo borgateo self-assigned this Jul 7, 2026
@borgateo
borgateo marked this pull request as ready for review July 8, 2026 01:47

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Web Compatibility & Security Review — PR #2844

Scope: special-pages/pages/new-tab only (+50/−2). No changes to injected/, messaging/ transports, wrapper-utils.js, captured-globals.js, or message-bridge security checks.

Web Compatibility Assessment

File Lines Severity Finding
special-pages/pages/new-tab/app/index.js 179 info data-rebrand body attribute follows the existing data-animation / data-display pattern. Safe CSS hook; defaults to "false".
special-pages/pages/new-tab/app/components/App.module.css 30–32 info Empty body[data-rebrand="true"] placeholder — no layout or style impact until future rules are added.
special-pages/pages/new-tab/app/settings.provider.js 42–45 info useNewTabPageRebranding() hook is defined but not yet consumed by components. Expected for a wiring-only PR.

No API overrides, prototype modifications, DOM timing hazards, or third-party script interaction concerns. NTP runs in DDG's embedded page context, not arbitrary third-party sites.

Security Assessment

File Lines Severity Finding
special-pages/pages/new-tab/messages/types/settings.json 30–39 info JSON Schema constrains newTabPageRebranding.state to enabled | disabled.
special-pages/pages/new-tab/app/settings.js 46–61 info withFeatureState() validates enum before accepting native settings; invalid values are ignored, preserving constructor default (disabled).
special-pages/pages/new-tab/app/index.js 179 info data-rebrand is derived from native-controlled initialSetup settings, not page/user input. No nativeData leakage or new messaging surface.
special-pages/pages/new-tab/app/mock-transport.js 617–619 info ?rebrand=enabled URL param is dev/mock-only; not a production attack surface.

No messaging trust-boundary changes, no uncaptured globals, no postMessage, no dynamic code execution.

Risk Level

Low Risk — Config-only feature-flag plumbing for the New Tab Page, mirroring the established adBlocking pattern, with no injected-script or messaging security surface changes.

Recommendations

  1. Native wiring (out of scope): Ensure platform clients populate settings.newTabPageRebranding in initialSetup before enabling the flag in production.
  2. Follow-up PRs: When adding rebrand styles to App.module.css, prefer design-system tokens (as in recent omnibar theming work) to avoid hardcoded colors.
  3. Tests: Integration coverage for default false and mock enabled param passes (verified locally).

✅ No blocking web-compat or security issues for merge from an injected-scripts perspective.

Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

@vkraucunas vkraucunas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add the rebrand query param info to the new-tab/README.md

Co-authored-by: Cursor <cursoragent@cursor.com>
daxtheduck
daxtheduck previously approved these changes Jul 18, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Injected PR Evaluation: Web Compatibility & Security

PR: Add New Tab rebrand feature flag wiring (5fa7306b)
Scope: special-pages/pages/new-tab/ only — no injected/, messaging/, or API override changes.


Web Compatibility Assessment

File Lines Severity Finding
(all) info Changes are confined to the first-party New Tab Page embedded app. No code runs in third-party page contexts, so injected-script compatibility categories (API fidelity, prototype chain, DOM safety on arbitrary sites) do not apply.
app/components/App.module.css 30–32 info Empty body[data-rebrand="true"] placeholder — no visual or layout changes in this PR. Safe scaffolding for follow-up rebrand CSS.
app/settings.provider.js 42–45 info useNewTabPageRebranding() hook is exported but not yet consumed by components in this PR. Infrastructure-only; no runtime UI impact until follow-up PRs gate styles/assets behind it.
app/index.js 179 info body[data-rebrand] follows the existing data-platform-name / data-display / data-animation pattern. Attribute is set synchronously in installGlobalSideEffects() after init — consistent with other global side effects.

Integration tests: 2/2 rebrand attribute tests pass locally.


Security Assessment

File Lines Severity Finding
(all) info No changes to captured-globals.js, message bridge, messaging transports, postMessage, or origin validation. Special-pages run in a first-party embedded context with native-provided settings — outside the hostile third-party page threat model.
messages/types/settings.json 30–39 info newTabPageRebranding schema lacks additionalProperties: false (same as adBlocking). Low risk because withFeatureState() only accepts state: 'enabled' | 'disabled' and ignores unknown keys via object spread.
app/settings.js 21, 49–61 info Default state: 'disabled' and enum validation in withFeatureState() provide safe defaults when native omits the setting.
app/index.js 70, 179 info Setting is read from native initial-setup response only; no new notify()/request() schemas and no nativeData forwarding risk.

Positive: Feature flag is config-gated with safe default-off behavior, matching the adBlocking pattern.


Risk Level

Low Risk — Special-pages-only settings/schema wiring with default-off feature flag, no injected runtime changes, and no security-boundary modifications.


Recommendations

  1. Coordinate native rollout — Platforms must include newTabPageRebranding in initialSetup settings before consumers can enable rebrand UI in follow-up PRs.
  2. (Optional) Add additionalProperties: false to the newTabPageRebranding schema object for consistency with stricter message schemas elsewhere.
  3. Follow-up PRs should gate rebrand CSS/assets behind body[data-rebrand="true"] or useNewTabPageRebranding() to keep the flag remotely controllable per platform.
Open in Web View Automation 

Sent by Cursor Automation: Web compat and sec

Co-authored-by: Cursor <cursoragent@cursor.com>
@daxtheduck
daxtheduck dismissed their stale review July 18, 2026 02:04

Dismissing stale approval — new commits pushed, awaiting Cursor re-review.

daxtheduck
daxtheduck previously approved these changes Jul 18, 2026
@borgateo
borgateo added this pull request to the merge queue Jul 18, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 18, 2026
@daxtheduck
daxtheduck dismissed their stale review July 20, 2026 01:34

Dismissing stale approval — new commits pushed, awaiting Cursor re-review.

@borgateo
borgateo added this pull request to the merge queue Jul 20, 2026
Merged via the queue into main with commit 92ae219 Jul 20, 2026
42 checks passed
@borgateo
borgateo deleted the matteo/rebrand/new-tab-page-feature-flag branch July 20, 2026 02:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-minor New feature — triggers minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants