diff --git a/assets/common/dark/grid.svg b/assets/common/dark/grid.svg
new file mode 100644
index 000000000..36b00d921
--- /dev/null
+++ b/assets/common/dark/grid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/common/light/grid.svg b/assets/common/light/grid.svg
new file mode 100644
index 000000000..c64061633
--- /dev/null
+++ b/assets/common/light/grid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/logos/dark/gradient_r.svg b/assets/logos/dark/gradient_r.svg
new file mode 100644
index 000000000..1c30d61ba
--- /dev/null
+++ b/assets/logos/dark/gradient_r.svg
@@ -0,0 +1,77 @@
+
\ No newline at end of file
diff --git a/assets/logos/light/gradient_r.svg b/assets/logos/light/gradient_r.svg
new file mode 100644
index 000000000..1c30d61ba
--- /dev/null
+++ b/assets/logos/light/gradient_r.svg
@@ -0,0 +1,77 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/accenture.svg b/assets/migration/dark/accenture.svg
new file mode 100644
index 000000000..c12408f9c
--- /dev/null
+++ b/assets/migration/dark/accenture.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/autodesk.svg b/assets/migration/dark/autodesk.svg
new file mode 100644
index 000000000..6b37b678c
--- /dev/null
+++ b/assets/migration/dark/autodesk.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/claude.svg b/assets/migration/dark/claude.svg
new file mode 100644
index 000000000..fcaafae22
--- /dev/null
+++ b/assets/migration/dark/claude.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/cursor.svg b/assets/migration/dark/cursor.svg
new file mode 100644
index 000000000..b02771473
--- /dev/null
+++ b/assets/migration/dark/cursor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/django.svg b/assets/migration/dark/django.svg
new file mode 100644
index 000000000..30291aa3c
--- /dev/null
+++ b/assets/migration/dark/django.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/fastapi.svg b/assets/migration/dark/fastapi.svg
new file mode 100644
index 000000000..dd0d97fdf
--- /dev/null
+++ b/assets/migration/dark/fastapi.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/fastly.svg b/assets/migration/dark/fastly.svg
new file mode 100644
index 000000000..dc7eb0439
--- /dev/null
+++ b/assets/migration/dark/fastly.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/gradio.svg b/assets/migration/dark/gradio.svg
new file mode 100644
index 000000000..070368ab8
--- /dev/null
+++ b/assets/migration/dark/gradio.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/js.svg b/assets/migration/dark/js.svg
new file mode 100644
index 000000000..d15880a10
--- /dev/null
+++ b/assets/migration/dark/js.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/lovable.svg b/assets/migration/dark/lovable.svg
new file mode 100644
index 000000000..0c076f09f
--- /dev/null
+++ b/assets/migration/dark/lovable.svg
@@ -0,0 +1,46 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/open_sea.svg b/assets/migration/dark/open_sea.svg
new file mode 100644
index 000000000..dc8f1391e
--- /dev/null
+++ b/assets/migration/dark/open_sea.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/plotly.svg b/assets/migration/dark/plotly.svg
new file mode 100644
index 000000000..8bd721101
--- /dev/null
+++ b/assets/migration/dark/plotly.svg
@@ -0,0 +1,23 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/powerbi.svg b/assets/migration/dark/powerbi.svg
new file mode 100644
index 000000000..469973a41
--- /dev/null
+++ b/assets/migration/dark/powerbi.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/react.svg b/assets/migration/dark/react.svg
new file mode 100644
index 000000000..f1306c029
--- /dev/null
+++ b/assets/migration/dark/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/replit.svg b/assets/migration/dark/replit.svg
new file mode 100644
index 000000000..a4ee3f7ed
--- /dev/null
+++ b/assets/migration/dark/replit.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/retool.svg b/assets/migration/dark/retool.svg
new file mode 100644
index 000000000..b76379595
--- /dev/null
+++ b/assets/migration/dark/retool.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/streamlit.svg b/assets/migration/dark/streamlit.svg
new file mode 100644
index 000000000..d9a304a55
--- /dev/null
+++ b/assets/migration/dark/streamlit.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/assets/migration/dark/tableau.svg b/assets/migration/dark/tableau.svg
new file mode 100644
index 000000000..3a9249262
--- /dev/null
+++ b/assets/migration/dark/tableau.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/accenture.svg b/assets/migration/light/accenture.svg
new file mode 100644
index 000000000..c12408f9c
--- /dev/null
+++ b/assets/migration/light/accenture.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/autodesk.svg b/assets/migration/light/autodesk.svg
new file mode 100644
index 000000000..6b37b678c
--- /dev/null
+++ b/assets/migration/light/autodesk.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/claude.svg b/assets/migration/light/claude.svg
new file mode 100644
index 000000000..fcaafae22
--- /dev/null
+++ b/assets/migration/light/claude.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/cursor.svg b/assets/migration/light/cursor.svg
new file mode 100644
index 000000000..b02771473
--- /dev/null
+++ b/assets/migration/light/cursor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/django.svg b/assets/migration/light/django.svg
new file mode 100644
index 000000000..30291aa3c
--- /dev/null
+++ b/assets/migration/light/django.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/fastapi.svg b/assets/migration/light/fastapi.svg
new file mode 100644
index 000000000..dd0d97fdf
--- /dev/null
+++ b/assets/migration/light/fastapi.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/fastly.svg b/assets/migration/light/fastly.svg
new file mode 100644
index 000000000..dc7eb0439
--- /dev/null
+++ b/assets/migration/light/fastly.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/gradio.svg b/assets/migration/light/gradio.svg
new file mode 100644
index 000000000..070368ab8
--- /dev/null
+++ b/assets/migration/light/gradio.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/js.svg b/assets/migration/light/js.svg
new file mode 100644
index 000000000..d15880a10
--- /dev/null
+++ b/assets/migration/light/js.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/lovable.svg b/assets/migration/light/lovable.svg
new file mode 100644
index 000000000..0c076f09f
--- /dev/null
+++ b/assets/migration/light/lovable.svg
@@ -0,0 +1,46 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/open_sea.svg b/assets/migration/light/open_sea.svg
new file mode 100644
index 000000000..dc8f1391e
--- /dev/null
+++ b/assets/migration/light/open_sea.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/plotly.svg b/assets/migration/light/plotly.svg
new file mode 100644
index 000000000..8bd721101
--- /dev/null
+++ b/assets/migration/light/plotly.svg
@@ -0,0 +1,23 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/powerbi.svg b/assets/migration/light/powerbi.svg
new file mode 100644
index 000000000..469973a41
--- /dev/null
+++ b/assets/migration/light/powerbi.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/react.svg b/assets/migration/light/react.svg
new file mode 100644
index 000000000..f1306c029
--- /dev/null
+++ b/assets/migration/light/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/replit.svg b/assets/migration/light/replit.svg
new file mode 100644
index 000000000..a4ee3f7ed
--- /dev/null
+++ b/assets/migration/light/replit.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/retool.svg b/assets/migration/light/retool.svg
new file mode 100644
index 000000000..b76379595
--- /dev/null
+++ b/assets/migration/light/retool.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/streamlit.svg b/assets/migration/light/streamlit.svg
new file mode 100644
index 000000000..d9a304a55
--- /dev/null
+++ b/assets/migration/light/streamlit.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/assets/migration/light/tableau.svg b/assets/migration/light/tableau.svg
new file mode 100644
index 000000000..3a9249262
--- /dev/null
+++ b/assets/migration/light/tableau.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/pcweb/pages/__init__.py b/pcweb/pages/__init__.py
index 02455eb09..9d8f6b264 100644
--- a/pcweb/pages/__init__.py
+++ b/pcweb/pages/__init__.py
@@ -20,6 +20,14 @@
from .meeting_successfully_booked import (
page_meeting_successfully_booked as page_meeting_successfully_booked,
)
+from .migration.low_code import low_code_migration_page as low_code_migration_page
+from .migration.no_code import no_code_migration_page as no_code_migration_page
+from .migration.other_ai_tools import (
+ other_ai_tools_migration_page as other_ai_tools_migration_page,
+)
+from .migration.other_frameworks import (
+ other_frameworks_migration_page as other_frameworks_migration_page,
+)
from .page404 import page404 as page404
from .pricing.pricing import pricing as pricing
from .sales import sales as sales
diff --git a/pcweb/pages/blog/blog.py b/pcweb/pages/blog/blog.py
index 2755cf1f0..d80e10a8f 100644
--- a/pcweb/pages/blog/blog.py
+++ b/pcweb/pages/blog/blog.py
@@ -168,7 +168,7 @@ def component_grid() -> rx.Component:
rx.el.div(
class_name="absolute -bottom-24 -right-px w-px h-24 bg-gradient-to-b from-current to-transparent text-m-slate-4 dark:text-m-slate-10"
),
- class_name="grid lg:grid-cols-2 xl:grid-cols-3 grid-cols-1 lg:border border-m-slate-4 dark:border-m-slate-10 w-full gap-x-8 gap-y-8 lg:gap-y-24 relative py-24 lg:mb-48 mb-24",
+ class_name="grid lg:grid-cols-2 xl:grid-cols-3 grid-cols-1 lg:border border-m-slate-4 dark:border-m-slate-10 w-full gap-x-8 gap-y-8 lg:gap-y-24 relative py-24",
)
diff --git a/pcweb/pages/blog/page.py b/pcweb/pages/blog/page.py
index 080abdbaa..8d555615d 100644
--- a/pcweb/pages/blog/page.py
+++ b/pcweb/pages/blog/page.py
@@ -173,7 +173,7 @@ def more_posts(current_post: dict) -> rx.Component:
*posts,
class_name="gap-6 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 [&>*]:min-w-[320px] w-full mb-4 blog-grid",
),
- class_name="flex flex-col gap-10 mt-20 mb-24",
+ class_name="flex flex-col gap-10 mt-20",
)
diff --git a/pcweb/pages/framework/views/footer_index.py b/pcweb/pages/framework/views/footer_index.py
index 80db108c6..09713fe45 100644
--- a/pcweb/pages/framework/views/footer_index.py
+++ b/pcweb/pages/framework/views/footer_index.py
@@ -81,7 +81,7 @@ def dark_mode_toggle() -> rx.Component:
tab_item("system", "computer_footer"),
tab_item("light", "sun_footer"),
tab_item("dark", "moon_footer"),
- class_name="flex flex-row gap-0.5 items-center p-0.5 [box-shadow:0_1px_0_0_rgba(0,_0,_0,_0.08),_0_0_0_1px_rgba(0,_0,_0,_0.08),_0_1px_2px_0_rgba(0,_0,_0,_0.02),_0_1px_4px_0_rgba(0,_0,_0,_0.02)] w-fit mt-auto bg-m-slate-1 dark:bg-m-slate-12 rounded-[0.625rem] dark:border dark:border-m-slate-9 border border-transparent lg:ml-auto",
+ class_name="flex flex-row gap-0.5 items-center p-0.5 [box-shadow:0_1px_0_0_rgba(0,_0,_0,_0.08),_0_0_0_1px_rgba(0,_0,_0,_0.08),_0_1px_2px_0_rgba(0,_0,_0,_0.02),_0_1px_4px_0_rgba(0,_0,_0,_0.02)] w-fit mt-auto bg-m-slate-1 dark:bg-m-slate-12 rounded-[0.625rem] dark:border dark:border-m-slate-9 border border-transparent lg:ml-auto mr-px",
)
diff --git a/pcweb/pages/hosting/hosting.py b/pcweb/pages/hosting/hosting.py
index fb37aba4c..4add630ce 100644
--- a/pcweb/pages/hosting/hosting.py
+++ b/pcweb/pages/hosting/hosting.py
@@ -8,7 +8,6 @@
from .views.features import features
from .views.hero import hero
from .views.preview import preview
-from .views.pricing_cards import pricing_cards
from .views.templates import templates
@@ -21,7 +20,6 @@ def hosting_landing() -> rx.Component:
preview(),
deploy_animation(),
features(),
- pricing_cards(),
templates(),
class_name="flex flex-col size-full justify-center items-center",
)
diff --git a/pcweb/pages/migration/common/compare.py b/pcweb/pages/migration/common/compare.py
new file mode 100644
index 000000000..34d17143a
--- /dev/null
+++ b/pcweb/pages/migration/common/compare.py
@@ -0,0 +1,154 @@
+from typing import TypedDict
+
+import reflex as rx
+import reflex_ui as ui
+
+
+class ComparisonItem(TypedDict):
+ title: str
+ icon: str
+ pros: list[str]
+ cons: list[str]
+
+
+def comparison_title(title: str, icon: str) -> rx.Component:
+ return rx.el.div(
+ ui.icon(icon, stroke_width=1.5, class_name="shrink-0 lg:size-7 size-6"),
+ rx.el.span(
+ title,
+ class_name="text-m-slate-12 dark:text-m-slate-3 lg:text-lg text-base font-[575]",
+ ),
+ class_name="flex flex-row items-center gap-3 lg:p-12 p-6 border-y border-r border-m-slate-4 dark:border-m-slate-10",
+ )
+
+
+def pros_card(pros: list[str]) -> rx.Component:
+ return rx.el.ul(
+ *[
+ rx.el.li(
+ ui.icon(
+ "Tick02Icon",
+ class_name="shrink-0 text-primary-9 dark:text-primary-10 h-[1.5rem]",
+ ),
+ rx.el.span(
+ pro,
+ class_name="text-m-slate-12 dark:text-m-slate-3 text-sm font-[525]",
+ ),
+ class_name="flex flex-row items-start gap-2.5",
+ )
+ for pro in pros
+ ],
+ class_name="list-inside flex flex-col gap-2 lg:p-12 p-6 [box-shadow:0_0_0_1px_rgba(0,_0,_0,_0.12)_inset,_0_6px_12px_0_rgba(0,_0,_0,_0.06),_0_1px_1px_0_rgba(0,_0,_0,_0.01),_0_4px_6px_0_rgba(0,_0,_0,_0.02)] dark:shadow-none dark:border dark:border-m-slate-9 rounded-xl bg-white-1 dark:bg-m-slate-11 w-full",
+ )
+
+
+def cons_card(cons: list[str]) -> rx.Component:
+ return rx.el.ul(
+ *[
+ rx.el.li(
+ ui.icon(
+ "MultiplicationSignIcon",
+ stroke_width=1.5,
+ class_name="shrink-0 text-m-slate-7 dark:text-m-slate-6 h-[1.5rem]",
+ ),
+ rx.el.span(
+ con,
+ class_name="text-m-slate-7 dark:text-m-slate-6 text-sm font-[525]",
+ ),
+ class_name="flex flex-row items-start gap-2.5",
+ )
+ for con in cons
+ ],
+ class_name="list-inside flex flex-col gap-2 lg:p-12 p-6 w-full lg:border-x border-l border-m-slate-4 dark:border-m-slate-10",
+ )
+
+
+def pros_cons_cards(pros: list[str], cons: list[str]) -> rx.Component:
+ return rx.el.div(
+ pros_card(pros),
+ cons_card(cons),
+ class_name="grid lg:grid-cols-2 grid-cols-1 max-lg:border-r",
+ )
+
+
+def top_title(title: str) -> rx.Component:
+ return rx.el.span(
+ title,
+ class_name="text-m-slate-12 dark:text-m-slate-3 text-xs leading-[1.5rem] font-[415] font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-12 lg:py-3 p-6 bg-m-slate-1 dark:bg-m-slate-12 border-t uppercase",
+ )
+
+
+def heading_with_breaks(lines: list[str]) -> list[rx.Component | str]:
+ heading_parts: list[rx.Component | str] = []
+ for index, line in enumerate(lines):
+ heading_parts.append(line)
+ if index < len(lines) - 1:
+ heading_parts.append(rx.el.br(class_name="max-lg:hidden"))
+ return heading_parts
+
+
+def comparison_cards(
+ top_left_title: str,
+ top_right_title: str,
+ comparison_items: list[ComparisonItem],
+) -> rx.Component:
+ return rx.el.div(
+ rx.el.div(
+ top_title(top_left_title),
+ top_title(top_right_title),
+ class_name="grid grid-cols-2",
+ ),
+ *[
+ rx.fragment(
+ comparison_title(item["title"], item["icon"]),
+ pros_cons_cards(item["pros"], item["cons"]),
+ )
+ for item in comparison_items
+ ],
+ rx.el.div(
+ class_name="absolute -top-24 right-0 w-px h-24 bg-gradient-to-b from-transparent to-current text-m-slate-4 dark:text-m-slate-10 max-lg:hidden"
+ ),
+ rx.el.div(
+ class_name="absolute -top-24 -left-px w-px h-24 bg-gradient-to-b from-transparent to-current text-m-slate-4 dark:text-m-slate-10 max-lg:hidden"
+ ),
+ rx.el.div(
+ class_name="absolute -bottom-24 right-0 w-px h-24 bg-gradient-to-b from-current to-transparent text-m-slate-4 dark:text-m-slate-10"
+ ),
+ rx.el.div(
+ class_name="absolute -bottom-24 -left-px w-px h-24 bg-gradient-to-b from-current to-transparent text-m-slate-4 dark:text-m-slate-10"
+ ),
+ class_name="flex flex-col w-full max-w-[45rem] ml-auto border-l border-m-slate-4 dark:border-m-slate-9 mt-18 border-b mb-24 relative",
+ )
+
+
+def compare(
+ *,
+ kicker: str,
+ heading_lines: list[str],
+ description: str,
+ top_left_title: str,
+ top_right_title: str,
+ comparison_items: list[ComparisonItem],
+) -> rx.Component:
+ return rx.el.section(
+ rx.el.div(
+ rx.el.div(
+ rx.el.p(
+ kicker,
+ class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-primary-9",
+ ),
+ rx.el.h1(
+ *heading_with_breaks(heading_lines),
+ class_name="text-m-slate-12 dark:text-m-slate-3 text-3xl font-[575]",
+ ),
+ rx.el.h2(
+ description,
+ class_name="text-m-slate-7 dark:text-m-slate-6 text-base font-[475]",
+ ),
+ class_name="flex flex-col gap-6 lg:max-w-[18rem] lg:sticky lg:mt-[5rem] lg:top-[9rem] lg:self-start max-lg:self-center max-lg:items-center max-lg:text-center",
+ ),
+ comparison_cards(top_left_title, top_right_title, comparison_items),
+ class_name="flex lg:flex-row flex-col max-lg:gap-6 max-w-(--docs-layout-max-width) mx-auto relative pb-24 pt-6 max-lg:px-6",
+ ),
+ class_name="bg-linear-to-b from-white-1 to-m-slate-1 dark:from-m-slate-11 dark:to-m-slate-12 to-20% w-full relative",
+ )
diff --git a/pcweb/pages/migration/common/explore.py b/pcweb/pages/migration/common/explore.py
new file mode 100644
index 000000000..8da896eea
--- /dev/null
+++ b/pcweb/pages/migration/common/explore.py
@@ -0,0 +1,76 @@
+from typing import TypedDict
+
+import reflex as rx
+import reflex_ui as ui
+
+
+class Feature(TypedDict):
+ title: str
+ description: str
+ icon: str
+
+
+def feature_card(feature: Feature) -> rx.Component:
+ return rx.el.div(
+ rx.el.div(
+ ui.icon(
+ feature["icon"],
+ stroke_width=1.5,
+ class_name="text-primary-10 dark:text-primary-9 size-5 shrink-0",
+ ),
+ rx.el.span(
+ feature["title"],
+ class_name="text-m-slate-12 dark:text-m-slate-3 text-sm font-[525]",
+ ),
+ class_name="flex flex-row gap-2.5 items-center",
+ ),
+ rx.el.p(
+ feature["description"],
+ class_name="text-m-slate-7 dark:text-m-slate-6 text-sm font-[475] text-start",
+ ),
+ class_name="flex flex-col gap-2 justify-start",
+ )
+
+
+def feature_grid(features: list[Feature]) -> rx.Component:
+ return rx.el.div(
+ *[feature_card(feature) for feature in features],
+ class_name="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-12 gap-y-16",
+ )
+
+
+def explore(
+ *,
+ kicker: str,
+ title_prefix: str,
+ title_suffix: str,
+ description: str,
+ features: list[Feature],
+) -> rx.Component:
+ return rx.el.section(
+ rx.el.div(
+ rx.el.div(
+ rx.el.p(
+ kicker,
+ class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-primary-9",
+ ),
+ rx.el.div(
+ rx.el.h1(
+ title_prefix,
+ rx.el.br(),
+ title_suffix,
+ class_name="text-m-slate-12 dark:text-m-slate-3 lg:text-4xl text-3xl font-[575] shrink-0",
+ ),
+ rx.el.p(
+ description,
+ class_name="text-base text-m-slate-7 dark:text-m-slate-6 font-[475]",
+ ),
+ class_name="flex lg:flex-row flex-col gap-8 lg:gap-36",
+ ),
+ class_name="relative flex flex-col gap-6 lg:pt-24 pt-16",
+ ),
+ feature_grid(features),
+ class_name="flex flex-col gap-16 max-w-(--layout-max-width) mx-auto lg:px-24 px-6 max-lg:text-center relative lg:pb-24 pb-16",
+ ),
+ class_name="bg-gradient-to-b from-white-1 to-m-slate-1 dark:from-m-slate-11 dark:to-m-slate-12 w-full",
+ )
diff --git a/pcweb/pages/migration/common/hero.py b/pcweb/pages/migration/common/hero.py
new file mode 100644
index 000000000..402ac1fb9
--- /dev/null
+++ b/pcweb/pages/migration/common/hero.py
@@ -0,0 +1,101 @@
+from typing import TypedDict
+
+import reflex as rx
+import reflex_ui as ui
+from reflex_ui.blocks.demo_form import demo_form_dialog
+
+from pcweb.components.marketing_button import button
+
+
+class HeroLogo(TypedDict):
+ image_name: str
+ alt: str
+ class_name: str
+
+
+def floating_logo(logo: HeroLogo, logo_base_path: str) -> rx.Component:
+ return rx.el.div(
+ rx.image(
+ src=f"{logo_base_path}/{rx.color_mode_cond('light', 'dark')}/{logo['image_name']}",
+ alt=logo["alt"],
+ loading="eager",
+ custom_attrs={"fetchPriority": "high"},
+ ),
+ class_name=ui.cn(
+ logo["class_name"],
+ "absolute left-1/2 -translate-x-1/2 -translate-y-1/2 z-[-1] pointer-events-none size-16 rounded-[1rem] bg-m-slate-1 dark:bg-m-slate-12 [box-shadow:0_1px_0_0_#FFF_inset,_0_0_0_1px_rgba(0,_0,_0,_0.12),_0_8px_16px_0_rgba(0,_0,_0,_0.06),_0_1px_1px_0_rgba(0,_0,_0,_0.01),_0_4px_8px_0_rgba(0,_0,_0,_0.02)] dark:shadow-none dark:border dark:border-m-slate-9 flex items-center justify-center",
+ ),
+ )
+
+
+def gradient_logo() -> rx.Component:
+ return rx.el.div(
+ rx.image(
+ src=f"/logos/{rx.color_mode_cond('light', 'dark')}/gradient_r.svg",
+ alt="Gradient Reflex Logo",
+ loading="eager",
+ custom_attrs={"fetchPriority": "high"},
+ ),
+ class_name="size-24 flex items-center justify-center absolute left-1/2 -translate-x-1/2 -translate-y-1/2 z-[1] pointer-events-none top-[13.5rem]",
+ )
+
+
+def hero(
+ *,
+ kicker: str,
+ title: str,
+ subtitle: str,
+ cta_text: str,
+ logos: list[HeroLogo],
+ logo_base_path: str,
+) -> rx.Component:
+ return rx.el.section(
+ rx.el.div(
+ rx.el.div(
+ rx.image(
+ src=f"/common/{rx.color_mode_cond('light', 'dark')}/grid.svg",
+ alt="Grid",
+ loading="eager",
+ custom_attrs={"fetchPriority": "high"},
+ class_name=ui.cn(
+ "absolute left-1/2 -translate-x-1/2 z-[-1] pointer-events-none top-0",
+ ),
+ ),
+ *[floating_logo(logo, logo_base_path=logo_base_path) for logo in logos],
+ gradient_logo(),
+ class_name="max-lg:hidden",
+ ),
+ rx.el.p(
+ kicker,
+ class_name="text-sm font-[525] text-primary-10 dark:text-m-slate-6 -mt-6",
+ ),
+ rx.el.h1(
+ title,
+ class_name="text-m-slate-12 dark:text-m-slate-3 lg:text-5xl text-3xl font-[575]",
+ ),
+ rx.el.h2(
+ subtitle,
+ class_name="text-m-slate-7 dark:text-m-slate-6 text-base font-[475]",
+ ),
+ demo_form_dialog(
+ trigger=button(
+ cta_text,
+ variant="primary",
+ size="lg",
+ native_button=False,
+ ),
+ ),
+ rx.el.div(
+ class_name="absolute -bottom-px -right-24 w-24 h-px bg-gradient-to-l from-transparent to-current text-m-slate-4 dark:text-m-slate-10"
+ ),
+ rx.el.div(
+ class_name="absolute -bottom-px -left-24 w-24 h-px bg-gradient-to-r from-transparent to-current text-m-slate-4 dark:text-m-slate-10"
+ ),
+ class_name=ui.cn(
+ "flex flex-col gap-6 items-center justify-center text-center max-w-[45rem] pb-16 border-b border-m-slate-4 dark:border-m-slate-10 relative isolate lg:pt-[21.75rem] pt-[10.5rem]",
+ ),
+ ),
+ class_name=ui.cn(
+ "flex lg:flex-row flex-col max-w-(--layout-max-width) mx-auto lg:px-24 px-6 overflow-hidden",
+ ),
+ )
diff --git a/pcweb/pages/migration/common/quotes.py b/pcweb/pages/migration/common/quotes.py
new file mode 100644
index 000000000..d2a64b4b8
--- /dev/null
+++ b/pcweb/pages/migration/common/quotes.py
@@ -0,0 +1,113 @@
+from typing import TypedDict
+
+import reflex as rx
+import reflex_ui as ui
+from reflex.experimental import ClientStateVar
+
+
+class CompanyInfo(TypedDict):
+ key: str
+ logo_image_name: str
+ logo_alt: str
+ name: str
+ title: str
+ quote: str
+ profile_image: str
+
+
+active_company_cs = ClientStateVar.create("active_company_cs", default="open_sea")
+
+
+def company_card(company: CompanyInfo, logo_base_path: str) -> rx.Component:
+ return rx.el.button(
+ rx.image(
+ src=f"{logo_base_path}/{rx.color_mode_cond('light', 'dark')}/{company['logo_image_name']}",
+ alt=company["logo_alt"],
+ loading="lazy",
+ class_name=ui.cn(
+ "transition-[filter] group-hover:brightness-0 dark:group-hover:brightness-[10]",
+ rx.cond(
+ active_company_cs.value == company["key"],
+ "brightness-0 dark:brightness-[10]",
+ "",
+ ),
+ ),
+ ),
+ aria_label=f"Company: {company['key']}",
+ on_click=active_company_cs.set_value(company["key"]),
+ class_name=ui.cn(
+ "flex justify-end items-center h-12 py-3.5 lg:pr-12 pr-3.5 group",
+ rx.cond(
+ active_company_cs.value == company["key"],
+ "lg:shadow-[1px_0_0_0_var(--m-slate-12)] lg:dark:shadow-[1px_0_0_0_var(--m-slate-3)]",
+ "",
+ ),
+ ),
+ )
+
+
+def quote_card(company: CompanyInfo) -> rx.Component:
+ return rx.el.div(
+ rx.el.p(
+ company["quote"],
+ class_name="text-m-slate-12 dark:text-m-slate-3 text-lg font-[575] text-pretty",
+ ),
+ rx.el.div(
+ ui.gradient_profile(
+ seed=company["name"],
+ class_name="size-6 rounded-full",
+ )
+ if not company["profile_image"]
+ else rx.image(
+ src=company["profile_image"],
+ loading="lazy",
+ alt=company["name"],
+ class_name="size-6 rounded-full",
+ ),
+ rx.el.span(
+ company["name"],
+ class_name="text-m-slate-12 dark:text-m-slate-3 text-sm font-[525]",
+ ),
+ rx.el.span(
+ company["title"],
+ class_name="text-m-slate-7 dark:text-m-slate-6 text-sm font-[525]",
+ ),
+ class_name="flex flex-row items-center gap-3",
+ ),
+ class_name="flex flex-col gap-8 lg:px-12 lg:pt-16 p-6 lg:w-[33rem] w-full",
+ )
+
+
+def companies_column(companies: list[CompanyInfo], logo_base_path: str) -> rx.Component:
+ return rx.el.div(
+ *[
+ company_card(company, logo_base_path=logo_base_path)
+ for company in companies
+ ],
+ rx.el.div(
+ class_name="absolute -bottom-24 -right-px w-px h-24 bg-gradient-to-b from-current to-transparent text-m-slate-4 dark:text-m-slate-10 max-lg:hidden"
+ ),
+ class_name="flex max-lg:px-6 max-lg:overflow-x-auto lg:flex-col flex-row gap-2 pt-13 lg:max-w-[12rem] w-full lg:border-r border-m-slate-4 dark:border-m-slate-10 relative max-lg:justify-center",
+ )
+
+
+def quotes(
+ *,
+ companies: list[CompanyInfo],
+ default_active_key: str,
+ logo_base_path: str,
+) -> rx.Component:
+ matches: list[tuple[str, rx.Component]] = [
+ (company["key"], quote_card(company)) for company in companies
+ ]
+
+ return rx.el.section(
+ companies_column(companies, logo_base_path=logo_base_path),
+ rx.match(
+ active_company_cs.value,
+ *matches,
+ quote_card(companies[0]),
+ ),
+ on_mount=active_company_cs.set_value(default_active_key),
+ class_name="flex lg:flex-row flex-col pb-24 max-w-[45rem] mx-auto w-full dark:bg-[radial-gradient(50%_100%_at_50%_0%,var(--m-slate-11,#1D2025)_50.33%,var(--m-slate-12,#151618)_100%)] bg-[radial-gradient(50%_100%_at_50%_0%,var(white,#fff)_50.33%,var(--m-slate-1,#FCFCFD)_100%)]",
+ )
diff --git a/pcweb/pages/migration/low_code/__init__.py b/pcweb/pages/migration/low_code/__init__.py
new file mode 100644
index 000000000..ef446472c
--- /dev/null
+++ b/pcweb/pages/migration/low_code/__init__.py
@@ -0,0 +1,30 @@
+import reflex as rx
+
+from pcweb.meta.meta import create_meta_tags
+from pcweb.pages.about.views.divider import divider
+from pcweb.pages.migration.low_code.views import compare, explore, hero, quotes
+from pcweb.templates.marketing_page import marketing_page
+
+
+@marketing_page(
+ path="/migration/low-code",
+ title="Switch from Low Code to Reflex",
+ meta=create_meta_tags(
+ title="Switch from Low Code to Reflex",
+ description="Switch from Low Code to Reflex - The platform to build and scale enterprise apps in pure Python",
+ image="/previews/index_preview.webp",
+ ),
+)
+def low_code_migration_page() -> rx.Component:
+ return rx.el.div(
+ rx.el.div(
+ hero(),
+ quotes(),
+ divider(),
+ compare(),
+ divider(),
+ explore(),
+ class_name="flex flex-col relative justify-center items-center w-full",
+ ),
+ class_name="flex flex-col w-full relative h-full justify-center items-center",
+ )
diff --git a/pcweb/pages/migration/low_code/views/__init__.py b/pcweb/pages/migration/low_code/views/__init__.py
new file mode 100644
index 000000000..f76295d0f
--- /dev/null
+++ b/pcweb/pages/migration/low_code/views/__init__.py
@@ -0,0 +1,6 @@
+from .compare import compare
+from .explore import explore
+from .hero import hero
+from .quotes import quotes
+
+__all__ = ["compare", "explore", "hero", "quotes"]
diff --git a/pcweb/pages/migration/low_code/views/compare.py b/pcweb/pages/migration/low_code/views/compare.py
new file mode 100644
index 000000000..4797e1ee5
--- /dev/null
+++ b/pcweb/pages/migration/low_code/views/compare.py
@@ -0,0 +1,105 @@
+from pcweb.pages.migration.common.compare import ComparisonItem
+from pcweb.pages.migration.common.compare import compare as common_compare
+
+COMPARISON_ITEMS: list[ComparisonItem] = [
+ {
+ "title": "Architecture and state management.",
+ "icon": "SquareArrowExpand02Icon",
+ "pros": [
+ "Your app only updates the parts that changed — no unnecessary reruns, so it stays fast even with large data",
+ "User sessions remember where they are — multi-step workflows, background tasks, and real-time updates all work without extra effort",
+ "The event-driven model keeps your code clean and organized, even as your app gets more complex",
+ ],
+ "cons": [
+ "Streamlit reruns your entire script every time a user clicks anything, leading to memory leaks and slowdowns that make it unreliable for long-term use",
+ "Dash works fine for small apps, but as they grow the logic gets spread across many separate callback functions with no native support for object-oriented state, making it hard to follow and maintain",
+ "Gradio is built for ML model demos — it's not a general-purpose app framework",
+ ],
+ },
+ {
+ "title": "Real-time and interactivity.",
+ "icon": "ZapIcon",
+ "pros": [
+ "Changes on the server show up instantly in the browser — no refresh needed, no extra setup",
+ "Live dashboards, real-time data feeds, and collaborative features just work out of the box",
+ "Fully event-based — your app can react to specific user actions like edits, clicks, and selections as they happen",
+ ],
+ "cons": [
+ "Streamlit can't push updates to the user — nothing happens in the browser until the user clicks something to trigger a full script rerun",
+ "Dash has no built-in way to push live updates — getting real-time data requires workarounds like constant polling or adding custom extensions",
+ "Gradio only handles simple input-in, output-out interactions for ML models — it's not built for apps that need to respond to complex user actions",
+ ],
+ },
+ {
+ "title": "Code structure and maintainability.",
+ "icon": "SourceCodeSquareIcon",
+ "pros": [
+ "Clean Python class structure keeps your code organized and easy to follow, even as apps grow to multiple pages and features",
+ "Real projects with complexity use roughly half the code compared to the same app built in Dash",
+ "Teams that tried other Python frameworks found Reflex significantly cleaner to maintain and extend",
+ ],
+ "cons": [
+ "Dash scatters your logic across many separate callback functions that become harder to trace as the app grows",
+ "Streamlit's simple script approach works at first but falls apart when you need complex page flows or shared state across views",
+ "Gradio's simple interface definitions can't support complex multi-page app structures",
+ ],
+ },
+ {
+ "title": "Customization and UI components.",
+ "icon": "WebDesign01Icon",
+ "pros": [
+ "No limits on what you can build — use any React component in pure Python with full control over styling and layout",
+ "Complete design flexibility without ever leaving the Python ecosystem",
+ ],
+ "cons": [
+ "Most low-code Python frameworks offer very basic layout and styling options with little flexibility",
+ "Lack of customization is one of the most commonly cited frustrations across low-code Python tools — building anything beyond the default look typically requires dropping into React, TypeScript, or JavaScript",
+ ],
+ },
+ {
+ "title": "Built-in functionality.",
+ "icon": "Settings01Icon",
+ "pros": [
+ "Authentication, database management, background jobs, file uploads, and role-based access all come built in",
+ "Everything you need to go from prototype to production without stitching together a patchwork of separate tools",
+ "SSO and user management are included — no third-party libraries or workarounds needed",
+ ],
+ "cons": [
+ "Streamlit has no built-in auth, database access, or background processing — even simple things like a loading button require workarounds",
+ "The Dash open-source package has no auth, no background tasks, and no database layer — each one needs a separate library",
+ "Gradio is focused narrowly on ML demos and lacks general-purpose app features entirely",
+ ],
+ },
+ {
+ "title": "Deployment and the prototype-to-production gap.",
+ "icon": "UserSwitchIcon",
+ "pros": [
+ "Compiles to a FastAPI backend with a React frontend on an async web server — production-ready and container-friendly from the start",
+ "Fits into Git, pull requests, automated testing, and CI/CD from day one — no separate production rewrite needed",
+ "What you build is what you ship — you're in production without having to rebuild",
+ ],
+ "cons": [
+ "All low-code tools are seen as prototyping tools — teams build a first version, then have to rebuild the real thing from scratch when it's time to ship to production",
+ "Streamlit apps hit out-of-memory errors under load with even moderately large datasets, and its rerun model fundamentally limits production scalability",
+ "Open-source Dash runs on Flask and requires manual infrastructure setup to scale",
+ ],
+ },
+]
+
+
+def compare():
+ return common_compare(
+ kicker="Compare",
+ heading_lines=[
+ "How You Benefit ",
+ "With Reflex vs. ",
+ "Streamlit, Dash, Gradio",
+ ],
+ description="Streamlit, Dash, and Gradio get you prototyping fast. Reflex lets you finish. Here's how Reflex compares to the leading low-code Python frameworks.",
+ top_left_title="Reflex",
+ top_right_title="Streamlit, Dash, Gradio",
+ comparison_items=COMPARISON_ITEMS,
+ )
+
+
+__all__ = ["compare"]
diff --git a/pcweb/pages/migration/low_code/views/explore.py b/pcweb/pages/migration/low_code/views/explore.py
new file mode 100644
index 000000000..3d5a107c1
--- /dev/null
+++ b/pcweb/pages/migration/low_code/views/explore.py
@@ -0,0 +1,48 @@
+from pcweb.pages.migration.common.explore import Feature
+from pcweb.pages.migration.common.explore import explore as common_explore
+
+FEATURES: list[Feature] = [
+ {
+ "title": "Architecture That Scales",
+ "description": "Declarative state, event-driven updates, and reactive re-renders. Only affected components update — no full script reruns or callback spaghetti.",
+ "icon": "SquareArrowExpand02Icon",
+ },
+ {
+ "title": "Real-Time Out of the Box",
+ "description": "WebSocket sync means server changes show up instantly in the browser. Live dashboards and collaborative features work natively.",
+ "icon": "ZapIcon",
+ },
+ {
+ "title": "Clean, Maintainable Code",
+ "description": "Python class-based state keeps logic organized. Real projects use roughly half the code compared to equivalent Dash apps.",
+ "icon": "SourceCodeSquareIcon",
+ },
+ {
+ "title": "Full Customization",
+ "description": "Wrap any React component from Python. Complete design flexibility without leaving the Python ecosystem.",
+ "icon": "WebDesign01Icon",
+ },
+ {
+ "title": "Production-Ready Built-Ins",
+ "description": "Auth, ORM, database migrations, background jobs, and file uploads — everything you need to ship without stitching together libraries.",
+ "icon": "Settings01Icon",
+ },
+ {
+ "title": "What You Build Is What You Ship",
+ "description": "Compiles to FastAPI + React. Fits Git, CI/CD, and container deployment from day one. No prototype-to-production rewrite.",
+ "icon": "UserSwitchIcon",
+ },
+]
+
+
+def explore():
+ return common_explore(
+ kicker="Explore",
+ title_prefix="Why Reflex Over ",
+ title_suffix="Streamlit, Dash, Gradio",
+ description="Low-code Python frameworks get you prototyping fast. Reflex lets you finish. Declarative state, real-time updates, production-ready output from day one.",
+ features=FEATURES,
+ )
+
+
+__all__ = ["explore"]
diff --git a/pcweb/pages/migration/low_code/views/hero.py b/pcweb/pages/migration/low_code/views/hero.py
new file mode 100644
index 000000000..0a5825e55
--- /dev/null
+++ b/pcweb/pages/migration/low_code/views/hero.py
@@ -0,0 +1,34 @@
+from pcweb.pages.migration.common.hero import HeroLogo
+from pcweb.pages.migration.common.hero import hero as common_hero
+
+HERO_LOGOS: list[HeroLogo] = [
+ {
+ "image_name": "streamlit.svg",
+ "alt": "Streamlit Logo",
+ "class_name": "top-[9.5rem] -ml-[10.5rem]",
+ },
+ {
+ "image_name": "plotly.svg",
+ "alt": "Plotly Dash Logo",
+ "class_name": "top-[9.5rem] ml-[10.5rem]",
+ },
+ {
+ "image_name": "gradio.svg",
+ "alt": "Gradio Logo",
+ "class_name": "top-[15rem] -ml-[16.5rem]",
+ },
+]
+
+
+def hero():
+ return common_hero(
+ kicker="Move From Low Code to Reflex",
+ title="Architecture That Scales, Code That Stays Clean",
+ subtitle="Streamlit, Dash, and Gradio get you prototyping fast, but you hit walls — rerun model, callback spaghetti, no real-time, no production path. Reflex gives you declarative state, event-driven updates, and production-ready output from day one.",
+ cta_text="Book a Demo",
+ logos=HERO_LOGOS,
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["hero"]
diff --git a/pcweb/pages/migration/low_code/views/quotes.py b/pcweb/pages/migration/low_code/views/quotes.py
new file mode 100644
index 000000000..04ea15888
--- /dev/null
+++ b/pcweb/pages/migration/low_code/views/quotes.py
@@ -0,0 +1,52 @@
+from pcweb.pages.migration.common.quotes import CompanyInfo
+from pcweb.pages.migration.common.quotes import quotes as common_quotes
+
+COMPANIES: list[CompanyInfo] = [
+ {
+ "key": "open_sea",
+ "logo_image_name": "open_sea.svg",
+ "logo_alt": "OpenSea logo",
+ "name": "Alex Atallah",
+ "title": "Co-founder & CEO, OpenSea",
+ "quote": "Have been playing with Reflex since January and realized I should just say, from a fellow YC member: love the architecture decisions you guys are making!",
+ "profile_image": "/landing/social/alex_opensea.webp",
+ },
+ {
+ "key": "fastly",
+ "logo_image_name": "fastly.svg",
+ "logo_alt": "Fastly logo",
+ "name": "Emanuele Bonura",
+ "title": "Senior SOC Engineer",
+ "quote": "Migrating our cybersecurity app from Streamlit to Reflex has been excellent. We quickly built a unified interface connecting BigQuery, Salesforce, and PagerDuty for our 15+ team members. The ease of use and rapid development, supported by your responsive team, made it a great experience.",
+ "profile_image": "",
+ },
+ {
+ "key": "autodesk",
+ "logo_image_name": "autodesk.svg",
+ "logo_alt": "Autodesk logo",
+ "name": "Paolo",
+ "title": "Principal Consultant",
+ "quote": "One person can do the job of two with Reflex, so it cut our cost in half. I am able to wear all the caps at once: Solution Architecture, UI/UX, front-end and back-end.",
+ "profile_image": "",
+ },
+ {
+ "key": "accenture",
+ "logo_image_name": "accenture.svg",
+ "logo_alt": "Accenture logo",
+ "name": "Jordan Lee",
+ "title": "Senior Automation Developer",
+ "quote": "Reflex let us automate workflows that were impossible with previous low-code platforms. We went from prototype to rollout in days, and our team loves writing real Python instead of fighting drag-and-drop UI pain.",
+ "profile_image": "",
+ },
+]
+
+
+def quotes():
+ return common_quotes(
+ companies=COMPANIES,
+ default_active_key="open_sea",
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["quotes"]
diff --git a/pcweb/pages/migration/no_code/__init__.py b/pcweb/pages/migration/no_code/__init__.py
new file mode 100644
index 000000000..061e6d6f6
--- /dev/null
+++ b/pcweb/pages/migration/no_code/__init__.py
@@ -0,0 +1,30 @@
+import reflex as rx
+
+from pcweb.meta.meta import create_meta_tags
+from pcweb.pages.about.views.divider import divider
+from pcweb.pages.migration.no_code.views import compare, explore, hero, quotes
+from pcweb.templates.marketing_page import marketing_page
+
+
+@marketing_page(
+ path="/migration/no-code",
+ title="Switch from No Code to Reflex",
+ meta=create_meta_tags(
+ title="Switch from No Code to Reflex",
+ description="Switch from No Code to Reflex - The platform to build and scale enterprise apps",
+ image="/previews/index_preview.webp",
+ ),
+)
+def no_code_migration_page() -> rx.Component:
+ return rx.el.div(
+ rx.el.div(
+ hero(),
+ quotes(),
+ divider(),
+ compare(),
+ divider(),
+ explore(),
+ class_name="flex flex-col relative justify-center items-center w-full",
+ ),
+ class_name="flex flex-col w-full relative h-full justify-center items-center",
+ )
diff --git a/pcweb/pages/migration/no_code/views/__init__.py b/pcweb/pages/migration/no_code/views/__init__.py
new file mode 100644
index 000000000..f76295d0f
--- /dev/null
+++ b/pcweb/pages/migration/no_code/views/__init__.py
@@ -0,0 +1,6 @@
+from .compare import compare
+from .explore import explore
+from .hero import hero
+from .quotes import quotes
+
+__all__ = ["compare", "explore", "hero", "quotes"]
diff --git a/pcweb/pages/migration/no_code/views/compare.py b/pcweb/pages/migration/no_code/views/compare.py
new file mode 100644
index 000000000..ac0c15863
--- /dev/null
+++ b/pcweb/pages/migration/no_code/views/compare.py
@@ -0,0 +1,89 @@
+from pcweb.pages.migration.common.compare import ComparisonItem
+from pcweb.pages.migration.common.compare import compare as common_compare
+
+COMPARISON_ITEMS: list[ComparisonItem] = [
+ {
+ "title": "Full control without the ceiling.",
+ "icon": "CodesandboxIcon",
+ "pros": [
+ "Pure Python with no ceiling — if Python can do it, Reflex can do it",
+ "Custom logic, complex data flows, and performance optimization are all possible out of the box",
+ "One language to learn, no platform-specific syntax",
+ ],
+ "cons": [
+ "No-code tools hit walls on custom logic, complex data flows, and performance optimization",
+ "Anything the platform didn't anticipate requires workarounds or is impossible",
+ 'Despite the "no-code" label, there is a significant learning curve for advanced features',
+ ],
+ },
+ {
+ "title": "You own your code.",
+ "icon": "SourceCodeSquareIcon",
+ "pros": [
+ "It's your Python code — deploy it anywhere, on any infrastructure",
+ "Full version control so your codebase is portable and auditable",
+ "Never hostage to a platform's pricing changes or shutdown",
+ ],
+ "cons": [
+ "Your app lives on their infrastructure, in their proprietary format",
+ "Vendor lock-in — no way to export or migrate your work",
+ "Exposed to pricing changes you can't control",
+ ],
+ },
+ {
+ "title": "Python ecosystem access.",
+ "icon": "PythonIcon",
+ "pros": [
+ "Build with Python libraries your team already knows — pandas, scikit-learn, or any pip package",
+ "No need to learn JavaScript or be constrained by a drag-and-drop builder's integrations",
+ "Data scientists, ML engineers, and backend devs can build internal tools or customer-facing apps directly",
+ ],
+ "cons": [
+ "No-code tools constrain you to a drag-and-drop builder's integrations",
+ "Requires learning JavaScript or platform-specific languages for anything custom",
+ "Data scientists and ML engineers can't use the Python libraries they already know",
+ ],
+ },
+ {
+ "title": "Scales with complexity.",
+ "icon": "SquareArrowExpand02Icon",
+ "pros": [
+ "CRUD, auth flows, real-time features, complex state management, and custom APIs are all native",
+ "No dataset size limits, no scheduled refreshes — real-time by default",
+ "Handles complexity natively because it's just code",
+ ],
+ "cons": [
+ "Even basic interactivity is a problem and tools like Tableau and Power BI don't natively support CRUD operations at all",
+ "Performance degrades at scale — dataset size limits, scheduled refreshes instead of real-time data, and apps slowing under complexity",
+ "Once you need users to create, edit, or delete data, you're fighting the tool instead of building",
+ ],
+ },
+ {
+ "title": "Production-ready from day one.",
+ "icon": "UserSwitchIcon",
+ "pros": [
+ "Fits into Git, PRs, automated testing, staging environments from the start",
+ 'What you demo is what you ship — no "rewrite it properly" phase',
+ "Your engineering team can deploy, maintain, and scale it using workflows they already use",
+ ],
+ "cons": [
+ "No native version control, git integration, code review, or CI/CD pipelines",
+ "When it's time to hand it to IT or take it to production, you hit a wall",
+ "The prototype-to-production gap forces teams to either rewrite in code or accept platform limitations",
+ ],
+ },
+]
+
+
+def compare():
+ return common_compare(
+ kicker="Compare",
+ heading_lines=["How You Benefit ", "With Reflex vs. ", "Other Approaches"],
+ description="No-code tools get you started fast, but Reflex lets you finish. Here's how Reflex compares to platforms like Power BI, Tableau, Retool, and similar no-code tools.",
+ top_left_title="Reflex",
+ top_right_title="Power BI, Tableau, Retool",
+ comparison_items=COMPARISON_ITEMS,
+ )
+
+
+__all__ = ["compare"]
diff --git a/pcweb/pages/migration/no_code/views/explore.py b/pcweb/pages/migration/no_code/views/explore.py
new file mode 100644
index 000000000..0916b83d4
--- /dev/null
+++ b/pcweb/pages/migration/no_code/views/explore.py
@@ -0,0 +1,48 @@
+from pcweb.pages.migration.common.explore import Feature
+from pcweb.pages.migration.common.explore import explore as common_explore
+
+FEATURES: list[Feature] = [
+ {
+ "title": "Full Control Without the Ceiling",
+ "description": "Pure Python with no ceiling — custom logic, complex data flows, and performance optimization are all possible out of the box.",
+ "icon": "CodesandboxIcon",
+ },
+ {
+ "title": "You Own Your Code",
+ "description": "Deploy anywhere, on any infrastructure. Full version control. Never hostage to a platform's pricing changes or shutdown.",
+ "icon": "SourceCodeSquareIcon",
+ },
+ {
+ "title": "Python Ecosystem Access",
+ "description": "Build with pandas, scikit-learn, or any pip package. No JavaScript. Data scientists and ML engineers can ship directly.",
+ "icon": "PythonIcon",
+ },
+ {
+ "title": "Scales With Complexity",
+ "description": "CRUD, auth flows, real-time features, complex state management, and custom APIs — all native. Real-time by default.",
+ "icon": "SquareArrowExpand02Icon",
+ },
+ {
+ "title": "Production-Ready From Day One",
+ "description": "Git, PRs, automated testing, staging environments from the start. What you demo is what you ship.",
+ "icon": "UserSwitchIcon",
+ },
+ {
+ "title": "Data Stack Integrations",
+ "description": "Connect databases, APIs, and internal services without low-code workarounds. No platform lock-in.",
+ "icon": "DatabaseIcon",
+ },
+]
+
+
+def explore():
+ return common_explore(
+ kicker="Explore",
+ title_prefix="Why Reflex Over ",
+ title_suffix="Power BI, Tableau, Retool",
+ description="No-code tools get you started fast, but Reflex lets you finish. Pure Python, no ceiling, you own your code.",
+ features=FEATURES,
+ )
+
+
+__all__ = ["explore"]
diff --git a/pcweb/pages/migration/no_code/views/hero.py b/pcweb/pages/migration/no_code/views/hero.py
new file mode 100644
index 000000000..f321d16e8
--- /dev/null
+++ b/pcweb/pages/migration/no_code/views/hero.py
@@ -0,0 +1,34 @@
+from pcweb.pages.migration.common.hero import HeroLogo
+from pcweb.pages.migration.common.hero import hero as common_hero
+
+HERO_LOGOS: list[HeroLogo] = [
+ {
+ "image_name": "powerbi.svg",
+ "alt": "Power BI Logo",
+ "class_name": "top-[9.5rem] -ml-[10.5rem]",
+ },
+ {
+ "image_name": "retool.svg",
+ "alt": "Retool Logo",
+ "class_name": "top-[9.5rem] ml-[10.5rem]",
+ },
+ {
+ "image_name": "tableau.svg",
+ "alt": "Tableau Logo",
+ "class_name": "top-[15rem] -ml-[16.5rem]",
+ },
+]
+
+
+def hero():
+ return common_hero(
+ kicker="Move From No Code to Reflex",
+ title="Full Control Without the Ceiling",
+ subtitle="No-code tools get you to v1 fast, but you hit walls — custom logic, complex data flows, performance. With Reflex, you're writing Python, so there's no ceiling. You own your code, deploy anywhere, and ship what you demo.",
+ cta_text="Book a Demo",
+ logos=HERO_LOGOS,
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["hero"]
diff --git a/pcweb/pages/migration/no_code/views/quotes.py b/pcweb/pages/migration/no_code/views/quotes.py
new file mode 100644
index 000000000..04ea15888
--- /dev/null
+++ b/pcweb/pages/migration/no_code/views/quotes.py
@@ -0,0 +1,52 @@
+from pcweb.pages.migration.common.quotes import CompanyInfo
+from pcweb.pages.migration.common.quotes import quotes as common_quotes
+
+COMPANIES: list[CompanyInfo] = [
+ {
+ "key": "open_sea",
+ "logo_image_name": "open_sea.svg",
+ "logo_alt": "OpenSea logo",
+ "name": "Alex Atallah",
+ "title": "Co-founder & CEO, OpenSea",
+ "quote": "Have been playing with Reflex since January and realized I should just say, from a fellow YC member: love the architecture decisions you guys are making!",
+ "profile_image": "/landing/social/alex_opensea.webp",
+ },
+ {
+ "key": "fastly",
+ "logo_image_name": "fastly.svg",
+ "logo_alt": "Fastly logo",
+ "name": "Emanuele Bonura",
+ "title": "Senior SOC Engineer",
+ "quote": "Migrating our cybersecurity app from Streamlit to Reflex has been excellent. We quickly built a unified interface connecting BigQuery, Salesforce, and PagerDuty for our 15+ team members. The ease of use and rapid development, supported by your responsive team, made it a great experience.",
+ "profile_image": "",
+ },
+ {
+ "key": "autodesk",
+ "logo_image_name": "autodesk.svg",
+ "logo_alt": "Autodesk logo",
+ "name": "Paolo",
+ "title": "Principal Consultant",
+ "quote": "One person can do the job of two with Reflex, so it cut our cost in half. I am able to wear all the caps at once: Solution Architecture, UI/UX, front-end and back-end.",
+ "profile_image": "",
+ },
+ {
+ "key": "accenture",
+ "logo_image_name": "accenture.svg",
+ "logo_alt": "Accenture logo",
+ "name": "Jordan Lee",
+ "title": "Senior Automation Developer",
+ "quote": "Reflex let us automate workflows that were impossible with previous low-code platforms. We went from prototype to rollout in days, and our team loves writing real Python instead of fighting drag-and-drop UI pain.",
+ "profile_image": "",
+ },
+]
+
+
+def quotes():
+ return common_quotes(
+ companies=COMPANIES,
+ default_active_key="open_sea",
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["quotes"]
diff --git a/pcweb/pages/migration/other_ai_tools/__init__.py b/pcweb/pages/migration/other_ai_tools/__init__.py
new file mode 100644
index 000000000..730134cad
--- /dev/null
+++ b/pcweb/pages/migration/other_ai_tools/__init__.py
@@ -0,0 +1,30 @@
+import reflex as rx
+
+from pcweb.meta.meta import create_meta_tags
+from pcweb.pages.about.views.divider import divider
+from pcweb.pages.migration.other_ai_tools.views import compare, explore, hero, quotes
+from pcweb.templates.marketing_page import marketing_page
+
+
+@marketing_page(
+ path="/migration/other-ai-tools",
+ title="Switch from Other AI Tools to Reflex",
+ meta=create_meta_tags(
+ title="Switch from Other AI Tools to Reflex",
+ description="Switch from Other AI Tools to Reflex - The platform to build and scale enterprise apps",
+ image="/previews/low_code_migration_preview.webp",
+ ),
+)
+def other_ai_tools_migration_page() -> rx.Component:
+ return rx.el.div(
+ rx.el.div(
+ hero(),
+ quotes(),
+ divider(),
+ compare(),
+ divider(),
+ explore(),
+ class_name="flex flex-col relative justify-center items-center w-full",
+ ),
+ class_name="flex flex-col w-full relative h-full justify-center items-center",
+ )
diff --git a/pcweb/pages/migration/other_ai_tools/views/__init__.py b/pcweb/pages/migration/other_ai_tools/views/__init__.py
new file mode 100644
index 000000000..f76295d0f
--- /dev/null
+++ b/pcweb/pages/migration/other_ai_tools/views/__init__.py
@@ -0,0 +1,6 @@
+from .compare import compare
+from .explore import explore
+from .hero import hero
+from .quotes import quotes
+
+__all__ = ["compare", "explore", "hero", "quotes"]
diff --git a/pcweb/pages/migration/other_ai_tools/views/compare.py b/pcweb/pages/migration/other_ai_tools/views/compare.py
new file mode 100644
index 000000000..9588a648a
--- /dev/null
+++ b/pcweb/pages/migration/other_ai_tools/views/compare.py
@@ -0,0 +1,155 @@
+import reflex as rx
+
+from pcweb.pages.migration.common.compare import ComparisonItem
+from pcweb.pages.migration.common.compare import compare as common_compare
+
+AI_APP_BUILDERS_ITEMS: list[ComparisonItem] = [
+ {
+ "title": "Built on a real Python framework, not a black box.",
+ "icon": "PythonIcon",
+ "pros": [
+ "The AI writes to an open-source Python framework with shared abstractions, so generated code follows consistent, structured patterns that developers can fully inspect and modify",
+ "Non-technical users can start apps with natural language and developers refine the exact same codebase. No handoff gap and no throwaway prototype",
+ "Built-in abstractions for auth, real-time streaming, and shared state mean the AI generates reliable code rather than stitching together workarounds",
+ ],
+ "cons": [
+ "Replit and Lovable generate code that is often fragile, hard to understand, and difficult for developers to take over and maintain",
+ "Debugging is unpredictable and expensive. Users report burning through significant tokens and spending hundreds of dollars just fixing bugs the AI introduced",
+ "The output often looks great as a demo but can't actually be launched without significant technical help to finish and configure external services",
+ ],
+ },
+ {
+ "title": "Works with your existing infrastructure.",
+ "icon": "CloudServerIcon",
+ "pros": [
+ "The AI App Builder deploys on-prem, in your private cloud, or air-gapped so your apps run wherever your infrastructure already lives",
+ "Connects to any data source: REST or GraphQL APIs, any Python library or SDK, databases like PostgreSQL, MySQL, and MongoDB, and file formats like CSV, Excel, PDF, and images",
+ "Integrates natively with your existing Python codebase and auth systems rather than being a separate island",
+ ],
+ "cons": [
+ "Replit and Lovable are SaaS-only with no self-hosted on-prem option. Your code and data flow through their servers",
+ "These platforms lock you into a specific stack — a particular database, cloud, or frontend framework — that may not match what your organization has standardized on",
+ "Enterprise projects are rarely greenfield, but these platforms have no way to integrate with existing codebases, data stacks, or internal services",
+ ],
+ },
+ {
+ "title": "Enterprise guardrails and governance.",
+ "icon": "Layers01Icon",
+ "pros": [
+ "Prompt security blocks malicious threats, code generation runs in sandboxed environments, and your data is never used for training",
+ "SSO enforced on every application, with RBAC controls across integrations, apps, and users",
+ "Every action is audit-logged and sent to your SIEM for full visibility, with a unified platform to view, manage, and govern all apps across the organization",
+ ],
+ "cons": [
+ "Replit and Lovable are built for individual users, not organizations. There's no shared view of what's been built, no consistent security policies, and no governance layer",
+ "Non-technical users building apps on these platforms commonly misconfigure databases and security policies, with Lovable having had a critical vulnerability where AI-generated code was exposed to malicious prompt injection",
+ "No audit logging, no centralized access control, and no way to enforce security standards across teams",
+ ],
+ },
+ {
+ "title": "Deploy anywhere, scale without limits.",
+ "icon": "SquareArrowExpand02Icon",
+ "pros": [
+ "One-click deployment to any infrastructure including on-premise, with a unified platform to manage, monitor, and govern all apps",
+ "The platform owns the full stack — the AI builder, underlying framework, and hosting — so the same app scales from prototype to production without switching tools",
+ "No manual finishing, no external service configuration, and no rebuilding required to get to production",
+ ],
+ "cons": [
+ "Replit and Lovable typically offer one deployment option: their own cloud. If you need AWS, Azure, GCP, or on-premise, you're out of luck",
+ "These platforms create great prototypes but are often fragile under more complex enterprise requirements, requiring significant manual work to get anywhere near production-ready",
+ "Scaling beyond a demo means configuring external services, debugging platform limitations, and often rebuilding parts of the app outside the platform entirely",
+ ],
+ },
+]
+
+AI_CODING_ASSISTANTS_ITEMS: list[ComparisonItem] = [
+ {
+ "title": "Accessible to your whole team, not just engineers.",
+ "icon": "UserGroupIcon",
+ "pros": [
+ "Non-technical users describe what they need in natural language and get a working app. No coding knowledge required",
+ "Developers can refine the exact same codebase when needed, with no handoff gap between prototype and production",
+ "The person with the idea can take it all the way to deployment without needing to know Git, terminal commands, or software architecture",
+ ],
+ "cons": [
+ "Claude Code and Cursor are built exclusively for developers who already understand code, Git workflows, terminal commands, and software architecture",
+ "Non-technical team members like PMs, analysts, operations, and business stakeholders are completely cut out of the development process",
+ "Only 17% of developers say AI coding tools have improved team collaboration, meaning they remain individual productivity tools, not organization-wide solutions",
+ ],
+ },
+ {
+ "title": "A complete platform, not just a coding tool.",
+ "icon": "CodesandboxIcon",
+ "pros": [
+ "Includes the AI builder, the underlying open-source framework, and deployment and hosting as a unified platform for the entire app lifecycle from idea to production",
+ "Built-in integrations, auth, real-time features, and database management mean you're not assembling separate tools for each piece",
+ "Organization-level features like shared integrations, governance, and a centralized app management dashboard come out of the box",
+ ],
+ "cons": [
+ "Claude Code and Cursor help you write code faster but don't provide a framework, deployment, hosting, or app management",
+ "You still need to choose and assemble your own stack (framework, database, auth, hosting, CI/CD) and the AI just helps you type faster within that stack",
+ "Every new project starts from scratch with no shared patterns, no reusable integrations, and no consistency across what different teams build",
+ ],
+ },
+ {
+ "title": "Structured, maintainable output.",
+ "icon": "SourceCodeSquareIcon",
+ "pros": [
+ "The AI writes to a specific framework with shared abstractions, so generated code follows consistent patterns that are easy to understand and modify",
+ "Common operations like authentication, real-time streaming, and shared state are handled by the framework itself, reducing boilerplate and increasing reliability",
+ "The framework acts as guardrails, keeping codebases consistent across teams and projects",
+ ],
+ "cons": [
+ "Claude Code and Cursor can generate code in any style, any framework, and any architecture, leading to inconsistent patterns across projects and teams",
+ "Without framework-level guardrails, AI-generated code can be harder to review, maintain, and scale because there's no shared standard for how things are built",
+ "Large refactors across many files can still go wrong, and the AI has no awareness of your organization's conventions unless you manually configure it each time",
+ ],
+ },
+ {
+ "title": "Enterprise security and data privacy.",
+ "icon": "DatabaseIcon",
+ "pros": [
+ "Deploys entirely on your own infrastructure (on-prem, private cloud, or air-gapped) so your code and data never leave your environment",
+ "Prompt security, code sandboxing, SSO on every application, RBAC controls, and full audit logging to your SIEM",
+ "Your data is never used for training, with a unified governance layer across the entire platform",
+ ],
+ "cons": [
+ "Claude Code and Cursor offer privacy options like bring-your-own-key and Privacy Mode, but they remain individual developer tools with no centralized way to enforce consistent security policies across all developers",
+ "No unified governance layer across all the apps being built, no built-in deployment to your own infrastructure, and no organization-wide RBAC or audit logging to a SIEM",
+ "They solve the 'write code faster' problem but not the 'manage, govern, and deploy apps across an organization' problem",
+ ],
+ },
+]
+
+
+def compare():
+ return rx.el.div(
+ common_compare(
+ kicker="AI App Builder Platforms",
+ heading_lines=[
+ "How You Benefit ",
+ "With Reflex vs. ",
+ "Replit & Lovable",
+ ],
+ description="AI app builders get you prototyping fast but hit a wall in production. Here's how Reflex compares to Replit and Lovable.",
+ top_left_title="Reflex",
+ top_right_title="Replit & Lovable",
+ comparison_items=AI_APP_BUILDERS_ITEMS,
+ ),
+ common_compare(
+ kicker="AI Coding Assistants",
+ heading_lines=[
+ "How You Benefit ",
+ "With Reflex vs. ",
+ "Claude Code & Cursor",
+ ],
+ description="AI coding assistants boost developer speed but leave the rest of your organization behind. Here's how Reflex compares to Claude Code and Cursor.",
+ top_left_title="Reflex",
+ top_right_title="Claude Code & Cursor",
+ comparison_items=AI_CODING_ASSISTANTS_ITEMS,
+ ),
+ class_name="flex flex-col w-full",
+ )
+
+
+__all__ = ["compare"]
diff --git a/pcweb/pages/migration/other_ai_tools/views/explore.py b/pcweb/pages/migration/other_ai_tools/views/explore.py
new file mode 100644
index 000000000..4c450f123
--- /dev/null
+++ b/pcweb/pages/migration/other_ai_tools/views/explore.py
@@ -0,0 +1,48 @@
+from pcweb.pages.migration.common.explore import Feature
+from pcweb.pages.migration.common.explore import explore as common_explore
+
+FEATURES: list[Feature] = [
+ {
+ "title": "Full Control Without the Ceiling",
+ "description": "Pure Python with no ceiling — custom logic, complex data flows, and performance optimization are all possible out of the box. You own every line of code.",
+ "icon": "CodesandboxIcon",
+ },
+ {
+ "title": "Accessible to Your Whole Team",
+ "description": "Non-technical users build with natural language, developers refine the same codebase. No handoff gap, no throwaway prototype, no one left out.",
+ "icon": "UserGroupIcon",
+ },
+ {
+ "title": "A Complete Platform, Not Just a Tool",
+ "description": "The AI builder, open-source framework, and hosting in one place. No assembling a stack, no starting from scratch on every project.",
+ "icon": "Layers01Icon",
+ },
+ {
+ "title": "Works With Your Existing Infrastructure",
+ "description": "Deploy on-prem, in your private cloud, or air-gapped. Connect any database, API, or Python library your organization already uses.",
+ "icon": "CloudServerIcon",
+ },
+ {
+ "title": "Enterprise Guardrails and Governance",
+ "description": "SSO, RBAC, audit logging to your SIEM, and sandboxed code generation. A unified governance layer across every app your organization builds.",
+ "icon": "DatabaseIcon",
+ },
+ {
+ "title": "Python Ecosystem Access",
+ "description": "Build with pandas, scikit-learn, or any pip package. Data scientists and ML engineers can ship directly without learning a new stack.",
+ "icon": "PythonIcon",
+ },
+]
+
+
+def explore():
+ return common_explore(
+ kicker="Explore",
+ title_prefix="Why Reflex Over ",
+ title_suffix="Replit, Lovable, Claude Code & Cursor",
+ description="Whether you're escaping fragile AI-generated code or looking beyond a developer-only tool, Reflex gives your whole organization a production-grade platform.",
+ features=FEATURES,
+ )
+
+
+__all__ = ["explore"]
diff --git a/pcweb/pages/migration/other_ai_tools/views/hero.py b/pcweb/pages/migration/other_ai_tools/views/hero.py
new file mode 100644
index 000000000..c65aeac6b
--- /dev/null
+++ b/pcweb/pages/migration/other_ai_tools/views/hero.py
@@ -0,0 +1,39 @@
+from pcweb.pages.migration.common.hero import HeroLogo
+from pcweb.pages.migration.common.hero import hero as common_hero
+
+HERO_LOGOS: list[HeroLogo] = [
+ {
+ "image_name": "cursor.svg",
+ "alt": "Cursor Logo",
+ "class_name": "top-[9.5rem] -ml-[10.5rem]",
+ },
+ {
+ "image_name": "claude.svg",
+ "alt": "Claude Logo",
+ "class_name": "top-[15rem] ml-[16.5rem]",
+ },
+ {
+ "image_name": "replit.svg",
+ "alt": "Replit Logo",
+ "class_name": "top-[9.5rem] ml-[10.5rem]",
+ },
+ {
+ "image_name": "lovable.svg",
+ "alt": "Lovable Logo",
+ "class_name": "top-[15rem] -ml-[16.5rem]",
+ },
+]
+
+
+def hero():
+ return common_hero(
+ kicker="Move From Other AI Tools to Reflex",
+ title="The Next-Gen Platform Built for Modern Enterprises",
+ subtitle="Escape AI tool constraints without sacrificing speed. Build production-grade apps in pure Python with complete control over your stack.",
+ cta_text="Book a Demo",
+ logos=HERO_LOGOS,
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["hero"]
diff --git a/pcweb/pages/migration/other_ai_tools/views/quotes.py b/pcweb/pages/migration/other_ai_tools/views/quotes.py
new file mode 100644
index 000000000..04ea15888
--- /dev/null
+++ b/pcweb/pages/migration/other_ai_tools/views/quotes.py
@@ -0,0 +1,52 @@
+from pcweb.pages.migration.common.quotes import CompanyInfo
+from pcweb.pages.migration.common.quotes import quotes as common_quotes
+
+COMPANIES: list[CompanyInfo] = [
+ {
+ "key": "open_sea",
+ "logo_image_name": "open_sea.svg",
+ "logo_alt": "OpenSea logo",
+ "name": "Alex Atallah",
+ "title": "Co-founder & CEO, OpenSea",
+ "quote": "Have been playing with Reflex since January and realized I should just say, from a fellow YC member: love the architecture decisions you guys are making!",
+ "profile_image": "/landing/social/alex_opensea.webp",
+ },
+ {
+ "key": "fastly",
+ "logo_image_name": "fastly.svg",
+ "logo_alt": "Fastly logo",
+ "name": "Emanuele Bonura",
+ "title": "Senior SOC Engineer",
+ "quote": "Migrating our cybersecurity app from Streamlit to Reflex has been excellent. We quickly built a unified interface connecting BigQuery, Salesforce, and PagerDuty for our 15+ team members. The ease of use and rapid development, supported by your responsive team, made it a great experience.",
+ "profile_image": "",
+ },
+ {
+ "key": "autodesk",
+ "logo_image_name": "autodesk.svg",
+ "logo_alt": "Autodesk logo",
+ "name": "Paolo",
+ "title": "Principal Consultant",
+ "quote": "One person can do the job of two with Reflex, so it cut our cost in half. I am able to wear all the caps at once: Solution Architecture, UI/UX, front-end and back-end.",
+ "profile_image": "",
+ },
+ {
+ "key": "accenture",
+ "logo_image_name": "accenture.svg",
+ "logo_alt": "Accenture logo",
+ "name": "Jordan Lee",
+ "title": "Senior Automation Developer",
+ "quote": "Reflex let us automate workflows that were impossible with previous low-code platforms. We went from prototype to rollout in days, and our team loves writing real Python instead of fighting drag-and-drop UI pain.",
+ "profile_image": "",
+ },
+]
+
+
+def quotes():
+ return common_quotes(
+ companies=COMPANIES,
+ default_active_key="open_sea",
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["quotes"]
diff --git a/pcweb/pages/migration/other_frameworks/__init__.py b/pcweb/pages/migration/other_frameworks/__init__.py
new file mode 100644
index 000000000..06e496b6b
--- /dev/null
+++ b/pcweb/pages/migration/other_frameworks/__init__.py
@@ -0,0 +1,30 @@
+import reflex as rx
+
+from pcweb.meta.meta import create_meta_tags
+from pcweb.pages.about.views.divider import divider
+from pcweb.pages.migration.other_frameworks.views import compare, explore, hero, quotes
+from pcweb.templates.marketing_page import marketing_page
+
+
+@marketing_page(
+ path="/migration/other-frameworks",
+ title="Switch from Other Frameworks to Reflex",
+ meta=create_meta_tags(
+ title="Switch from Other Frameworks to Reflex",
+ description="Switch from Other Frameworks to Reflex - The platform to build and scale enterprise apps",
+ image="/previews/low_code_migration_preview.webp",
+ ),
+)
+def other_frameworks_migration_page() -> rx.Component:
+ return rx.el.div(
+ rx.el.div(
+ hero(),
+ quotes(),
+ divider(),
+ compare(),
+ divider(),
+ explore(),
+ class_name="flex flex-col relative justify-center items-center w-full",
+ ),
+ class_name="flex flex-col w-full relative h-full justify-center items-center",
+ )
diff --git a/pcweb/pages/migration/other_frameworks/views/__init__.py b/pcweb/pages/migration/other_frameworks/views/__init__.py
new file mode 100644
index 000000000..f76295d0f
--- /dev/null
+++ b/pcweb/pages/migration/other_frameworks/views/__init__.py
@@ -0,0 +1,6 @@
+from .compare import compare
+from .explore import explore
+from .hero import hero
+from .quotes import quotes
+
+__all__ = ["compare", "explore", "hero", "quotes"]
diff --git a/pcweb/pages/migration/other_frameworks/views/compare.py b/pcweb/pages/migration/other_frameworks/views/compare.py
new file mode 100644
index 000000000..b7c33283c
--- /dev/null
+++ b/pcweb/pages/migration/other_frameworks/views/compare.py
@@ -0,0 +1,97 @@
+from pcweb.pages.migration.common.compare import ComparisonItem
+from pcweb.pages.migration.common.compare import compare as common_compare
+
+COMPARISON_ITEMS: list[ComparisonItem] = [
+ {
+ "title": "One language, one codebase",
+ "icon": "PythonIcon",
+ "pros": [
+ "Build your entire app — frontend and backend — in pure Python with no context switching between languages",
+ "One codebase to maintain, version control, test, and deploy instead of two separate projects",
+ "No need to hire or rely on separate JavaScript and Python developers",
+ ],
+ "cons": [
+ "Traditional stacks require maintaining two codebases in two languages — Python for the backend and JavaScript/TypeScript for the frontend where every new feature touches both codebases",
+ "Connecting the two halves requires writing and maintaining REST or GraphQL API glue code, data serialization, and state synchronization",
+ "The full stack quickly expands to include React, TypeScript, Node, a bundler, a package manager, a CSS framework, and separate deployment orchestration",
+ ],
+ },
+ {
+ "title": "Built-in features vs. assembly required",
+ "icon": "Settings01Icon",
+ "pros": [
+ "Authentication, ORM, database migrations, real-time sync, background jobs, and file uploads all come out of the box",
+ "No need to evaluate, install, configure, and maintain a dozen separate libraries just to get production essentials",
+ ],
+ "cons": [
+ "FastAPI and Flask give you almost nothing out of the box — no auth, no admin panel, no ORM, no templating",
+ "Django includes more built-in features but its HTML templating is not suited for modern interactive interfaces",
+ ],
+ },
+ {
+ "title": "Development speed",
+ "icon": "ZapIcon",
+ "pros": [
+ "Building with Reflex is roughly 5x faster than assembling the same app from a traditional Python + React stack",
+ "No time spent wiring API endpoints, configuring CORS, setting up build pipelines, or debugging mismatches between frontend and backend",
+ ],
+ "cons": [
+ "Traditional stacks require significant boilerplate just to get a frontend talking to a backend before any real feature work begins",
+ "Every new feature touches both codebases — a backend endpoint, a frontend component, and the API contract between them",
+ ],
+ },
+ {
+ "title": "Modern frontend without JavaScript",
+ "icon": "WebDesign01Icon",
+ "pros": [
+ "Reflex compiles your Python code into a React frontend automatically — you get a modern, interactive UI without writing any JavaScript",
+ "Wrap any existing React component directly from Python when you need something custom",
+ ],
+ "cons": [
+ "Django's built-in templating and Flask's Jinja templating produce static HTML that looks poor out of the box and building anything interactive means bringing in the full JavaScript toolchain",
+ "FastAPI has no frontend or templating at all so you're starting from zero on the UI side",
+ ],
+ },
+ {
+ "title": "Performance and real-time capabilities",
+ "icon": "SquareArrowExpand02Icon",
+ "pros": [
+ "Reflex runs on an async web server with WebSocket sync — real-time updates, live data feeds, and high-concurrency traffic are handled natively",
+ "Compiles down under the hood to a FastAPI backend with a React frontend — the same production architecture, without the assembly cost",
+ ],
+ "cons": [
+ "Flask is synchronous by default and Django's monolithic architecture makes scaling more challenging — neither is natively built for high-concurrency or real-time use cases",
+ "None of the traditional frameworks include built-in real-time capabilities — adding WebSocket support requires additional libraries and infrastructure",
+ ],
+ },
+ {
+ "title": "Scaling and maintainability",
+ "icon": "SourceCodeSquareIcon",
+ "pros": [
+ "Python class-based state model keeps code organized as apps grow in complexity — no scattered API endpoints and disconnected frontend components",
+ "Adding new features means working in one place, not coordinating changes across two separate projects",
+ ],
+ "cons": [
+ "Traditional stacks become harder to maintain as they grow — every change requires coordinating updates across backend endpoints, frontend components, and the API layer between them",
+ "FastAPI's lack of built-in structure means teams must design their own patterns for organizing large applications",
+ ],
+ },
+]
+
+
+def compare():
+ return common_compare(
+ kicker="Compare",
+ heading_lines=[
+ "How You Benefit ",
+ "With Reflex vs. ",
+ "React, Django, FastAPI",
+ ],
+ description="React, Django, and FastAPI each solve part of the stack. Reflex lets you finish. Here's how Reflex compares to the leading Python and JavaScript frameworks.",
+ top_left_title="Reflex",
+ top_right_title="React, Django, FastAPI",
+ comparison_items=COMPARISON_ITEMS,
+ )
+
+
+__all__ = ["compare"]
diff --git a/pcweb/pages/migration/other_frameworks/views/explore.py b/pcweb/pages/migration/other_frameworks/views/explore.py
new file mode 100644
index 000000000..3ae3d65a8
--- /dev/null
+++ b/pcweb/pages/migration/other_frameworks/views/explore.py
@@ -0,0 +1,48 @@
+from pcweb.pages.migration.common.explore import Feature
+from pcweb.pages.migration.common.explore import explore as common_explore
+
+FEATURES: list[Feature] = [
+ {
+ "title": "One language, one codebase",
+ "description": "Build your entire app in pure Python with no context switching. One codebase to maintain, version control, test, and deploy instead of two separate projects.",
+ "icon": "PythonIcon",
+ },
+ {
+ "title": "Built-in features vs. assembly required",
+ "description": "Authentication, ORM, database migrations, real-time sync, background jobs, and file uploads all come out of the box — no need to stitch together a dozen separate libraries.",
+ "icon": "Settings01Icon",
+ },
+ {
+ "title": "Development speed",
+ "description": "Roughly 5x faster than assembling a traditional Python + React stack. No time spent wiring API endpoints, configuring CORS, or debugging frontend-backend mismatches.",
+ "icon": "ZapIcon",
+ },
+ {
+ "title": "Modern frontend without JavaScript",
+ "description": "Reflex compiles your Python into a React frontend automatically. Wrap any existing React component from Python when you need something custom.",
+ "icon": "WebDesign01Icon",
+ },
+ {
+ "title": "Performance and real-time capabilities",
+ "description": "Async web server with WebSocket sync. Real-time updates, live data feeds, and high-concurrency traffic handled natively.",
+ "icon": "SquareArrowExpand02Icon",
+ },
+ {
+ "title": "Scaling and maintainability",
+ "description": "Python class-based state keeps code organized as apps grow. Add new features in one place, not across two separate projects.",
+ "icon": "SourceCodeSquareIcon",
+ },
+]
+
+
+def explore():
+ return common_explore(
+ kicker="Explore",
+ title_prefix="Why Reflex Over ",
+ title_suffix="React, Django, FastAPI",
+ description="React, Django, and FastAPI each solve part of the stack. Reflex lets you finish. One language, full-stack, production-ready from day one.",
+ features=FEATURES,
+ )
+
+
+__all__ = ["explore"]
diff --git a/pcweb/pages/migration/other_frameworks/views/hero.py b/pcweb/pages/migration/other_frameworks/views/hero.py
new file mode 100644
index 000000000..af55b0648
--- /dev/null
+++ b/pcweb/pages/migration/other_frameworks/views/hero.py
@@ -0,0 +1,39 @@
+from pcweb.pages.migration.common.hero import HeroLogo
+from pcweb.pages.migration.common.hero import hero as common_hero
+
+HERO_LOGOS: list[HeroLogo] = [
+ {
+ "image_name": "react.svg",
+ "alt": "React Logo",
+ "class_name": "top-[9.5rem] -ml-[10.5rem]",
+ },
+ {
+ "image_name": "js.svg",
+ "alt": "JavaScript Logo",
+ "class_name": "top-[15rem] ml-[16.5rem]",
+ },
+ {
+ "image_name": "django.svg",
+ "alt": "Django Logo",
+ "class_name": "top-[9.5rem] ml-[10.5rem]",
+ },
+ {
+ "image_name": "fastapi.svg",
+ "alt": "FastAPI Logo",
+ "class_name": "top-[15rem] -ml-[16.5rem]",
+ },
+]
+
+
+def hero():
+ return common_hero(
+ kicker="Move From Other Frameworks to Reflex",
+ title="The Next-Gen Platform Built for Modern Enterprises",
+ subtitle="Escape other framework constraints without sacrificing speed. Build production-grade apps in pure Python with complete control over your stack.",
+ cta_text="Book a Demo",
+ logos=HERO_LOGOS,
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["hero"]
diff --git a/pcweb/pages/migration/other_frameworks/views/quotes.py b/pcweb/pages/migration/other_frameworks/views/quotes.py
new file mode 100644
index 000000000..04ea15888
--- /dev/null
+++ b/pcweb/pages/migration/other_frameworks/views/quotes.py
@@ -0,0 +1,52 @@
+from pcweb.pages.migration.common.quotes import CompanyInfo
+from pcweb.pages.migration.common.quotes import quotes as common_quotes
+
+COMPANIES: list[CompanyInfo] = [
+ {
+ "key": "open_sea",
+ "logo_image_name": "open_sea.svg",
+ "logo_alt": "OpenSea logo",
+ "name": "Alex Atallah",
+ "title": "Co-founder & CEO, OpenSea",
+ "quote": "Have been playing with Reflex since January and realized I should just say, from a fellow YC member: love the architecture decisions you guys are making!",
+ "profile_image": "/landing/social/alex_opensea.webp",
+ },
+ {
+ "key": "fastly",
+ "logo_image_name": "fastly.svg",
+ "logo_alt": "Fastly logo",
+ "name": "Emanuele Bonura",
+ "title": "Senior SOC Engineer",
+ "quote": "Migrating our cybersecurity app from Streamlit to Reflex has been excellent. We quickly built a unified interface connecting BigQuery, Salesforce, and PagerDuty for our 15+ team members. The ease of use and rapid development, supported by your responsive team, made it a great experience.",
+ "profile_image": "",
+ },
+ {
+ "key": "autodesk",
+ "logo_image_name": "autodesk.svg",
+ "logo_alt": "Autodesk logo",
+ "name": "Paolo",
+ "title": "Principal Consultant",
+ "quote": "One person can do the job of two with Reflex, so it cut our cost in half. I am able to wear all the caps at once: Solution Architecture, UI/UX, front-end and back-end.",
+ "profile_image": "",
+ },
+ {
+ "key": "accenture",
+ "logo_image_name": "accenture.svg",
+ "logo_alt": "Accenture logo",
+ "name": "Jordan Lee",
+ "title": "Senior Automation Developer",
+ "quote": "Reflex let us automate workflows that were impossible with previous low-code platforms. We went from prototype to rollout in days, and our team loves writing real Python instead of fighting drag-and-drop UI pain.",
+ "profile_image": "",
+ },
+]
+
+
+def quotes():
+ return common_quotes(
+ companies=COMPANIES,
+ default_active_key="open_sea",
+ logo_base_path="/migration",
+ )
+
+
+__all__ = ["quotes"]
diff --git a/pcweb/views/cta_card.py b/pcweb/views/cta_card.py
index cb6959106..a12bd5bff 100644
--- a/pcweb/views/cta_card.py
+++ b/pcweb/views/cta_card.py
@@ -46,5 +46,5 @@ def cta_card():
loading="lazy",
alt="CTA Card",
),
- class_name="flex flex-row justify-between max-w-(--docs-layout-max-width) mx-auto w-full bg-white/96 dark:bg-m-slate-11 backdrop-blur-[16px] rounded-xl relative overflow-hidden shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_12px_24px_0_rgba(0,0,0,0.08),0_1px_1px_0_rgba(0,0,0,0.01),0_4px_8px_0_rgba(0,0,0,0.03)] dark:shadow-none dark:border dark:border-m-slate-9 pl-16 max-lg:hidden mb-12",
+ class_name="flex flex-row justify-between max-w-(--docs-layout-max-width) mx-auto w-full bg-white/96 dark:bg-m-slate-11 backdrop-blur-[16px] rounded-xl relative overflow-hidden shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_12px_24px_0_rgba(0,0,0,0.08),0_1px_1px_0_rgba(0,0,0,0.01),0_4px_8px_0_rgba(0,0,0,0.03)] dark:shadow-none dark:border dark:border-m-slate-9 pl-16 max-lg:hidden mb-12 mt-24",
)
diff --git a/pcweb/views/marketing_navbar.py b/pcweb/views/marketing_navbar.py
index 77d943ea7..c42591eeb 100644
--- a/pcweb/views/marketing_navbar.py
+++ b/pcweb/views/marketing_navbar.py
@@ -15,6 +15,7 @@
JOBS_BOARD_URL,
REFLEX_BUILD_URL,
)
+from pcweb.pages.about import about_page
from pcweb.pages.blog import blogs
from pcweb.pages.blog.paths import blog_data
from pcweb.pages.customers.landing import customers
@@ -23,6 +24,10 @@
from pcweb.pages.framework.framework import framework
from pcweb.pages.gallery.gallery import gallery
from pcweb.pages.hosting.hosting import hosting_landing
+from pcweb.pages.migration.low_code import low_code_migration_page
+from pcweb.pages.migration.no_code import no_code_migration_page
+from pcweb.pages.migration.other_ai_tools import other_ai_tools_migration_page
+from pcweb.pages.migration.other_frameworks import other_frameworks_migration_page
from pcweb.pages.use_cases.consulting import consulting_use_case_page
from pcweb.pages.use_cases.finance import finance_use_case_page
from pcweb.pages.use_cases.government import government_use_case_page
@@ -379,16 +384,25 @@ def solutions_content() -> rx.Component:
solutions_column(
"Migration",
[
- ("Switch from No Code", "WebDesign01Icon", use_cases_page.path),
+ (
+ "Switch from No Code",
+ "WebDesign01Icon",
+ no_code_migration_page.path,
+ ),
+ (
+ "Switch from Low Code",
+ "SourceCodeSquareIcon",
+ low_code_migration_page.path,
+ ),
(
"Switch from Other Frameworks",
"CodeIcon",
- use_cases_page.path,
+ other_frameworks_migration_page.path,
),
(
"Switch from Other AI tools",
"ArtificialIntelligence04Icon",
- use_cases_page.path,
+ other_ai_tools_migration_page.path,
),
],
),
@@ -434,7 +448,7 @@ def about_content() -> rx.Component:
return menu_content(
rx.el.div(
rx.el.div(
- solutions_item("Company", "Profile02Icon", "/about"),
+ solutions_item("Company", "Profile02Icon", about_page.path),
solutions_item("Careers", "WorkIcon", JOBS_BOARD_URL),
class_name="p-4 flex flex-col rounded-xl bg-white-1 h-full dark:shadow-none dark:border dark:border-m-slate-9 dark:bg-m-slate-11 shadow-card",
),