diff --git a/packages/reflex-base/news/+referrer-param-env-var.feature.md b/packages/reflex-base/news/+referrer-param-env-var.feature.md new file mode 100644 index 00000000000..cc89d0fe737 --- /dev/null +++ b/packages/reflex-base/news/+referrer-param-env-var.feature.md @@ -0,0 +1 @@ +Add the `REFLEX_REFERRER_PARAM` environment variable, read at compile time to append a `ref` query parameter to the "Built with Reflex" badge link. diff --git a/packages/reflex-base/src/reflex_base/environment.py b/packages/reflex-base/src/reflex_base/environment.py index e1556dc6a97..587bba04026 100644 --- a/packages/reflex-base/src/reflex_base/environment.py +++ b/packages/reflex-base/src/reflex_base/environment.py @@ -759,6 +759,10 @@ class EnvironmentVariables: # Extra plugins to append to the config's plugins list. REFLEX_EXTRA_PLUGINS: EnvVar[list[type[Plugin]]] = env_var([]) + # Referrer identifier appended (urlencoded) to the "Built with Reflex" + # badge link as https://reflex.dev/?ref=. Read at compile time. + REFLEX_REFERRER_PARAM: EnvVar[str | None] = env_var(None) + environment = EnvironmentVariables() diff --git a/packages/reflex-components-core/news/+badge-referrer-param.feature.md b/packages/reflex-components-core/news/+badge-referrer-param.feature.md new file mode 100644 index 00000000000..6e222f7b5ee --- /dev/null +++ b/packages/reflex-components-core/news/+badge-referrer-param.feature.md @@ -0,0 +1 @@ +The "Built with Reflex" badge appends a urlencoded `ref` query parameter to its reflex.dev link when the `REFLEX_REFERRER_PARAM` environment variable is set at compile time. diff --git a/packages/reflex-components-core/src/reflex_components_core/core/sticky.py b/packages/reflex-components-core/src/reflex_components_core/core/sticky.py index 3881d77e0dd..f4f7312e341 100644 --- a/packages/reflex-components-core/src/reflex_components_core/core/sticky.py +++ b/packages/reflex-components-core/src/reflex_components_core/core/sticky.py @@ -1,6 +1,9 @@ """Components for displaying the Reflex sticky logo.""" +import urllib.parse + from reflex_base.components.component import ComponentNamespace +from reflex_base.environment import environment from reflex_base.style import Style from reflex_components_core.core.colors import color @@ -69,6 +72,18 @@ def add_style(self): }) +def _badge_href() -> str: + """Compute the badge link, appending the referrer param when set. + + Returns: + The badge destination URL. + """ + referrer = environment.REFLEX_REFERRER_PARAM.get() + if referrer: + return f"https://reflex.dev/?ref={urllib.parse.quote(referrer, safe='')}" + return "https://reflex.dev" + + class StickyBadge(A): """A badge that displays the Reflex sticky logo.""" @@ -82,7 +97,7 @@ def create(cls): return super().create( StickyLogo.create(), desktop_only(StickyLabel.create()), - href="https://reflex.dev", + href=_badge_href(), target="_blank", width="auto", padding="0.375rem", diff --git a/tests/units/components/core/test_sticky.py b/tests/units/components/core/test_sticky.py new file mode 100644 index 00000000000..257201f2553 --- /dev/null +++ b/tests/units/components/core/test_sticky.py @@ -0,0 +1,39 @@ +"""Tests for the "Built with Reflex" sticky badge.""" + +import pytest +from reflex_components_core.core.sticky import StickyBadge + + +def _badge_href() -> str: + """Render a fresh badge and extract its href prop. + + Returns: + The rendered href value, without surrounding quotes. + """ + props = StickyBadge.create().render()["props"] + href_prop = next(p for p in props if p.startswith("href:")) + return href_prop.removeprefix("href:").strip('"') + + +def test_badge_href_default(monkeypatch: pytest.MonkeyPatch): + """Without a referrer param, the badge links to the plain reflex.dev URL.""" + monkeypatch.delenv("REFLEX_REFERRER_PARAM", raising=False) + assert _badge_href() == "https://reflex.dev" + + +def test_badge_href_with_referrer(monkeypatch: pytest.MonkeyPatch): + """A referrer param is appended as a ref query parameter.""" + monkeypatch.setenv("REFLEX_REFERRER_PARAM", "owner-123") + assert _badge_href() == "https://reflex.dev/?ref=owner-123" + + +def test_badge_href_urlencodes_referrer(monkeypatch: pytest.MonkeyPatch): + """Special characters in the referrer param are urlencoded.""" + monkeypatch.setenv("REFLEX_REFERRER_PARAM", "a b&c/d?e=f") + assert _badge_href() == "https://reflex.dev/?ref=a%20b%26c%2Fd%3Fe%3Df" + + +def test_badge_href_empty_referrer(monkeypatch: pytest.MonkeyPatch): + """An empty referrer param falls back to the default URL.""" + monkeypatch.setenv("REFLEX_REFERRER_PARAM", "") + assert _badge_href() == "https://reflex.dev"