From a46ebb29d11c5fd2317c8526b85c3f6555251d2b Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 23 Feb 2026 11:31:15 +0100 Subject: [PATCH 01/10] ENG-8877: Low code page --- assets/common/dark/grid.svg | 1 + assets/common/light/grid.svg | 1 + assets/logos/dark/gradient_r.svg | 1 + assets/logos/light/gradient_r.svg | 1 + assets/migration/dark/accenture.svg | 1 + assets/migration/dark/autodesk.svg | 1 + assets/migration/dark/fastly.svg | 1 + assets/migration/dark/open_sea.svg | 1 + assets/migration/dark/plotly.svg | 23 +++ assets/migration/dark/powerbi.svg | 9 + assets/migration/dark/retool.svg | 3 + assets/migration/dark/streamlit.svg | 12 ++ assets/migration/light/accenture.svg | 1 + assets/migration/light/autodesk.svg | 1 + assets/migration/light/fastly.svg | 1 + assets/migration/light/open_sea.svg | 1 + assets/migration/light/plotly.svg | 23 +++ assets/migration/light/powerbi.svg | 9 + assets/migration/light/retool.svg | 3 + assets/migration/light/streamlit.svg | 12 ++ pcweb/pages/__init__.py | 1 + pcweb/pages/hosting/hosting.py | 2 - pcweb/pages/migration/low_code/__init__.py | 44 ++++ .../migration/low_code/views/__init__.py | 5 + .../pages/migration/low_code/views/compare.py | 188 ++++++++++++++++++ pcweb/pages/migration/low_code/views/hero.py | 104 ++++++++++ .../pages/migration/low_code/views/quotes.py | 140 +++++++++++++ pcweb/views/marketing_navbar.py | 6 +- 28 files changed, 593 insertions(+), 3 deletions(-) create mode 100644 assets/common/dark/grid.svg create mode 100644 assets/common/light/grid.svg create mode 100644 assets/logos/dark/gradient_r.svg create mode 100644 assets/logos/light/gradient_r.svg create mode 100644 assets/migration/dark/accenture.svg create mode 100644 assets/migration/dark/autodesk.svg create mode 100644 assets/migration/dark/fastly.svg create mode 100644 assets/migration/dark/open_sea.svg create mode 100644 assets/migration/dark/plotly.svg create mode 100644 assets/migration/dark/powerbi.svg create mode 100644 assets/migration/dark/retool.svg create mode 100644 assets/migration/dark/streamlit.svg create mode 100644 assets/migration/light/accenture.svg create mode 100644 assets/migration/light/autodesk.svg create mode 100644 assets/migration/light/fastly.svg create mode 100644 assets/migration/light/open_sea.svg create mode 100644 assets/migration/light/plotly.svg create mode 100644 assets/migration/light/powerbi.svg create mode 100644 assets/migration/light/retool.svg create mode 100644 assets/migration/light/streamlit.svg create mode 100644 pcweb/pages/migration/low_code/__init__.py create mode 100644 pcweb/pages/migration/low_code/views/__init__.py create mode 100644 pcweb/pages/migration/low_code/views/compare.py create mode 100644 pcweb/pages/migration/low_code/views/hero.py create mode 100644 pcweb/pages/migration/low_code/views/quotes.py 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..4ece52782 --- /dev/null +++ b/assets/logos/dark/gradient_r.svg @@ -0,0 +1 @@ + \ 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..4ece52782 --- /dev/null +++ b/assets/logos/light/gradient_r.svg @@ -0,0 +1 @@ + \ 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/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/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..9433ff6e8 --- /dev/null +++ b/assets/migration/dark/powerbi.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ 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/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/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/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..9433ff6e8 --- /dev/null +++ b/assets/migration/light/powerbi.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ 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/pcweb/pages/__init__.py b/pcweb/pages/__init__.py index 15c76d619..6a4d58872 100644 --- a/pcweb/pages/__init__.py +++ b/pcweb/pages/__init__.py @@ -20,6 +20,7 @@ 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 .page404 import page404 as page404 from .pricing.pricing import pricing as pricing from .sales import sales as sales 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/low_code/__init__.py b/pcweb/pages/migration/low_code/__init__.py new file mode 100644 index 000000000..60a67bb14 --- /dev/null +++ b/pcweb/pages/migration/low_code/__init__.py @@ -0,0 +1,44 @@ +import reflex as rx +import reflex_ui as ui + +from pcweb.components.hosting_banner import HostingBannerState +from pcweb.meta.meta import create_meta_tags +from pcweb.pages.about.views.divider import divider +from pcweb.pages.framework.views.footer_index import footer_index +from pcweb.pages.migration.low_code.views import compare, hero, quotes +from pcweb.views.marketing_navbar import marketing_navbar + + +@rx.page( + route="/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", + image="/previews/low_code_migration_preview.webp", + ), +) +def low_code_migration_page() -> rx.Component: + return rx.el.div( + marketing_navbar(), + rx.el.main( + rx.el.div( + hero(), + quotes(), + divider(), + compare(), + divider(), + footer_index(), + 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", + ), + class_name=ui.cn( + "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", + rx.cond( + HostingBannerState.is_banner_visible, + "lg:pt-[7rem] pt-[3.5rem]", + "lg:pt-[4.5rem] pt-[3.5rem]", + ), + ), + ) 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..7ad7dc9ad --- /dev/null +++ b/pcweb/pages/migration/low_code/views/__init__.py @@ -0,0 +1,5 @@ +from .compare import compare +from .hero import hero +from .quotes import quotes + +__all__ = ["compare", "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..9f3125181 --- /dev/null +++ b/pcweb/pages/migration/low_code/views/compare.py @@ -0,0 +1,188 @@ +import reflex as rx +import reflex_ui as ui + + +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", + ), + 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-center 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 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", + ), + 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-center 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-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-12 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t", + ) + + +def comparison_cards() -> rx.Component: + return rx.el.div( + rx.el.div( + top_title("Reflex"), + top_title("Bubble, Retool, Webflow, etc."), + class_name="grid grid-cols-2", + ), + comparison_title("Full Control Without the Ceiling", "CodesandboxIcon"), + pros_cons_cards( + [ + "Full control over your code", + "No limits on complexity", + "Customizable templates", + ], + [ + "Limited control over your code", + "No limits on complexity", + "Customizable templates", + ], + ), + comparison_title("Your own code", "SourceCodeSquareIcon"), + pros_cons_cards( + [ + "Full control over your code", + "No limits on complexity", + "Customizable templates", + ], + [ + "Limited control over your code", + "No limits on complexity", + "Customizable templates", + ], + ), + comparison_title("Python Ecosystem Access", "PythonIcon"), + pros_cons_cards( + [ + "Full control over your code", + "No limits on complexity", + "Customizable templates", + ], + [ + "Limited control over your code", + "No limits on complexity", + "Customizable templates", + ], + ), + comparison_title("Scales With Complexity", "SquareArrowExpand02Icon"), + pros_cons_cards( + [ + "Full control over your code", + "No limits on complexity", + "Customizable templates", + ], + [ + "Limited control over your code", + "No limits on complexity", + "Customizable templates", + ], + ), + comparison_title( + "Team Collaboration & Engineering Practices", "UserSwitchIcon" + ), + pros_cons_cards( + [ + "Full control over your code", + "No limits on complexity", + "Customizable templates", + ], + [ + "Limited control over your code", + "No limits on complexity", + "Customizable templates", + ], + ), + 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-10 mt-18 border-b mb-24 relative", + ) + + +def compare() -> rx.Component: + return rx.el.section( + rx.el.div( + rx.el.div( + rx.el.p( + "Compare", + class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-m-slate-6", + ), + rx.el.h1( + "How You Benefit ", + rx.el.br(class_name="max-lg:hidden"), + " With Reflex to ", + rx.el.br(class_name="max-lg:hidden"), + " Other Approaches", + class_name="text-m-slate-12 dark:text-m-slate-3 text-3xl font-[575]", + ), + rx.el.h2( + "Reflex is growing-and we're looking for people who care deeply about developer experience, clean abstractions, and shipping things that matter.", + 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:top-[11rem] lg:self-start max-lg:self-center max-lg:items-center max-lg:text-center", + ), + comparison_cards(), + class_name="flex lg:flex-row flex-col max-lg:gap-6 max-w-(--docs-layout-max-width) mx-auto relative py-24 max-lg:px-6", + ), + 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 relative", + ) 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..0f03410a4 --- /dev/null +++ b/pcweb/pages/migration/low_code/views/hero.py @@ -0,0 +1,104 @@ +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 + + +def floating_logo(src: str, alt: str, class_name: str = "") -> rx.Component: + return rx.el.div( + rx.image( + src=src, + alt=alt, + loading="eager", + custom_attrs={"fetchPriority": "high"}, + ), + class_name=ui.cn( + 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 rounded-[1rem] bg-gradient-to-b from-m-slate-2 to-white-1 dark:from-m-slate-11 dark:to-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 absolute left-1/2 -translate-x-1/2 -translate-y-1/2 z-[1] pointer-events-none top-[13.5rem]", + ) + + +def hero() -> 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-[2.815rem]", + ), + ), + floating_logo( + src=f"/migration/{rx.color_mode_cond('light', 'dark')}/plotly.svg", + alt="Plotly Logo", + class_name="top-[9.5rem] -ml-[10.5rem]", + ), + floating_logo( + src=f"/migration/{rx.color_mode_cond('light', 'dark')}/powerbi.svg", + alt="Power BI Logo", + class_name="top-[15rem] ml-[16.5rem]", + ), + floating_logo( + src=f"/migration/{rx.color_mode_cond('light', 'dark')}/retool.svg", + alt="Retool Logo", + class_name="top-[9.5rem] ml-[10.5rem]", + ), + floating_logo( + src=f"/migration/{rx.color_mode_cond('light', 'dark')}/streamlit.svg", + alt="Streamlit Logo", + class_name="top-[15rem] -ml-[16.5rem]", + ), + gradient_logo(), + class_name="max-lg:hidden", + ), + rx.el.p( + "Move From Low Code to Reflex", + class_name="text-sm font-[525] text-primary-10 dark:text-m-slate-6", + ), + rx.el.h1( + "The Next-Gen Platform Built for Modern Enterprises", + class_name="text-m-slate-12 dark:text-m-slate-3 lg:text-5xl text-3xl font-[575]", + ), + rx.el.h2( + "Escape low-code constraints without sacrificing speed. Build production-grade apps in pure Python with complete control over your stack.", + class_name="text-m-slate-7 dark:text-m-slate-6 text-base font-[475]", + ), + demo_form_dialog( + trigger=button( + "Book a Demo", + 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/low_code/views/quotes.py b/pcweb/pages/migration/low_code/views/quotes.py new file mode 100644 index 000000000..e0e18e90a --- /dev/null +++ b/pcweb/pages/migration/low_code/views/quotes.py @@ -0,0 +1,140 @@ +from enum import StrEnum +from typing import TypedDict + +import reflex as rx +import reflex_ui as ui +from reflex.experimental import ClientStateVar + + +class Companies(StrEnum): + OPEN_SEA = "open_sea" + FASTLY = "fastly" + AUTODESK = "autodesk" + ACCENTURE = "accenture" + + +class CompanyInfo(TypedDict): + name: str + title: str + quote: str + + +COMPANIES_INFO: dict[Companies, CompanyInfo] = { + Companies.OPEN_SEA: { + "name": "Alex Atallah", + "title": "Co-founder & CEO, OpenSea", + "image": "/landing/social/alex_opensea.webp", + "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!", + }, + Companies.FASTLY: { + "name": "Alex Atallah", + "title": "Co-founder & CEO, OpenSea", + "image": "/landing/social/alex_opensea.webp", + "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!", + }, + Companies.AUTODESK: { + "name": "Alex Atallah", + "title": "Co-founder & CEO, OpenSea", + "image": "/landing/social/alex_opensea.webp", + "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!", + }, + Companies.ACCENTURE: { + "name": "Alex Atallah", + "title": "Co-founder & CEO, OpenSea", + "image": "/landing/social/alex_opensea.webp", + "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!", + }, +} + + +active_company_cs = ClientStateVar.create( + "active_company_cs", default=Companies.OPEN_SEA +) + + +def company_card(company: Companies) -> rx.Component: + return rx.el.button( + rx.image( + src=f"/migration/{rx.color_mode_cond('light', 'dark')}/{company}.svg", + alt=f"{company} logo", + loading="lazy", + class_name=ui.cn( + "transition-[filter] group-hover:brightness-0 dark:group-hover:brightness-[10]", + rx.cond( + active_company_cs.value == company, + "brightness-0 dark:brightness-[10]", + "", + ), + ), + ), + aria_label=f"Company: {company}", + on_click=active_company_cs.set_value(company), + 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, + "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: Companies) -> rx.Component: + return rx.el.div( + rx.el.p( + COMPANIES_INFO[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=COMPANIES_INFO[company]["name"], + class_name="size-6 rounded-full", + ) + if not COMPANIES_INFO[company]["image"] + else rx.image( + src=COMPANIES_INFO[company]["image"], + loading="lazy", + alt=f"{company} logo", + class_name="size-6 rounded-full", + ), + rx.el.span( + COMPANIES_INFO[company]["name"], + class_name="text-m-slate-12 dark:text-m-slate-3 text-sm font-[525]", + ), + rx.el.span( + COMPANIES_INFO[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() -> rx.Component: + return rx.el.div( + company_card(Companies.OPEN_SEA), + company_card(Companies.FASTLY), + company_card(Companies.AUTODESK), + company_card(Companies.ACCENTURE), + 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() -> rx.Component: + return rx.el.section( + companies_column(), + rx.match( + active_company_cs.value, + (Companies.OPEN_SEA, quote_card(Companies.OPEN_SEA)), + (Companies.FASTLY, quote_card(Companies.FASTLY)), + (Companies.AUTODESK, quote_card(Companies.AUTODESK)), + (Companies.ACCENTURE, quote_card(Companies.ACCENTURE)), + quote_card(Companies.OPEN_SEA), + ), + class_name="flex lg:flex-row flex-col pb-24", + ) diff --git a/pcweb/views/marketing_navbar.py b/pcweb/views/marketing_navbar.py index 017784f63..8d56d738a 100644 --- a/pcweb/views/marketing_navbar.py +++ b/pcweb/views/marketing_navbar.py @@ -379,7 +379,11 @@ def solutions_content() -> rx.Component: solutions_column( "Migration", [ - ("Switch from No Code", "WebDesign01Icon", use_cases_page.path), + ( + "Switch from No Code", + "WebDesign01Icon", + "/migration/low-code", + ), ( "Switch from Other Frameworks", "CodeIcon", From 5279df5d79428f01c9a61995698cc92f83d44de4 Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 23 Feb 2026 11:37:33 +0100 Subject: [PATCH 02/10] add image --- pcweb/pages/migration/low_code/views/quotes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pcweb/pages/migration/low_code/views/quotes.py b/pcweb/pages/migration/low_code/views/quotes.py index e0e18e90a..ed7d471d2 100644 --- a/pcweb/pages/migration/low_code/views/quotes.py +++ b/pcweb/pages/migration/low_code/views/quotes.py @@ -17,6 +17,7 @@ class CompanyInfo(TypedDict): name: str title: str quote: str + image: str COMPANIES_INFO: dict[Companies, CompanyInfo] = { From 61fb6b4038afec6757cb16d6c471fd50f79e3799 Mon Sep 17 00:00:00 2001 From: Carlos Date: Tue, 24 Feb 2026 11:33:41 +0100 Subject: [PATCH 03/10] updates --- .../pages/migration/low_code/views/compare.py | 80 +++++++++---------- .../pages/migration/low_code/views/quotes.py | 24 +++--- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/pcweb/pages/migration/low_code/views/compare.py b/pcweb/pages/migration/low_code/views/compare.py index 9f3125181..c5c4e7caf 100644 --- a/pcweb/pages/migration/low_code/views/compare.py +++ b/pcweb/pages/migration/low_code/views/compare.py @@ -19,13 +19,13 @@ def pros_card(pros: list[str]) -> rx.Component: rx.el.li( ui.icon( "Tick02Icon", - class_name="shrink-0 text-primary-9 dark:text-primary-10", + 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-center gap-2.5", + class_name="flex flex-row items-start gap-2.5", ) for pro in pros ], @@ -40,13 +40,13 @@ def cons_card(cons: list[str]) -> rx.Component: ui.icon( "MultiplicationSignIcon", stroke_width=1.5, - class_name="shrink-0 text-m-slate-7 dark:text-m-slate-6", + 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-center gap-2.5", + class_name="flex flex-row items-start gap-2.5", ) for con in cons ], @@ -65,7 +65,7 @@ def pros_cons_cards(pros: list[str], cons: list[str]) -> rx.Component: 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-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-12 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t", + class_name="text-m-slate-12 dark:text-m-slate-3 text-xs leading-[1.5rem] font-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-8 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t", ) @@ -73,59 +73,59 @@ def comparison_cards() -> rx.Component: return rx.el.div( rx.el.div( top_title("Reflex"), - top_title("Bubble, Retool, Webflow, etc."), + top_title("Retool, Streamlit, Plotly Dash, Power BI"), class_name="grid grid-cols-2", ), comparison_title("Full Control Without the Ceiling", "CodesandboxIcon"), pros_cons_cards( [ - "Full control over your code", - "No limits on complexity", - "Customizable templates", + "Write real Python — no ceiling on what you can build", + "Handle custom logic, complex data flows, and performance optimization natively", + "Build anything a full-stack app can do", ], [ - "Limited control over your code", - "No limits on complexity", - "Customizable templates", + "Get you to v1 fast, then you hit walls", + "Custom logic and complex data flows require ugly workarounds", + "Platform limitations dictate what's possible, not your requirements", ], ), - comparison_title("Your own code", "SourceCodeSquareIcon"), + comparison_title("You Own Your Code", "SourceCodeSquareIcon"), pros_cons_cards( [ - "Full control over your code", - "No limits on complexity", - "Customizable templates", + "It's your Python code — deploy it anywhere", + "Full version control with Git", + "Never hostage to a platform's pricing or shutdown", ], [ - "Limited control over your code", - "No limits on complexity", - "Customizable templates", + "Your app lives on their infrastructure in their proprietary format", + "Vendor lock-in makes migration painful or impossible", + "Pricing changes or platform shutdowns put your app at risk", ], ), comparison_title("Python Ecosystem Access", "PythonIcon"), pros_cons_cards( [ - "Full control over your code", - "No limits on complexity", - "Customizable templates", + "Use libraries you already know — pandas, scikit-learn, whatever", + "Build internal tools or customer-facing apps in one language", + "Leverage the entire Python ecosystem with no restrictions", ], [ - "Limited control over your code", - "No limits on complexity", - "Customizable templates", + "Limited to the platform's pre-built integrations", + "Can't tap into Python's ML, data science, or backend libraries", + "Forces non-JS developers to learn new tools or work around limitations", ], ), comparison_title("Scales With Complexity", "SquareArrowExpand02Icon"), pros_cons_cards( [ - "Full control over your code", - "No limits on complexity", - "Customizable templates", + "Auth flows, real-time features, complex state management — all native", + "Handles growing complexity because it's just code", + "No artificial boundaries on what you can build", ], [ - "Limited control over your code", - "No limits on complexity", - "Customizable templates", + "Great for simple CRUD apps and dashboards, then it breaks down", + "Once you need real complexity, you're fighting the tool instead of building", + "Workarounds pile up and become unmaintainable", ], ), comparison_title( @@ -133,14 +133,14 @@ def comparison_cards() -> rx.Component: ), pros_cons_cards( [ - "Full control over your code", - "No limits on complexity", - "Customizable templates", + "Fits into normal engineering workflows — Git, PRs, CI/CD", + "Code review and automated testing work out of the box", + "Your whole team can collaborate using standard dev practices", ], [ - "Limited control over your code", - "No limits on complexity", - "Customizable templates", + "Version control is difficult or impossible", + "Code review and testing are afterthoughts at best", + "Engineering best practices don't apply to proprietary drag-and-drop formats", ], ), rx.el.div( @@ -170,13 +170,13 @@ def compare() -> rx.Component: rx.el.h1( "How You Benefit ", rx.el.br(class_name="max-lg:hidden"), - " With Reflex to ", + "With Reflex vs. ", rx.el.br(class_name="max-lg:hidden"), - " Other Approaches", + "Other Approaches", class_name="text-m-slate-12 dark:text-m-slate-3 text-3xl font-[575]", ), rx.el.h2( - "Reflex is growing-and we're looking for people who care deeply about developer experience, clean abstractions, and shipping things that matter.", + "No-code tools get you started fast, but Reflex lets you finish. Here's how Reflex compares to platforms like Retool, Streamlit, Plotly Dash, and Power BI.", 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:top-[11rem] lg:self-start max-lg:self-center max-lg:items-center max-lg:text-center", diff --git a/pcweb/pages/migration/low_code/views/quotes.py b/pcweb/pages/migration/low_code/views/quotes.py index ed7d471d2..d6aa17bc5 100644 --- a/pcweb/pages/migration/low_code/views/quotes.py +++ b/pcweb/pages/migration/low_code/views/quotes.py @@ -28,22 +28,22 @@ class CompanyInfo(TypedDict): "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!", }, Companies.FASTLY: { - "name": "Alex Atallah", - "title": "Co-founder & CEO, OpenSea", - "image": "/landing/social/alex_opensea.webp", - "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!", + "name": "Emanuele Bonura", + "title": "Senior SOC Engineer", + "image": "", + "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.", }, Companies.AUTODESK: { - "name": "Alex Atallah", - "title": "Co-founder & CEO, OpenSea", - "image": "/landing/social/alex_opensea.webp", - "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!", + "name": "Paolo", + "title": "Principal Consultant", + "image": "", + "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.", }, Companies.ACCENTURE: { - "name": "Alex Atallah", - "title": "Co-founder & CEO, OpenSea", - "image": "/landing/social/alex_opensea.webp", - "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!", + "name": "Jordan Lee", + "title": "Senior Automation Developer", + "image": "", + "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.", }, } From e1ab6fb4c7baf7e0c166c16061b91ddfffd61030 Mon Sep 17 00:00:00 2001 From: carlosabadia Date: Thu, 26 Feb 2026 13:39:49 +0100 Subject: [PATCH 04/10] updates --- assets/migration/dark/chatgpt.svg | 1 + assets/migration/dark/claude.svg | 1 + assets/migration/dark/django.svg | 1 + assets/migration/dark/fastapi.svg | 1 + assets/migration/dark/js.svg | 1 + assets/migration/dark/powerbi.svg | 10 +- assets/migration/dark/react.svg | 1 + assets/migration/dark/replit.svg | 1 + assets/migration/light/chatgpt.svg | 1 + assets/migration/light/claude.svg | 1 + assets/migration/light/django.svg | 1 + assets/migration/light/fastapi.svg | 1 + assets/migration/light/js.svg | 1 + assets/migration/light/powerbi.svg | 10 +- assets/migration/light/react.svg | 1 + assets/migration/light/replit.svg | 1 + pcweb/pages/migration/low_code/__init__.py | 4 +- .../migration/low_code/views/__init__.py | 3 +- .../pages/migration/low_code/views/explore.py | 101 ++++++++++++++++++ 19 files changed, 122 insertions(+), 20 deletions(-) create mode 100644 assets/migration/dark/chatgpt.svg create mode 100644 assets/migration/dark/claude.svg create mode 100644 assets/migration/dark/django.svg create mode 100644 assets/migration/dark/fastapi.svg create mode 100644 assets/migration/dark/js.svg create mode 100644 assets/migration/dark/react.svg create mode 100644 assets/migration/dark/replit.svg create mode 100644 assets/migration/light/chatgpt.svg create mode 100644 assets/migration/light/claude.svg create mode 100644 assets/migration/light/django.svg create mode 100644 assets/migration/light/fastapi.svg create mode 100644 assets/migration/light/js.svg create mode 100644 assets/migration/light/react.svg create mode 100644 assets/migration/light/replit.svg create mode 100644 pcweb/pages/migration/low_code/views/explore.py diff --git a/assets/migration/dark/chatgpt.svg b/assets/migration/dark/chatgpt.svg new file mode 100644 index 000000000..4268c44de --- /dev/null +++ b/assets/migration/dark/chatgpt.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/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/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/powerbi.svg b/assets/migration/dark/powerbi.svg index 9433ff6e8..469973a41 100644 --- a/assets/migration/dark/powerbi.svg +++ b/assets/migration/dark/powerbi.svg @@ -1,9 +1 @@ - - - - - - - - - \ No newline at end of file + \ 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..cc76ee631 --- /dev/null +++ b/assets/migration/dark/replit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/migration/light/chatgpt.svg b/assets/migration/light/chatgpt.svg new file mode 100644 index 000000000..4268c44de --- /dev/null +++ b/assets/migration/light/chatgpt.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/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/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/powerbi.svg b/assets/migration/light/powerbi.svg index 9433ff6e8..469973a41 100644 --- a/assets/migration/light/powerbi.svg +++ b/assets/migration/light/powerbi.svg @@ -1,9 +1 @@ - - - - - - - - - \ No newline at end of file + \ 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..cc76ee631 --- /dev/null +++ b/assets/migration/light/replit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pcweb/pages/migration/low_code/__init__.py b/pcweb/pages/migration/low_code/__init__.py index 60a67bb14..1e549fb39 100644 --- a/pcweb/pages/migration/low_code/__init__.py +++ b/pcweb/pages/migration/low_code/__init__.py @@ -5,7 +5,7 @@ from pcweb.meta.meta import create_meta_tags from pcweb.pages.about.views.divider import divider from pcweb.pages.framework.views.footer_index import footer_index -from pcweb.pages.migration.low_code.views import compare, hero, quotes +from pcweb.pages.migration.low_code.views import compare, explore, hero, quotes from pcweb.views.marketing_navbar import marketing_navbar @@ -28,6 +28,8 @@ def low_code_migration_page() -> rx.Component: divider(), compare(), divider(), + explore(), + divider(), footer_index(), class_name="flex flex-col relative justify-center items-center w-full", ), diff --git a/pcweb/pages/migration/low_code/views/__init__.py b/pcweb/pages/migration/low_code/views/__init__.py index 7ad7dc9ad..f76295d0f 100644 --- a/pcweb/pages/migration/low_code/views/__init__.py +++ b/pcweb/pages/migration/low_code/views/__init__.py @@ -1,5 +1,6 @@ from .compare import compare +from .explore import explore from .hero import hero from .quotes import quotes -__all__ = ["compare", "hero", "quotes"] +__all__ = ["compare", "explore", "hero", "quotes"] 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..8bbe32d28 --- /dev/null +++ b/pcweb/pages/migration/low_code/views/explore.py @@ -0,0 +1,101 @@ +from typing import TypedDict + +import reflex as rx +import reflex_ui as ui + + +class Feature(TypedDict): + title: str + description: str + icon: str + + +FEATURES: list[Feature] = [ + { + "title": "AI-Powered Development", + "description": "Build your app with the speed of AI and precision of Python", + "icon": "ArtificialIntelligence04Icon", + }, + { + "title": "Python-Powered Development", + "description": "Build your app with the speed of AI and precision of Python", + "icon": "RepeatIcon", + }, + { + "title": "Python-Powered Development", + "description": "Build your app with the speed of AI and precision of Python", + "icon": "FlowConnectionIcon", + }, + { + "title": "Python-Powered Development", + "description": "Build your app with the speed of AI and precision of Python", + "icon": "Layers01Icon", + }, + { + "title": "Python-Powered Development", + "description": "Build your app with the speed of AI and precision of Python", + "icon": "Layers01Icon", + }, + { + "title": "Python-Powered Development", + "description": "Build your app with the speed of AI and precision of Python", + "icon": "Layers01Icon", + }, +] + + +def feature_card(feature: Feature) -> rx.Component: + return rx.el.div( + rx.el.div( + ui.icon( + feature["icon"], class_name="text-primary-10 dark:text-primary-9 size-5" + ), + 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() -> 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() -> rx.Component: + return rx.el.section( + rx.el.div( + rx.el.div( + rx.el.p( + "Explore", + class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-m-slate-6", + ), + rx.el.div( + rx.el.h1( + "Build Your App With the Speed of ", + rx.el.br(), + "AI and Precision of Python", + class_name="text-m-slate-12 dark:text-m-slate-3 lg:text-4xl text-3xl font-[575] shrink-0", + ), + rx.el.p( + "Reflex is growing—and we’re looking for people who care deeply about developer experience, clean abstractions.", + 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:py-24 py-16", + ), + feature_grid(), + 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", + ) From 69a89927a570dd482480ee7b1131a1c7be013927 Mon Sep 17 00:00:00 2001 From: carlosabadia Date: Thu, 26 Feb 2026 18:12:29 +0100 Subject: [PATCH 05/10] template --- pcweb/pages/migration/common/compare.py | 154 +++++++++++ pcweb/pages/migration/common/explore.py | 74 +++++ pcweb/pages/migration/common/hero.py | 101 +++++++ pcweb/pages/migration/common/quotes.py | 113 ++++++++ .../pages/migration/low_code/views/compare.py | 261 ++++++------------ .../pages/migration/low_code/views/explore.py | 107 ++----- pcweb/pages/migration/low_code/views/hero.py | 131 +++------ .../pages/migration/low_code/views/quotes.py | 151 +++------- 8 files changed, 614 insertions(+), 478 deletions(-) create mode 100644 pcweb/pages/migration/common/compare.py create mode 100644 pcweb/pages/migration/common/explore.py create mode 100644 pcweb/pages/migration/common/hero.py create mode 100644 pcweb/pages/migration/common/quotes.py diff --git a/pcweb/pages/migration/common/compare.py b/pcweb/pages/migration/common/compare.py new file mode 100644 index 000000000..cf4bb8177 --- /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 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-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-8 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t", + ) + + +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-10 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-m-slate-6", + ), + 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:top-[11rem] 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 py-24 max-lg:px-6", + ), + 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 relative", + ) diff --git a/pcweb/pages/migration/common/explore.py b/pcweb/pages/migration/common/explore.py new file mode 100644 index 000000000..716e81b62 --- /dev/null +++ b/pcweb/pages/migration/common/explore.py @@ -0,0 +1,74 @@ +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"], class_name="text-primary-10 dark:text-primary-9 size-5" + ), + 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-m-slate-6", + ), + 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:py-24 py-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..117f33f09 --- /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 rounded-[1rem] bg-gradient-to-b from-m-slate-2 to-white-1 dark:from-m-slate-11 dark:to-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 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..a59876981 --- /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", + ) diff --git a/pcweb/pages/migration/low_code/views/compare.py b/pcweb/pages/migration/low_code/views/compare.py index c5c4e7caf..74fef35eb 100644 --- a/pcweb/pages/migration/low_code/views/compare.py +++ b/pcweb/pages/migration/low_code/views/compare.py @@ -1,188 +1,89 @@ -import reflex as rx -import reflex_ui as ui +from pcweb.pages.migration.common.compare import ComparisonItem +from pcweb.pages.migration.common.compare import compare as common_compare - -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 +COMPARISON_ITEMS: list[ComparisonItem] = [ + { + "title": "Full Control Without the Ceiling", + "icon": "CodesandboxIcon", + "pros": [ + "Write real Python — no ceiling on what you can build", + "Handle custom logic, complex data flows, and performance optimization natively", + "Build anything a full-stack app can do", ], - 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 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 + "cons": [ + "Get you to v1 fast, then you hit walls", + "Custom logic and complex data flows require ugly workarounds", + "Platform limitations dictate what's possible, not your requirements", ], - 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-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-8 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t", - ) + }, + { + "title": "You Own Your Code", + "icon": "SourceCodeSquareIcon", + "pros": [ + "It's your Python code — deploy it anywhere", + "Full version control with Git", + "Never hostage to a platform's pricing or shutdown", + ], + "cons": [ + "Your app lives on their infrastructure in their proprietary format", + "Vendor lock-in makes migration painful or impossible", + "Pricing changes or platform shutdowns put your app at risk", + ], + }, + { + "title": "Python Ecosystem Access", + "icon": "PythonIcon", + "pros": [ + "Use libraries you already know — pandas, scikit-learn, whatever", + "Build internal tools or customer-facing apps in one language", + "Leverage the entire Python ecosystem with no restrictions", + ], + "cons": [ + "Limited to the platform's pre-built integrations", + "Can't tap into Python's ML, data science, or backend libraries", + "Forces non-JS developers to learn new tools or work around limitations", + ], + }, + { + "title": "Scales With Complexity", + "icon": "SquareArrowExpand02Icon", + "pros": [ + "Auth flows, real-time features, complex state management — all native", + "Handles growing complexity because it's just code", + "No artificial boundaries on what you can build", + ], + "cons": [ + "Great for simple CRUD apps and dashboards, then it breaks down", + "Once you need real complexity, you're fighting the tool instead of building", + "Workarounds pile up and become unmaintainable", + ], + }, + { + "title": "Team Collaboration & Engineering Practices", + "icon": "UserSwitchIcon", + "pros": [ + "Fits into normal engineering workflows — Git, PRs, CI/CD", + "Code review and automated testing work out of the box", + "Your whole team can collaborate using standard dev practices", + ], + "cons": [ + "Version control is difficult or impossible", + "Code review and testing are afterthoughts at best", + "Engineering best practices don't apply to proprietary drag-and-drop formats", + ], + }, +] -def comparison_cards() -> rx.Component: - return rx.el.div( - rx.el.div( - top_title("Reflex"), - top_title("Retool, Streamlit, Plotly Dash, Power BI"), - class_name="grid grid-cols-2", - ), - comparison_title("Full Control Without the Ceiling", "CodesandboxIcon"), - pros_cons_cards( - [ - "Write real Python — no ceiling on what you can build", - "Handle custom logic, complex data flows, and performance optimization natively", - "Build anything a full-stack app can do", - ], - [ - "Get you to v1 fast, then you hit walls", - "Custom logic and complex data flows require ugly workarounds", - "Platform limitations dictate what's possible, not your requirements", - ], - ), - comparison_title("You Own Your Code", "SourceCodeSquareIcon"), - pros_cons_cards( - [ - "It's your Python code — deploy it anywhere", - "Full version control with Git", - "Never hostage to a platform's pricing or shutdown", - ], - [ - "Your app lives on their infrastructure in their proprietary format", - "Vendor lock-in makes migration painful or impossible", - "Pricing changes or platform shutdowns put your app at risk", - ], - ), - comparison_title("Python Ecosystem Access", "PythonIcon"), - pros_cons_cards( - [ - "Use libraries you already know — pandas, scikit-learn, whatever", - "Build internal tools or customer-facing apps in one language", - "Leverage the entire Python ecosystem with no restrictions", - ], - [ - "Limited to the platform's pre-built integrations", - "Can't tap into Python's ML, data science, or backend libraries", - "Forces non-JS developers to learn new tools or work around limitations", - ], - ), - comparison_title("Scales With Complexity", "SquareArrowExpand02Icon"), - pros_cons_cards( - [ - "Auth flows, real-time features, complex state management — all native", - "Handles growing complexity because it's just code", - "No artificial boundaries on what you can build", - ], - [ - "Great for simple CRUD apps and dashboards, then it breaks down", - "Once you need real complexity, you're fighting the tool instead of building", - "Workarounds pile up and become unmaintainable", - ], - ), - comparison_title( - "Team Collaboration & Engineering Practices", "UserSwitchIcon" - ), - pros_cons_cards( - [ - "Fits into normal engineering workflows — Git, PRs, CI/CD", - "Code review and automated testing work out of the box", - "Your whole team can collaborate using standard dev practices", - ], - [ - "Version control is difficult or impossible", - "Code review and testing are afterthoughts at best", - "Engineering best practices don't apply to proprietary drag-and-drop formats", - ], - ), - 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-10 mt-18 border-b mb-24 relative", +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 Retool, Streamlit, Plotly Dash, and Power BI.", + top_left_title="Reflex", + top_right_title="Retool, Streamlit, Plotly Dash, Power BI", + comparison_items=COMPARISON_ITEMS, ) -def compare() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - rx.el.p( - "Compare", - class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-m-slate-6", - ), - rx.el.h1( - "How You Benefit ", - rx.el.br(class_name="max-lg:hidden"), - "With Reflex vs. ", - rx.el.br(class_name="max-lg:hidden"), - "Other Approaches", - class_name="text-m-slate-12 dark:text-m-slate-3 text-3xl font-[575]", - ), - rx.el.h2( - "No-code tools get you started fast, but Reflex lets you finish. Here's how Reflex compares to platforms like Retool, Streamlit, Plotly Dash, and Power BI.", - 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:top-[11rem] lg:self-start max-lg:self-center max-lg:items-center max-lg:text-center", - ), - comparison_cards(), - class_name="flex lg:flex-row flex-col max-lg:gap-6 max-w-(--docs-layout-max-width) mx-auto relative py-24 max-lg:px-6", - ), - 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 relative", - ) +__all__ = ["compare"] diff --git a/pcweb/pages/migration/low_code/views/explore.py b/pcweb/pages/migration/low_code/views/explore.py index 8bbe32d28..18ca500f7 100644 --- a/pcweb/pages/migration/low_code/views/explore.py +++ b/pcweb/pages/migration/low_code/views/explore.py @@ -1,101 +1,48 @@ -from typing import TypedDict - -import reflex as rx -import reflex_ui as ui - - -class Feature(TypedDict): - title: str - description: str - icon: str - +from pcweb.pages.migration.common.explore import Feature +from pcweb.pages.migration.common.explore import explore as common_explore FEATURES: list[Feature] = [ { - "title": "AI-Powered Development", - "description": "Build your app with the speed of AI and precision of Python", + "title": "AI-Assisted App Development", + "description": "Generate UI and app logic faster with AI while keeping full code control.", "icon": "ArtificialIntelligence04Icon", }, { - "title": "Python-Powered Development", - "description": "Build your app with the speed of AI and precision of Python", - "icon": "RepeatIcon", + "title": "Real Python, Not Drag-and-Drop", + "description": "Write maintainable Python code that fits your existing engineering standards.", + "icon": "SourceCodeSquareIcon", }, { - "title": "Python-Powered Development", - "description": "Build your app with the speed of AI and precision of Python", - "icon": "FlowConnectionIcon", + "title": "Data Stack Integrations", + "description": "Connect databases, APIs, and internal services without low-code workarounds.", + "icon": "DatabaseIcon", }, { - "title": "Python-Powered Development", - "description": "Build your app with the speed of AI and precision of Python", - "icon": "Layers01Icon", + "title": "Security-First by Design", + "description": "Deploy with full control over infrastructure, access, and compliance boundaries.", + "icon": "ShieldEnergyIcon", }, { - "title": "Python-Powered Development", - "description": "Build your app with the speed of AI and precision of Python", - "icon": "Layers01Icon", + "title": "Production-Grade Performance", + "description": "Scale from internal tools to enterprise apps with robust backend capabilities.", + "icon": "DashboardSpeed01Icon", }, { - "title": "Python-Powered Development", - "description": "Build your app with the speed of AI and precision of Python", - "icon": "Layers01Icon", + "title": "Team-Friendly Workflows", + "description": "Use Git, PR reviews, and CI/CD workflows your team already trusts.", + "icon": "UserSwitchIcon", }, ] -def feature_card(feature: Feature) -> rx.Component: - return rx.el.div( - rx.el.div( - ui.icon( - feature["icon"], class_name="text-primary-10 dark:text-primary-9 size-5" - ), - 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 explore(): + return common_explore( + kicker="Explore", + title_prefix="Build Your App With the Speed of ", + title_suffix="AI and Precision of Python", + description="Reflex is growing—and we're looking for people who care deeply about developer experience, clean abstractions.", + features=FEATURES, ) -def feature_grid() -> 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() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - rx.el.p( - "Explore", - class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-m-slate-6", - ), - rx.el.div( - rx.el.h1( - "Build Your App With the Speed of ", - rx.el.br(), - "AI and Precision of Python", - class_name="text-m-slate-12 dark:text-m-slate-3 lg:text-4xl text-3xl font-[575] shrink-0", - ), - rx.el.p( - "Reflex is growing—and we’re looking for people who care deeply about developer experience, clean abstractions.", - 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:py-24 py-16", - ), - feature_grid(), - 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", - ) +__all__ = ["explore"] diff --git a/pcweb/pages/migration/low_code/views/hero.py b/pcweb/pages/migration/low_code/views/hero.py index 0f03410a4..8034f27a8 100644 --- a/pcweb/pages/migration/low_code/views/hero.py +++ b/pcweb/pages/migration/low_code/views/hero.py @@ -1,104 +1,39 @@ -import reflex as rx -import reflex_ui as ui -from reflex_ui.blocks.demo_form import demo_form_dialog +from pcweb.pages.migration.common.hero import HeroLogo +from pcweb.pages.migration.common.hero import hero as common_hero -from pcweb.components.marketing_button import button +HERO_LOGOS: list[HeroLogo] = [ + { + "image_name": "plotly.svg", + "alt": "Plotly Logo", + "class_name": "top-[9.5rem] -ml-[10.5rem]", + }, + { + "image_name": "powerbi.svg", + "alt": "Power BI Logo", + "class_name": "top-[15rem] ml-[16.5rem]", + }, + { + "image_name": "retool.svg", + "alt": "Retool Logo", + "class_name": "top-[9.5rem] ml-[10.5rem]", + }, + { + "image_name": "streamlit.svg", + "alt": "Streamlit Logo", + "class_name": "top-[15rem] -ml-[16.5rem]", + }, +] -def floating_logo(src: str, alt: str, class_name: str = "") -> rx.Component: - return rx.el.div( - rx.image( - src=src, - alt=alt, - loading="eager", - custom_attrs={"fetchPriority": "high"}, - ), - class_name=ui.cn( - 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 hero(): + return common_hero( + kicker="Move From Low Code to Reflex", + title="The Next-Gen Platform Built for Modern Enterprises", + subtitle="Escape low-code 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", ) -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 rounded-[1rem] bg-gradient-to-b from-m-slate-2 to-white-1 dark:from-m-slate-11 dark:to-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 absolute left-1/2 -translate-x-1/2 -translate-y-1/2 z-[1] pointer-events-none top-[13.5rem]", - ) - - -def hero() -> 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-[2.815rem]", - ), - ), - floating_logo( - src=f"/migration/{rx.color_mode_cond('light', 'dark')}/plotly.svg", - alt="Plotly Logo", - class_name="top-[9.5rem] -ml-[10.5rem]", - ), - floating_logo( - src=f"/migration/{rx.color_mode_cond('light', 'dark')}/powerbi.svg", - alt="Power BI Logo", - class_name="top-[15rem] ml-[16.5rem]", - ), - floating_logo( - src=f"/migration/{rx.color_mode_cond('light', 'dark')}/retool.svg", - alt="Retool Logo", - class_name="top-[9.5rem] ml-[10.5rem]", - ), - floating_logo( - src=f"/migration/{rx.color_mode_cond('light', 'dark')}/streamlit.svg", - alt="Streamlit Logo", - class_name="top-[15rem] -ml-[16.5rem]", - ), - gradient_logo(), - class_name="max-lg:hidden", - ), - rx.el.p( - "Move From Low Code to Reflex", - class_name="text-sm font-[525] text-primary-10 dark:text-m-slate-6", - ), - rx.el.h1( - "The Next-Gen Platform Built for Modern Enterprises", - class_name="text-m-slate-12 dark:text-m-slate-3 lg:text-5xl text-3xl font-[575]", - ), - rx.el.h2( - "Escape low-code constraints without sacrificing speed. Build production-grade apps in pure Python with complete control over your stack.", - class_name="text-m-slate-7 dark:text-m-slate-6 text-base font-[475]", - ), - demo_form_dialog( - trigger=button( - "Book a Demo", - 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", - ), - ) +__all__ = ["hero"] diff --git a/pcweb/pages/migration/low_code/views/quotes.py b/pcweb/pages/migration/low_code/views/quotes.py index d6aa17bc5..04ea15888 100644 --- a/pcweb/pages/migration/low_code/views/quotes.py +++ b/pcweb/pages/migration/low_code/views/quotes.py @@ -1,141 +1,52 @@ -from enum import StrEnum -from typing import TypedDict - -import reflex as rx -import reflex_ui as ui -from reflex.experimental import ClientStateVar - - -class Companies(StrEnum): - OPEN_SEA = "open_sea" - FASTLY = "fastly" - AUTODESK = "autodesk" - ACCENTURE = "accenture" - - -class CompanyInfo(TypedDict): - name: str - title: str - quote: str - image: str - - -COMPANIES_INFO: dict[Companies, CompanyInfo] = { - Companies.OPEN_SEA: { +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", - "image": "/landing/social/alex_opensea.webp", "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", }, - Companies.FASTLY: { + { + "key": "fastly", + "logo_image_name": "fastly.svg", + "logo_alt": "Fastly logo", "name": "Emanuele Bonura", "title": "Senior SOC Engineer", - "image": "", "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": "", }, - Companies.AUTODESK: { + { + "key": "autodesk", + "logo_image_name": "autodesk.svg", + "logo_alt": "Autodesk logo", "name": "Paolo", "title": "Principal Consultant", - "image": "", "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": "", }, - Companies.ACCENTURE: { + { + "key": "accenture", + "logo_image_name": "accenture.svg", + "logo_alt": "Accenture logo", "name": "Jordan Lee", "title": "Senior Automation Developer", - "image": "", "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": "", }, -} - +] -active_company_cs = ClientStateVar.create( - "active_company_cs", default=Companies.OPEN_SEA -) - -def company_card(company: Companies) -> rx.Component: - return rx.el.button( - rx.image( - src=f"/migration/{rx.color_mode_cond('light', 'dark')}/{company}.svg", - alt=f"{company} logo", - loading="lazy", - class_name=ui.cn( - "transition-[filter] group-hover:brightness-0 dark:group-hover:brightness-[10]", - rx.cond( - active_company_cs.value == company, - "brightness-0 dark:brightness-[10]", - "", - ), - ), - ), - aria_label=f"Company: {company}", - on_click=active_company_cs.set_value(company), - 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, - "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: Companies) -> rx.Component: - return rx.el.div( - rx.el.p( - COMPANIES_INFO[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=COMPANIES_INFO[company]["name"], - class_name="size-6 rounded-full", - ) - if not COMPANIES_INFO[company]["image"] - else rx.image( - src=COMPANIES_INFO[company]["image"], - loading="lazy", - alt=f"{company} logo", - class_name="size-6 rounded-full", - ), - rx.el.span( - COMPANIES_INFO[company]["name"], - class_name="text-m-slate-12 dark:text-m-slate-3 text-sm font-[525]", - ), - rx.el.span( - COMPANIES_INFO[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 quotes(): + return common_quotes( + companies=COMPANIES, + default_active_key="open_sea", + logo_base_path="/migration", ) -def companies_column() -> rx.Component: - return rx.el.div( - company_card(Companies.OPEN_SEA), - company_card(Companies.FASTLY), - company_card(Companies.AUTODESK), - company_card(Companies.ACCENTURE), - 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() -> rx.Component: - return rx.el.section( - companies_column(), - rx.match( - active_company_cs.value, - (Companies.OPEN_SEA, quote_card(Companies.OPEN_SEA)), - (Companies.FASTLY, quote_card(Companies.FASTLY)), - (Companies.AUTODESK, quote_card(Companies.AUTODESK)), - (Companies.ACCENTURE, quote_card(Companies.ACCENTURE)), - quote_card(Companies.OPEN_SEA), - ), - class_name="flex lg:flex-row flex-col pb-24", - ) +__all__ = ["quotes"] From d9bf609bac9dd2f7e87dabeeb4baaa144f29b854 Mon Sep 17 00:00:00 2001 From: carlosabadia Date: Thu, 26 Feb 2026 20:10:13 +0100 Subject: [PATCH 06/10] add other pages --- assets/migration/dark/lovable.svg | 46 ++++++++++ assets/migration/dark/replit.svg | 6 +- assets/migration/light/lovable.svg | 46 ++++++++++ assets/migration/light/replit.svg | 6 +- pcweb/pages/__init__.py | 6 ++ .../migration/other_ai_tools/__init__.py | 46 ++++++++++ .../other_ai_tools/views/__init__.py | 6 ++ .../migration/other_ai_tools/views/compare.py | 89 +++++++++++++++++++ .../migration/other_ai_tools/views/explore.py | 48 ++++++++++ .../migration/other_ai_tools/views/hero.py | 39 ++++++++ .../migration/other_ai_tools/views/quotes.py | 52 +++++++++++ .../migration/other_frameworks/__init__.py | 46 ++++++++++ .../other_frameworks/views/__init__.py | 6 ++ .../other_frameworks/views/compare.py | 89 +++++++++++++++++++ .../other_frameworks/views/explore.py | 48 ++++++++++ .../migration/other_frameworks/views/hero.py | 39 ++++++++ .../other_frameworks/views/quotes.py | 52 +++++++++++ pcweb/views/marketing_navbar.py | 4 +- 18 files changed, 670 insertions(+), 4 deletions(-) create mode 100644 assets/migration/dark/lovable.svg create mode 100644 assets/migration/light/lovable.svg create mode 100644 pcweb/pages/migration/other_ai_tools/__init__.py create mode 100644 pcweb/pages/migration/other_ai_tools/views/__init__.py create mode 100644 pcweb/pages/migration/other_ai_tools/views/compare.py create mode 100644 pcweb/pages/migration/other_ai_tools/views/explore.py create mode 100644 pcweb/pages/migration/other_ai_tools/views/hero.py create mode 100644 pcweb/pages/migration/other_ai_tools/views/quotes.py create mode 100644 pcweb/pages/migration/other_frameworks/__init__.py create mode 100644 pcweb/pages/migration/other_frameworks/views/__init__.py create mode 100644 pcweb/pages/migration/other_frameworks/views/compare.py create mode 100644 pcweb/pages/migration/other_frameworks/views/explore.py create mode 100644 pcweb/pages/migration/other_frameworks/views/hero.py create mode 100644 pcweb/pages/migration/other_frameworks/views/quotes.py 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/replit.svg b/assets/migration/dark/replit.svg index cc76ee631..a4ee3f7ed 100644 --- a/assets/migration/dark/replit.svg +++ b/assets/migration/dark/replit.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + \ 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/replit.svg b/assets/migration/light/replit.svg index cc76ee631..a4ee3f7ed 100644 --- a/assets/migration/light/replit.svg +++ b/assets/migration/light/replit.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/pcweb/pages/__init__.py b/pcweb/pages/__init__.py index 6a4d58872..ad600843f 100644 --- a/pcweb/pages/__init__.py +++ b/pcweb/pages/__init__.py @@ -21,6 +21,12 @@ 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.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/migration/other_ai_tools/__init__.py b/pcweb/pages/migration/other_ai_tools/__init__.py new file mode 100644 index 000000000..925455ae4 --- /dev/null +++ b/pcweb/pages/migration/other_ai_tools/__init__.py @@ -0,0 +1,46 @@ +import reflex as rx +import reflex_ui as ui + +from pcweb.components.hosting_banner import HostingBannerState +from pcweb.meta.meta import create_meta_tags +from pcweb.pages.about.views.divider import divider +from pcweb.pages.framework.views.footer_index import footer_index +from pcweb.pages.migration.other_ai_tools.views import compare, explore, hero, quotes +from pcweb.views.marketing_navbar import marketing_navbar + + +@rx.page( + route="/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( + marketing_navbar(), + rx.el.main( + rx.el.div( + hero(), + quotes(), + divider(), + compare(), + divider(), + explore(), + divider(), + footer_index(), + 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", + ), + class_name=ui.cn( + "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", + rx.cond( + HostingBannerState.is_banner_visible, + "lg:pt-[7rem] pt-[3.5rem]", + "lg:pt-[4.5rem] pt-[3.5rem]", + ), + ), + ) 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..14dc80e1e --- /dev/null +++ b/pcweb/pages/migration/other_ai_tools/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": [ + "Write real Python — no ceiling on what you can build", + "Handle custom logic, complex data flows, and performance optimization natively", + "Build anything a full-stack app can do", + ], + "cons": [ + "Get you to v1 fast, then you hit walls", + "Custom logic and complex data flows require ugly workarounds", + "Platform limitations dictate what's possible, not your requirements", + ], + }, + { + "title": "You Own Your Code", + "icon": "SourceCodeSquareIcon", + "pros": [ + "It's your Python code — deploy it anywhere", + "Full version control with Git", + "Never hostage to a platform's pricing or shutdown", + ], + "cons": [ + "Your app lives on their infrastructure in their proprietary format", + "Vendor lock-in makes migration painful or impossible", + "Pricing changes or platform shutdowns put your app at risk", + ], + }, + { + "title": "Python Ecosystem Access", + "icon": "PythonIcon", + "pros": [ + "Use libraries you already know — pandas, scikit-learn, whatever", + "Build internal tools or customer-facing apps in one language", + "Leverage the entire Python ecosystem with no restrictions", + ], + "cons": [ + "Limited to the platform's pre-built integrations", + "Can't tap into Python's ML, data science, or backend libraries", + "Forces non-JS developers to learn new tools or work around limitations", + ], + }, + { + "title": "Scales With Complexity", + "icon": "SquareArrowExpand02Icon", + "pros": [ + "Auth flows, real-time features, complex state management — all native", + "Handles growing complexity because it's just code", + "No artificial boundaries on what you can build", + ], + "cons": [ + "Great for simple CRUD apps and dashboards, then it breaks down", + "Once you need real complexity, you're fighting the tool instead of building", + "Workarounds pile up and become unmaintainable", + ], + }, + { + "title": "Team Collaboration & Engineering Practices", + "icon": "UserSwitchIcon", + "pros": [ + "Fits into normal engineering workflows — Git, PRs, CI/CD", + "Code review and automated testing work out of the box", + "Your whole team can collaborate using standard dev practices", + ], + "cons": [ + "Version control is difficult or impossible", + "Code review and testing are afterthoughts at best", + "Engineering best practices don't apply to proprietary drag-and-drop formats", + ], + }, +] + + +def compare(): + return common_compare( + kicker="Compare", + heading_lines=["How You Benefit ", "With Reflex vs. ", "Other Approaches"], + description="AI tools get you started fast, but Reflex lets you finish. Here's how Reflex compares to platforms like ChatGPT, Claude, Replit, and Lovable.", + top_left_title="Reflex", + top_right_title="ChatGPT, Claude, Replit, Lovable", + comparison_items=COMPARISON_ITEMS, + ) + + +__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..18ca500f7 --- /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": "AI-Assisted App Development", + "description": "Generate UI and app logic faster with AI while keeping full code control.", + "icon": "ArtificialIntelligence04Icon", + }, + { + "title": "Real Python, Not Drag-and-Drop", + "description": "Write maintainable Python code that fits your existing engineering standards.", + "icon": "SourceCodeSquareIcon", + }, + { + "title": "Data Stack Integrations", + "description": "Connect databases, APIs, and internal services without low-code workarounds.", + "icon": "DatabaseIcon", + }, + { + "title": "Security-First by Design", + "description": "Deploy with full control over infrastructure, access, and compliance boundaries.", + "icon": "ShieldEnergyIcon", + }, + { + "title": "Production-Grade Performance", + "description": "Scale from internal tools to enterprise apps with robust backend capabilities.", + "icon": "DashboardSpeed01Icon", + }, + { + "title": "Team-Friendly Workflows", + "description": "Use Git, PR reviews, and CI/CD workflows your team already trusts.", + "icon": "UserSwitchIcon", + }, +] + + +def explore(): + return common_explore( + kicker="Explore", + title_prefix="Build Your App With the Speed of ", + title_suffix="AI and Precision of Python", + description="Reflex is growing—and we're looking for people who care deeply about developer experience, clean abstractions.", + 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..854a66a34 --- /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": "chatgpt.svg", + "alt": "ChatGPT 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..c14ec3c1f --- /dev/null +++ b/pcweb/pages/migration/other_frameworks/__init__.py @@ -0,0 +1,46 @@ +import reflex as rx +import reflex_ui as ui + +from pcweb.components.hosting_banner import HostingBannerState +from pcweb.meta.meta import create_meta_tags +from pcweb.pages.about.views.divider import divider +from pcweb.pages.framework.views.footer_index import footer_index +from pcweb.pages.migration.other_frameworks.views import compare, explore, hero, quotes +from pcweb.views.marketing_navbar import marketing_navbar + + +@rx.page( + route="/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( + marketing_navbar(), + rx.el.main( + rx.el.div( + hero(), + quotes(), + divider(), + compare(), + divider(), + explore(), + divider(), + footer_index(), + 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", + ), + class_name=ui.cn( + "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", + rx.cond( + HostingBannerState.is_banner_visible, + "lg:pt-[7rem] pt-[3.5rem]", + "lg:pt-[4.5rem] pt-[3.5rem]", + ), + ), + ) 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..c431a0a7f --- /dev/null +++ b/pcweb/pages/migration/other_frameworks/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": [ + "Write real Python — no ceiling on what you can build", + "Handle custom logic, complex data flows, and performance optimization natively", + "Build anything a full-stack app can do", + ], + "cons": [ + "Get you to v1 fast, then you hit walls", + "Custom logic and complex data flows require ugly workarounds", + "Platform limitations dictate what's possible, not your requirements", + ], + }, + { + "title": "You Own Your Code", + "icon": "SourceCodeSquareIcon", + "pros": [ + "It's your Python code — deploy it anywhere", + "Full version control with Git", + "Never hostage to a platform's pricing or shutdown", + ], + "cons": [ + "Your app lives on their infrastructure in their proprietary format", + "Vendor lock-in makes migration painful or impossible", + "Pricing changes or platform shutdowns put your app at risk", + ], + }, + { + "title": "Python Ecosystem Access", + "icon": "PythonIcon", + "pros": [ + "Use libraries you already know — pandas, scikit-learn, whatever", + "Build internal tools or customer-facing apps in one language", + "Leverage the entire Python ecosystem with no restrictions", + ], + "cons": [ + "Limited to the platform's pre-built integrations", + "Can't tap into Python's ML, data science, or backend libraries", + "Forces non-JS developers to learn new tools or work around limitations", + ], + }, + { + "title": "Scales With Complexity", + "icon": "SquareArrowExpand02Icon", + "pros": [ + "Auth flows, real-time features, complex state management — all native", + "Handles growing complexity because it's just code", + "No artificial boundaries on what you can build", + ], + "cons": [ + "Great for simple CRUD apps and dashboards, then it breaks down", + "Once you need real complexity, you're fighting the tool instead of building", + "Workarounds pile up and become unmaintainable", + ], + }, + { + "title": "Team Collaboration & Engineering Practices", + "icon": "UserSwitchIcon", + "pros": [ + "Fits into normal engineering workflows — Git, PRs, CI/CD", + "Code review and automated testing work out of the box", + "Your whole team can collaborate using standard dev practices", + ], + "cons": [ + "Version control is difficult or impossible", + "Code review and testing are afterthoughts at best", + "Engineering best practices don't apply to proprietary drag-and-drop formats", + ], + }, +] + + +def compare(): + return common_compare( + kicker="Compare", + heading_lines=["How You Benefit ", "With Reflex vs. ", "Other Approaches"], + description="Other frameworks get you started fast, but Reflex lets you finish. Here's how Reflex compares to platforms like React, JavaScript, Django, and FastAPI.", + top_left_title="Reflex", + top_right_title="React, JavaScript, 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..18ca500f7 --- /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": "AI-Assisted App Development", + "description": "Generate UI and app logic faster with AI while keeping full code control.", + "icon": "ArtificialIntelligence04Icon", + }, + { + "title": "Real Python, Not Drag-and-Drop", + "description": "Write maintainable Python code that fits your existing engineering standards.", + "icon": "SourceCodeSquareIcon", + }, + { + "title": "Data Stack Integrations", + "description": "Connect databases, APIs, and internal services without low-code workarounds.", + "icon": "DatabaseIcon", + }, + { + "title": "Security-First by Design", + "description": "Deploy with full control over infrastructure, access, and compliance boundaries.", + "icon": "ShieldEnergyIcon", + }, + { + "title": "Production-Grade Performance", + "description": "Scale from internal tools to enterprise apps with robust backend capabilities.", + "icon": "DashboardSpeed01Icon", + }, + { + "title": "Team-Friendly Workflows", + "description": "Use Git, PR reviews, and CI/CD workflows your team already trusts.", + "icon": "UserSwitchIcon", + }, +] + + +def explore(): + return common_explore( + kicker="Explore", + title_prefix="Build Your App With the Speed of ", + title_suffix="AI and Precision of Python", + description="Reflex is growing—and we're looking for people who care deeply about developer experience, clean abstractions.", + 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/marketing_navbar.py b/pcweb/views/marketing_navbar.py index 8d56d738a..80b639d34 100644 --- a/pcweb/views/marketing_navbar.py +++ b/pcweb/views/marketing_navbar.py @@ -387,12 +387,12 @@ def solutions_content() -> rx.Component: ( "Switch from Other Frameworks", "CodeIcon", - use_cases_page.path, + "/migration/other-frameworks", ), ( "Switch from Other AI tools", "ArtificialIntelligence04Icon", - use_cases_page.path, + "/migration/other-ai-tools", ), ], ), From 03b012db2e414f8ea882b688aa8678eb48c27f9f Mon Sep 17 00:00:00 2001 From: carlosabadia Date: Tue, 3 Mar 2026 11:46:01 +0100 Subject: [PATCH 07/10] update pages --- assets/migration/dark/gradio.svg | 1 + assets/migration/dark/tableau.svg | 1 + assets/migration/light/gradio.svg | 1 + assets/migration/light/tableau.svg | 1 + pcweb/pages/__init__.py | 1 + pcweb/pages/migration/common/compare.py | 15 ++- pcweb/pages/migration/low_code/__init__.py | 4 +- .../pages/migration/low_code/views/compare.py | 104 +++++++++++------- .../pages/migration/low_code/views/explore.py | 40 +++---- pcweb/pages/migration/low_code/views/hero.py | 21 ++-- pcweb/pages/migration/no_code/__init__.py | 46 ++++++++ .../pages/migration/no_code/views/__init__.py | 6 + .../pages/migration/no_code/views/compare.py | 94 ++++++++++++++++ .../pages/migration/no_code/views/explore.py | 48 ++++++++ pcweb/pages/migration/no_code/views/hero.py | 34 ++++++ pcweb/pages/migration/no_code/views/quotes.py | 52 +++++++++ pcweb/views/marketing_navbar.py | 5 + 17 files changed, 396 insertions(+), 78 deletions(-) create mode 100644 assets/migration/dark/gradio.svg create mode 100644 assets/migration/dark/tableau.svg create mode 100644 assets/migration/light/gradio.svg create mode 100644 assets/migration/light/tableau.svg create mode 100644 pcweb/pages/migration/no_code/__init__.py create mode 100644 pcweb/pages/migration/no_code/views/__init__.py create mode 100644 pcweb/pages/migration/no_code/views/compare.py create mode 100644 pcweb/pages/migration/no_code/views/explore.py create mode 100644 pcweb/pages/migration/no_code/views/hero.py create mode 100644 pcweb/pages/migration/no_code/views/quotes.py 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/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/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/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 b2e5e3702..9d8f6b264 100644 --- a/pcweb/pages/__init__.py +++ b/pcweb/pages/__init__.py @@ -21,6 +21,7 @@ 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, ) diff --git a/pcweb/pages/migration/common/compare.py b/pcweb/pages/migration/common/compare.py index cf4bb8177..ed64326d9 100644 --- a/pcweb/pages/migration/common/compare.py +++ b/pcweb/pages/migration/common/compare.py @@ -1,4 +1,4 @@ -from typing import TypedDict +from typing import NotRequired, TypedDict import reflex as rx import reflex_ui as ui @@ -9,6 +9,14 @@ class ComparisonItem(TypedDict): icon: str pros: list[str] cons: list[str] + description: NotRequired[str] + + +def comparison_description(description: str) -> rx.Component: + return rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-4 lg:text-sm text-xs font-[475] leading-relaxed lg:px-12 lg:py-6 px-6 py-4 border-r border-m-slate-4 dark:border-m-slate-10 bg-m-slate-1 dark:bg-m-slate-10 border-b", + ) def comparison_title(title: str, icon: str) -> rx.Component: @@ -74,7 +82,7 @@ def pros_cons_cards(pros: list[str], cons: list[str]) -> rx.Component: 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-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-8 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t", + class_name="text-m-slate-12 dark:text-m-slate-3 text-xs leading-[1.5rem] font-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-12 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t uppercase", ) @@ -101,6 +109,9 @@ def comparison_cards( *[ rx.fragment( comparison_title(item["title"], item["icon"]), + comparison_description(item["description"]) + if item.get("description") + else rx.fragment(), pros_cons_cards(item["pros"], item["cons"]), ) for item in comparison_items diff --git a/pcweb/pages/migration/low_code/__init__.py b/pcweb/pages/migration/low_code/__init__.py index 1e549fb39..463afa92c 100644 --- a/pcweb/pages/migration/low_code/__init__.py +++ b/pcweb/pages/migration/low_code/__init__.py @@ -14,8 +14,8 @@ 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", - image="/previews/low_code_migration_preview.webp", + 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: diff --git a/pcweb/pages/migration/low_code/views/compare.py b/pcweb/pages/migration/low_code/views/compare.py index 74fef35eb..1ef453246 100644 --- a/pcweb/pages/migration/low_code/views/compare.py +++ b/pcweb/pages/migration/low_code/views/compare.py @@ -3,73 +3,91 @@ COMPARISON_ITEMS: list[ComparisonItem] = [ { - "title": "Full Control Without the Ceiling", - "icon": "CodesandboxIcon", + "title": "Architecture and state management.", + "icon": "SquareArrowExpand02Icon", + "description": 'Streamlit uses a "script rerun" model where every widget change re-executes the entire Python script from top to bottom. Dash uses a callback-based architecture that becomes "callback spaghetti" as apps grow. Gradio is designed specifically for ML model demos. Reflex takes a declarative, state-driven approach where you define state classes and UI components in Python, and changes propagate reactively via WebSockets. Only affected components re-render.', "pros": [ - "Write real Python — no ceiling on what you can build", - "Handle custom logic, complex data flows, and performance optimization natively", - "Build anything a full-stack app can do", + "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": [ - "Get you to v1 fast, then you hit walls", - "Custom logic and complex data flows require ugly workarounds", - "Platform limitations dictate what's possible, not your requirements", + "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": "You Own Your Code", + "title": "Real-time and interactivity.", + "icon": "ZapIcon", + "description": "Streamlit has no server push — real-time or background updates need client polling or workarounds. Dash has no native server-push feature. Gradio's interactivity is limited to input-output pairs for ML model inference. Reflex uses automatic WebSocket sync where state changes on the server instantly propagate to the browser.", + "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", + "description": "Real Reflex projects cut approximately 50% of the code compared to equivalent Dash apps. Reflex's Python class-based state model keeps code organized. In Dash, the callback model fragments logic across scattered decorator functions. In Streamlit, the linear script model breaks down when you need complex page flows or shared state across views.", "pros": [ - "It's your Python code — deploy it anywhere", - "Full version control with Git", - "Never hostage to a platform's pricing or shutdown", + "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": [ - "Your app lives on their infrastructure in their proprietary format", - "Vendor lock-in makes migration painful or impossible", - "Pricing changes or platform shutdowns put your app at risk", + "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": "Python Ecosystem Access", - "icon": "PythonIcon", + "title": "Customization and UI components.", + "icon": "WebDesign01Icon", + "description": "Streamlit has a customization ceiling — deep CSS or HTML tweaks are difficult, and building truly bespoke widgets requires writing a Streamlit Component in React and TypeScript. Dash has a robust set of components but custom ones still require React. Gradio's customization is similarly limited. Reflex lets you wrap any React component directly from Python with fine-grained CSS control.", "pros": [ - "Use libraries you already know — pandas, scikit-learn, whatever", - "Build internal tools or customer-facing apps in one language", - "Leverage the entire Python ecosystem with no restrictions", + "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": [ - "Limited to the platform's pre-built integrations", - "Can't tap into Python's ML, data science, or backend libraries", - "Forces non-JS developers to learn new tools or work around limitations", + "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": "Scales With Complexity", - "icon": "SquareArrowExpand02Icon", + "title": "Built-in functionality.", + "icon": "Settings01Icon", + "description": "Streamlit and Dash both lack built-in essentials for production apps — no auth, background tasks, or ORM. Gradio is focused narrowly on ML model demos. Reflex ships with ORM, database migrations, background jobs, file uploads, and role-based auth out of the box.", "pros": [ - "Auth flows, real-time features, complex state management — all native", - "Handles growing complexity because it's just code", - "No artificial boundaries on what you can build", + "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": [ - "Great for simple CRUD apps and dashboards, then it breaks down", - "Once you need real complexity, you're fighting the tool instead of building", - "Workarounds pile up and become unmaintainable", + "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": "Team Collaboration & Engineering Practices", + "title": "Deployment and the prototype-to-production gap.", "icon": "UserSwitchIcon", + "description": "Low-code Python frameworks are good for getting a first version up quickly, but not designed to take apps to production. Streamlit apps hit out-of-memory errors under load. Open-source Dash runs on Flask and requires manual infrastructure setup. Gradio struggles to scale for production. Reflex compiles to a FastAPI backend with a React frontend — production-ready and container-friendly from day one.", "pros": [ - "Fits into normal engineering workflows — Git, PRs, CI/CD", - "Code review and automated testing work out of the box", - "Your whole team can collaborate using standard dev practices", + "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": [ - "Version control is difficult or impossible", - "Code review and testing are afterthoughts at best", - "Engineering best practices don't apply to proprietary drag-and-drop formats", + "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", ], }, ] @@ -78,10 +96,14 @@ 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 Retool, Streamlit, Plotly Dash, and Power BI.", + 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="Retool, Streamlit, Plotly Dash, Power BI", + top_right_title="Streamlit, Dash, Gradio", comparison_items=COMPARISON_ITEMS, ) diff --git a/pcweb/pages/migration/low_code/views/explore.py b/pcweb/pages/migration/low_code/views/explore.py index 18ca500f7..3d5a107c1 100644 --- a/pcweb/pages/migration/low_code/views/explore.py +++ b/pcweb/pages/migration/low_code/views/explore.py @@ -3,33 +3,33 @@ FEATURES: list[Feature] = [ { - "title": "AI-Assisted App Development", - "description": "Generate UI and app logic faster with AI while keeping full code control.", - "icon": "ArtificialIntelligence04Icon", + "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 Python, Not Drag-and-Drop", - "description": "Write maintainable Python code that fits your existing engineering standards.", - "icon": "SourceCodeSquareIcon", + "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": "Data Stack Integrations", - "description": "Connect databases, APIs, and internal services without low-code workarounds.", - "icon": "DatabaseIcon", + "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": "Security-First by Design", - "description": "Deploy with full control over infrastructure, access, and compliance boundaries.", - "icon": "ShieldEnergyIcon", + "title": "Full Customization", + "description": "Wrap any React component from Python. Complete design flexibility without leaving the Python ecosystem.", + "icon": "WebDesign01Icon", }, { - "title": "Production-Grade Performance", - "description": "Scale from internal tools to enterprise apps with robust backend capabilities.", - "icon": "DashboardSpeed01Icon", + "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": "Team-Friendly Workflows", - "description": "Use Git, PR reviews, and CI/CD workflows your team already trusts.", + "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", }, ] @@ -38,9 +38,9 @@ def explore(): return common_explore( kicker="Explore", - title_prefix="Build Your App With the Speed of ", - title_suffix="AI and Precision of Python", - description="Reflex is growing—and we're looking for people who care deeply about developer experience, clean abstractions.", + 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, ) diff --git a/pcweb/pages/migration/low_code/views/hero.py b/pcweb/pages/migration/low_code/views/hero.py index 8034f27a8..0a5825e55 100644 --- a/pcweb/pages/migration/low_code/views/hero.py +++ b/pcweb/pages/migration/low_code/views/hero.py @@ -3,23 +3,18 @@ HERO_LOGOS: list[HeroLogo] = [ { - "image_name": "plotly.svg", - "alt": "Plotly Logo", + "image_name": "streamlit.svg", + "alt": "Streamlit Logo", "class_name": "top-[9.5rem] -ml-[10.5rem]", }, { - "image_name": "powerbi.svg", - "alt": "Power BI Logo", - "class_name": "top-[15rem] ml-[16.5rem]", - }, - { - "image_name": "retool.svg", - "alt": "Retool Logo", + "image_name": "plotly.svg", + "alt": "Plotly Dash Logo", "class_name": "top-[9.5rem] ml-[10.5rem]", }, { - "image_name": "streamlit.svg", - "alt": "Streamlit Logo", + "image_name": "gradio.svg", + "alt": "Gradio Logo", "class_name": "top-[15rem] -ml-[16.5rem]", }, ] @@ -28,8 +23,8 @@ def hero(): return common_hero( kicker="Move From Low Code to Reflex", - title="The Next-Gen Platform Built for Modern Enterprises", - subtitle="Escape low-code constraints without sacrificing speed. Build production-grade apps in pure Python with complete control over your stack.", + 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", diff --git a/pcweb/pages/migration/no_code/__init__.py b/pcweb/pages/migration/no_code/__init__.py new file mode 100644 index 000000000..f9ca9c70b --- /dev/null +++ b/pcweb/pages/migration/no_code/__init__.py @@ -0,0 +1,46 @@ +import reflex as rx +import reflex_ui as ui + +from pcweb.components.hosting_banner import HostingBannerState +from pcweb.meta.meta import create_meta_tags +from pcweb.pages.about.views.divider import divider +from pcweb.pages.framework.views.footer_index import footer_index +from pcweb.pages.migration.no_code.views import compare, explore, hero, quotes +from pcweb.views.marketing_navbar import marketing_navbar + + +@rx.page( + route="/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( + marketing_navbar(), + rx.el.main( + rx.el.div( + hero(), + quotes(), + divider(), + compare(), + divider(), + explore(), + divider(), + footer_index(), + 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", + ), + class_name=ui.cn( + "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", + rx.cond( + HostingBannerState.is_banner_visible, + "lg:pt-[7rem] pt-[3.5rem]", + "lg:pt-[4.5rem] pt-[3.5rem]", + ), + ), + ) 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..559ff8ac5 --- /dev/null +++ b/pcweb/pages/migration/no_code/views/compare.py @@ -0,0 +1,94 @@ +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", + "description": "No-code tools (PowerBI, Tableau, Retool) get you to v1 fast, but you hit walls — custom logic, complex data flows, performance optimization, or anything the platform didn't anticipate. Despite being \"no-code,\" there is a significant learning curve for advanced features. With Reflex, you're writing Python, so there's no ceiling. You can do anything a full-stack app can do.", + "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", + "description": "No-code platforms create vendor lock-in. Your app lives on their infrastructure, in their proprietary format. With Reflex, it's your Python code — you can deploy it anywhere, version control it, and you're never hostage to a platform's pricing changes or shutdown.", + "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", + "description": "Data scientists, ML engineers, and backend devs already live in Python. Reflex lets them build internal tools or customer-facing apps using libraries they already know (pandas, scikit-learn, whatever) without learning JavaScript or being constrained by a drag-and-drop builder's integrations.", + "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", + "description": "No-code works great for simple dashboards, but even basic interactivity is a problem. Tools like Tableau and Power BI don't natively support CRUD operations at all. Once you need users to create, edit, or delete data, plus auth flows, real-time features, complex state management, or custom APIs, you're fighting the tool instead of building. Tools also struggle with performance at scale — whether it's dataset size limits, reliance on scheduled refreshes instead of real-time data, or apps slowing down as complexity grows. Reflex handles that complexity natively because it's just code.", + "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", + "description": "No-code tools get you a prototype, but when it's time to hand it to IT or take it to production, you hit a wall. None of these tools support native version control, git integration, code review, or CI/CD pipelines. With Reflex, your app is built on real code from the start. It fits into the workflows your engineering team already uses — Git, PRs, automated testing, staging environments — so there's no painful \"rewrite it properly\" phase. What you demo is what you ship.", + "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/views/marketing_navbar.py b/pcweb/views/marketing_navbar.py index 80b639d34..59a3932d1 100644 --- a/pcweb/views/marketing_navbar.py +++ b/pcweb/views/marketing_navbar.py @@ -382,6 +382,11 @@ def solutions_content() -> rx.Component: ( "Switch from No Code", "WebDesign01Icon", + "/migration/no-code", + ), + ( + "Switch from Low Code", + "SourceCodeSquareIcon", "/migration/low-code", ), ( From b66a28a094b38973c1b24ad57041e05690db54a8 Mon Sep 17 00:00:00 2001 From: carlosabadia Date: Tue, 3 Mar 2026 16:34:48 +0100 Subject: [PATCH 08/10] temp content for the rest --- .../migration/other_ai_tools/views/compare.py | 79 +++++++------ .../migration/other_ai_tools/views/explore.py | 40 +++---- .../other_frameworks/views/compare.py | 108 +++++++++++------- .../other_frameworks/views/explore.py | 40 +++---- 4 files changed, 150 insertions(+), 117 deletions(-) diff --git a/pcweb/pages/migration/other_ai_tools/views/compare.py b/pcweb/pages/migration/other_ai_tools/views/compare.py index 14dc80e1e..eeeb3f7aa 100644 --- a/pcweb/pages/migration/other_ai_tools/views/compare.py +++ b/pcweb/pages/migration/other_ai_tools/views/compare.py @@ -3,73 +3,78 @@ COMPARISON_ITEMS: list[ComparisonItem] = [ { - "title": "Full Control Without the Ceiling", + "title": "Full control without the ceiling.", "icon": "CodesandboxIcon", + "description": "AI app builders (ChatGPT, Claude, Replit, Lovable) get you to v1 fast, but you hit walls — custom logic, integrations beyond what the AI knows, or anything the platform didn't anticipate. What you get is what they generate. With Reflex, you're writing Python, so there's no ceiling. You can do anything a full-stack app can do.", "pros": [ - "Write real Python — no ceiling on what you can build", - "Handle custom logic, complex data flows, and performance optimization natively", - "Build anything a full-stack app can do", + "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", + "You own every line of code — no black-box AI output you can't modify", ], "cons": [ - "Get you to v1 fast, then you hit walls", - "Custom logic and complex data flows require ugly workarounds", + "AI tools hit walls on custom logic, integrations, and anything the platform didn't anticipate", + "What you get is what they generate — no deep customization without fighting the tool", "Platform limitations dictate what's possible, not your requirements", ], }, { - "title": "You Own Your Code", + "title": "You own your code.", "icon": "SourceCodeSquareIcon", + "description": "AI app builders create output that lives on their infrastructure, in their proprietary format. Your app is tied to their platform — you can't export it, version it properly, or deploy it yourself. With Reflex, it's your Python code — you can deploy it anywhere, version control it, and you're never hostage to a platform's pricing changes or shutdown.", "pros": [ - "It's your Python code — deploy it anywhere", - "Full version control with Git", - "Never hostage to a platform's pricing or shutdown", + "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 makes migration painful or impossible", - "Pricing changes or platform shutdowns put your app at risk", + "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", + "title": "Python ecosystem access.", "icon": "PythonIcon", + "description": "Data scientists, ML engineers, and backend devs already live in Python. Reflex lets them build internal tools or customer-facing apps using libraries they already know (pandas, scikit-learn, whatever) without being constrained by an AI's pre-built integrations or learning JavaScript. AI tools are limited to what the model knows how to integrate.", "pros": [ - "Use libraries you already know — pandas, scikit-learn, whatever", - "Build internal tools or customer-facing apps in one language", - "Leverage the entire Python ecosystem with no restrictions", + "Build with Python libraries your team already knows — pandas, scikit-learn, or any pip package", + "No need to learn JavaScript or be constrained by pre-built integrations", + "Data scientists, ML engineers, and backend devs can build internal tools or customer-facing apps directly", ], "cons": [ - "Limited to the platform's pre-built integrations", - "Can't tap into Python's ML, data science, or backend libraries", - "Forces non-JS developers to learn new tools or work around limitations", + "AI tools constrain you to their pre-built integrations and what the model knows", + "Requires workarounds or is impossible for custom libraries and data sources", + "Data scientists and ML engineers can't use the Python libraries they already know", ], }, { - "title": "Scales With Complexity", + "title": "Scales with complexity.", "icon": "SquareArrowExpand02Icon", + "description": "AI app builders work great for simple demos, but once you need auth flows, real-time features, complex state management, custom APIs, or production-grade performance, you hit a wall. The generated output isn't designed for that. Reflex handles that complexity natively because it's just code.", "pros": [ - "Auth flows, real-time features, complex state management — all native", - "Handles growing complexity because it's just code", + "CRUD, auth flows, real-time features, complex state management, and custom APIs are all native", + "Handles complexity natively because it's just code", "No artificial boundaries on what you can build", ], "cons": [ - "Great for simple CRUD apps and dashboards, then it breaks down", - "Once you need real complexity, you're fighting the tool instead of building", - "Workarounds pile up and become unmaintainable", + "AI-generated apps break down once you need real complexity — auth, real-time, or production scale", + "The output isn't designed for maintainable, extensible codebases", + "Once you need users to do more than view a demo, you're fighting the tool instead of building", ], }, { - "title": "Team Collaboration & Engineering Practices", + "title": "Production-ready from day one.", "icon": "UserSwitchIcon", + "description": "AI app builders get you a prototype, but when it's time to hand it to IT or take it to production, you hit a wall. None of these tools support native version control, git integration, code review, or CI/CD pipelines. With Reflex, your app is built on real code from the start. It fits into the workflows your engineering team already uses — Git, PRs, automated testing, staging environments — so there's no painful \"rewrite it properly\" phase. What you demo is what you ship.", "pros": [ - "Fits into normal engineering workflows — Git, PRs, CI/CD", - "Code review and automated testing work out of the box", - "Your whole team can collaborate using standard dev practices", + "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": [ - "Version control is difficult or impossible", - "Code review and testing are afterthoughts at best", - "Engineering best practices don't apply to proprietary drag-and-drop formats", + "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", ], }, ] @@ -78,8 +83,12 @@ def compare(): return common_compare( kicker="Compare", - heading_lines=["How You Benefit ", "With Reflex vs. ", "Other Approaches"], - description="AI tools get you started fast, but Reflex lets you finish. Here's how Reflex compares to platforms like ChatGPT, Claude, Replit, and Lovable.", + heading_lines=[ + "How You Benefit ", + "With Reflex vs. ", + "ChatGPT, Claude, Replit, Lovable", + ], + description="AI app builders get you prototyping fast. Reflex lets you finish. Here's how Reflex compares to platforms like ChatGPT, Claude, Replit, and Lovable.", top_left_title="Reflex", top_right_title="ChatGPT, Claude, Replit, Lovable", comparison_items=COMPARISON_ITEMS, diff --git a/pcweb/pages/migration/other_ai_tools/views/explore.py b/pcweb/pages/migration/other_ai_tools/views/explore.py index 18ca500f7..051e62503 100644 --- a/pcweb/pages/migration/other_ai_tools/views/explore.py +++ b/pcweb/pages/migration/other_ai_tools/views/explore.py @@ -3,34 +3,34 @@ FEATURES: list[Feature] = [ { - "title": "AI-Assisted App Development", - "description": "Generate UI and app logic faster with AI while keeping full code control.", - "icon": "ArtificialIntelligence04Icon", + "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": "Real Python, Not Drag-and-Drop", - "description": "Write maintainable Python code that fits your existing engineering standards.", + "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": "Data Stack Integrations", - "description": "Connect databases, APIs, and internal services without low-code workarounds.", - "icon": "DatabaseIcon", + "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": "Security-First by Design", - "description": "Deploy with full control over infrastructure, access, and compliance boundaries.", - "icon": "ShieldEnergyIcon", + "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-Grade Performance", - "description": "Scale from internal tools to enterprise apps with robust backend capabilities.", - "icon": "DashboardSpeed01Icon", + "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": "Team-Friendly Workflows", - "description": "Use Git, PR reviews, and CI/CD workflows your team already trusts.", - "icon": "UserSwitchIcon", + "title": "Data Stack Integrations", + "description": "Connect databases, APIs, and internal services without platform workarounds. No lock-in to what the AI knows.", + "icon": "DatabaseIcon", }, ] @@ -38,9 +38,9 @@ def explore(): return common_explore( kicker="Explore", - title_prefix="Build Your App With the Speed of ", - title_suffix="AI and Precision of Python", - description="Reflex is growing—and we're looking for people who care deeply about developer experience, clean abstractions.", + title_prefix="Why Reflex Over ", + title_suffix="ChatGPT, Claude, Replit, Lovable", + description="AI app builders get you prototyping fast, but Reflex lets you finish. Pure Python, no ceiling, you own your code.", features=FEATURES, ) diff --git a/pcweb/pages/migration/other_frameworks/views/compare.py b/pcweb/pages/migration/other_frameworks/views/compare.py index c431a0a7f..e3b36c39e 100644 --- a/pcweb/pages/migration/other_frameworks/views/compare.py +++ b/pcweb/pages/migration/other_frameworks/views/compare.py @@ -3,73 +3,93 @@ COMPARISON_ITEMS: list[ComparisonItem] = [ { - "title": "Full Control Without the Ceiling", - "icon": "CodesandboxIcon", + "title": "One language for frontend and backend.", + "icon": "PythonIcon", + "description": "React and JavaScript require a split stack — you maintain frontend in JS/TypeScript and backend in Python, Go, or Node. Django is full-stack Python but server-rendered, with a different paradigm for modern SPAs. FastAPI is backend only — you still need React or Vue for the UI. Reflex gives you both in Python: declarative UI components and backend logic in one codebase.", "pros": [ - "Write real Python — no ceiling on what you can build", - "Handle custom logic, complex data flows, and performance optimization natively", - "Build anything a full-stack app can do", + "One language end to end — no context switching between JavaScript and Python", + "Data scientists, ML engineers, and backend devs build UIs without learning React", + "Single codebase for frontend and backend — simpler architecture, easier to maintain", ], "cons": [ - "Get you to v1 fast, then you hit walls", - "Custom logic and complex data flows require ugly workarounds", - "Platform limitations dictate what's possible, not your requirements", + "React requires JavaScript or TypeScript for the frontend — a separate stack to learn and maintain", + "Django is server-rendered — building modern SPAs with real-time updates requires additional tooling", + "FastAPI is backend only — you still need a separate frontend framework and two deployments", ], }, { - "title": "You Own Your Code", - "icon": "SourceCodeSquareIcon", + "title": "Architecture and state management.", + "icon": "SquareArrowExpand02Icon", + "description": "React uses a component-based model with hooks and external state libraries. Django uses server-side request/response. FastAPI has no built-in frontend. Reflex takes a declarative, state-driven approach where you define state classes and UI components in Python, and changes propagate reactively via WebSockets. Only affected components re-render.", "pros": [ - "It's your Python code — deploy it anywhere", - "Full version control with Git", - "Never hostage to a platform's pricing or shutdown", + "Declarative state and event-driven updates — only affected components re-render", + "User sessions remember where they are — multi-step workflows and real-time updates work without extra effort", + "The event-driven model keeps your code clean and organized as your app grows", ], "cons": [ - "Your app lives on their infrastructure in their proprietary format", - "Vendor lock-in makes migration painful or impossible", - "Pricing changes or platform shutdowns put your app at risk", + "React's ecosystem of state libraries (Redux, Zustand, etc.) adds complexity — you choose and maintain the stack", + "Django's request/response model doesn't natively support real-time or reactive updates", + "FastAPI has no frontend — real-time state sync requires building it yourself", ], }, { - "title": "Python Ecosystem Access", - "icon": "PythonIcon", + "title": "Real-time and interactivity.", + "icon": "ZapIcon", + "description": "React can do real-time but requires manual WebSocket setup or third-party services. Django has no native server-push. FastAPI supports WebSockets but you build the frontend integration yourself. Reflex uses automatic WebSocket sync where state changes on the server instantly propagate to the browser.", "pros": [ - "Use libraries you already know — pandas, scikit-learn, whatever", - "Build internal tools or customer-facing apps in one language", - "Leverage the entire Python ecosystem with no restrictions", + "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 reacts to user actions as they happen", ], "cons": [ - "Limited to the platform's pre-built integrations", - "Can't tap into Python's ML, data science, or backend libraries", - "Forces non-JS developers to learn new tools or work around limitations", + "React has no built-in server push — real-time needs manual WebSocket setup or services like Pusher", + "Django has no native real-time — you add Channels and more infrastructure", + "FastAPI has WebSockets but no integrated frontend — you wire it up yourself", ], }, { - "title": "Scales With Complexity", - "icon": "SquareArrowExpand02Icon", + "title": "Code structure and maintainability.", + "icon": "SourceCodeSquareIcon", + "description": "React apps split logic across components, hooks, and often a separate API layer. Django keeps things in one place but with a different mental model for SPAs. FastAPI + React means two codebases, two test suites. Reflex's Python class-based state model keeps frontend and backend logic organized in one place.", "pros": [ - "Auth flows, real-time features, complex state management — all native", - "Handles growing complexity because it's just code", - "No artificial boundaries on what you can build", + "Clean Python class structure keeps your code organized, even as apps grow to multiple pages and features", + "Frontend and backend logic live together — no API contract drift, no separate deployments to coordinate", + "One test suite, one deployment — simpler CI/CD and developer experience", ], "cons": [ - "Great for simple CRUD apps and dashboards, then it breaks down", - "Once you need real complexity, you're fighting the tool instead of building", - "Workarounds pile up and become unmaintainable", + "React + backend means two codebases, two languages, API contracts to maintain", + "Django's templates and views are a different paradigm from modern component-based UIs", + "FastAPI + React requires coordinating two deployments and keeping frontend and backend in sync", ], }, { - "title": "Team Collaboration & Engineering Practices", + "title": "Built-in functionality.", + "icon": "Settings01Icon", + "description": "React is a UI library — no auth, database, or background jobs. Django has these but with a server-rendered focus. FastAPI is minimal by design. Reflex ships with ORM, database migrations, background jobs, file uploads, and role-based auth out of the box — all integrated with your Python UI code.", + "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 libraries", + "SSO and user management are included — no third-party auth services required", + ], + "cons": [ + "React is UI only — auth, database, and backend logic each need separate libraries and services", + "Django has built-ins but they're built for server-rendered apps — adapting for SPAs takes work", + "FastAPI is minimal — you add each piece (auth, ORM, etc.) yourself", + ], + }, + { + "title": "Deployment and production readiness.", "icon": "UserSwitchIcon", + "description": "React apps need a separate backend deployment. Django and FastAPI need proper WSGI/ASGI setup and often separate static hosting. Reflex compiles to a FastAPI backend with a React frontend — production-ready and container-friendly from day one. One build, one deploy.", "pros": [ - "Fits into normal engineering workflows — Git, PRs, CI/CD", - "Code review and automated testing work out of the box", - "Your whole team can collaborate using standard dev practices", + "Compiles to a FastAPI backend with a React frontend on an async web server — production-ready from the start", + "Fits into Git, pull requests, automated testing, and CI/CD from day one", + "What you build is what you ship — one deployment, no separate frontend and backend to orchestrate", ], "cons": [ - "Version control is difficult or impossible", - "Code review and testing are afterthoughts at best", - "Engineering best practices don't apply to proprietary drag-and-drop formats", + "React requires a separate backend and often a CDN for static assets — two deployments to manage", + "Django and FastAPI need manual configuration for production — WSGI, ASGI, static files, CORS", + "Split stack means more moving parts when it's time to deploy and scale", ], }, ] @@ -78,10 +98,14 @@ def compare(): return common_compare( kicker="Compare", - heading_lines=["How You Benefit ", "With Reflex vs. ", "Other Approaches"], - description="Other frameworks get you started fast, but Reflex lets you finish. Here's how Reflex compares to platforms like React, JavaScript, Django, and FastAPI.", + 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, JavaScript, Django, FastAPI", + top_right_title="React, Django, FastAPI", comparison_items=COMPARISON_ITEMS, ) diff --git a/pcweb/pages/migration/other_frameworks/views/explore.py b/pcweb/pages/migration/other_frameworks/views/explore.py index 18ca500f7..f033f2a75 100644 --- a/pcweb/pages/migration/other_frameworks/views/explore.py +++ b/pcweb/pages/migration/other_frameworks/views/explore.py @@ -3,33 +3,33 @@ FEATURES: list[Feature] = [ { - "title": "AI-Assisted App Development", - "description": "Generate UI and app logic faster with AI while keeping full code control.", - "icon": "ArtificialIntelligence04Icon", + "title": "One Language End to End", + "description": "Python for frontend and backend. No JavaScript required. Data scientists and backend devs build UIs without learning React.", + "icon": "PythonIcon", }, { - "title": "Real Python, Not Drag-and-Drop", - "description": "Write maintainable Python code that fits your existing engineering standards.", - "icon": "SourceCodeSquareIcon", + "title": "Architecture That Scales", + "description": "Declarative state, event-driven updates, and reactive re-renders. Only affected components update — no callback spaghetti.", + "icon": "SquareArrowExpand02Icon", }, { - "title": "Data Stack Integrations", - "description": "Connect databases, APIs, and internal services without low-code workarounds.", - "icon": "DatabaseIcon", + "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": "Security-First by Design", - "description": "Deploy with full control over infrastructure, access, and compliance boundaries.", - "icon": "ShieldEnergyIcon", + "title": "Clean, Maintainable Code", + "description": "Python class-based state keeps logic organized. Single codebase for frontend and backend.", + "icon": "SourceCodeSquareIcon", }, { - "title": "Production-Grade Performance", - "description": "Scale from internal tools to enterprise apps with robust backend capabilities.", - "icon": "DashboardSpeed01Icon", + "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": "Team-Friendly Workflows", - "description": "Use Git, PR reviews, and CI/CD workflows your team already trusts.", + "title": "What You Build Is What You Ship", + "description": "Compiles to FastAPI + React. Fits Git, CI/CD, and container deployment from day one. One build, one deploy.", "icon": "UserSwitchIcon", }, ] @@ -38,9 +38,9 @@ def explore(): return common_explore( kicker="Explore", - title_prefix="Build Your App With the Speed of ", - title_suffix="AI and Precision of Python", - description="Reflex is growing—and we're looking for people who care deeply about developer experience, clean abstractions.", + 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, ) From 897953dce197bb07526011561d816eac0dbdda47 Mon Sep 17 00:00:00 2001 From: Carlos Date: Wed, 4 Mar 2026 11:52:38 +0100 Subject: [PATCH 09/10] remove description and update other frameworks --- assets/logos/dark/gradient_r.svg | 78 +++++++++++++++- assets/logos/light/gradient_r.svg | 78 +++++++++++++++- pcweb/pages/blog/blog.py | 2 +- pcweb/pages/blog/page.py | 2 +- pcweb/pages/framework/views/footer_index.py | 2 +- pcweb/pages/migration/common/compare.py | 27 ++---- pcweb/pages/migration/common/explore.py | 8 +- pcweb/pages/migration/common/hero.py | 2 +- pcweb/pages/migration/common/quotes.py | 2 +- pcweb/pages/migration/low_code/__init__.py | 40 +++------ .../pages/migration/low_code/views/compare.py | 6 -- pcweb/pages/migration/no_code/__init__.py | 40 +++------ .../pages/migration/no_code/views/compare.py | 5 -- .../migration/other_ai_tools/__init__.py | 40 +++------ .../migration/other_ai_tools/views/compare.py | 5 -- .../migration/other_frameworks/__init__.py | 40 +++------ .../other_frameworks/views/compare.py | 88 ++++++++----------- .../other_frameworks/views/explore.py | 32 +++---- pcweb/views/cta_card.py | 2 +- pcweb/views/marketing_navbar.py | 15 ++-- 20 files changed, 283 insertions(+), 231 deletions(-) diff --git a/assets/logos/dark/gradient_r.svg b/assets/logos/dark/gradient_r.svg index 4ece52782..1c30d61ba 100644 --- a/assets/logos/dark/gradient_r.svg +++ b/assets/logos/dark/gradient_r.svg @@ -1 +1,77 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/logos/light/gradient_r.svg b/assets/logos/light/gradient_r.svg index 4ece52782..1c30d61ba 100644 --- a/assets/logos/light/gradient_r.svg +++ b/assets/logos/light/gradient_r.svg @@ -1 +1,77 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file 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/migration/common/compare.py b/pcweb/pages/migration/common/compare.py index ed64326d9..34d17143a 100644 --- a/pcweb/pages/migration/common/compare.py +++ b/pcweb/pages/migration/common/compare.py @@ -1,4 +1,4 @@ -from typing import NotRequired, TypedDict +from typing import TypedDict import reflex as rx import reflex_ui as ui @@ -9,14 +9,6 @@ class ComparisonItem(TypedDict): icon: str pros: list[str] cons: list[str] - description: NotRequired[str] - - -def comparison_description(description: str) -> rx.Component: - return rx.el.p( - description, - class_name="text-m-slate-11 dark:text-m-slate-4 lg:text-sm text-xs font-[475] leading-relaxed lg:px-12 lg:py-6 px-6 py-4 border-r border-m-slate-4 dark:border-m-slate-10 bg-m-slate-1 dark:bg-m-slate-10 border-b", - ) def comparison_title(title: str, icon: str) -> rx.Component: @@ -46,7 +38,7 @@ def pros_card(pros: list[str]) -> rx.Component: ) 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 rounded-xl bg-white-1 dark:bg-m-slate-11 w-full", + 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", ) @@ -82,7 +74,7 @@ def pros_cons_cards(pros: list[str], cons: list[str]) -> rx.Component: 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-medium font-mono border-r border-m-slate-4 dark:border-m-slate-10 lg:px-12 lg:py-3 p-6 bg-secondary-1 dark:bg-m-slate-10 border-t uppercase", + 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", ) @@ -109,9 +101,6 @@ def comparison_cards( *[ rx.fragment( comparison_title(item["title"], item["icon"]), - comparison_description(item["description"]) - if item.get("description") - else rx.fragment(), pros_cons_cards(item["pros"], item["cons"]), ) for item in comparison_items @@ -128,7 +117,7 @@ def comparison_cards( 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-10 mt-18 border-b mb-24 relative", + 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", ) @@ -146,7 +135,7 @@ def compare( rx.el.div( rx.el.p( kicker, - class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-m-slate-6", + 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), @@ -156,10 +145,10 @@ def compare( 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:top-[11rem] lg:self-start max-lg:self-center max-lg:items-center max-lg:text-center", + 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 py-24 max-lg:px-6", + 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-gradient-to-b from-white-1 to-m-slate-1 dark:from-m-slate-11 dark:to-m-slate-12 w-full relative", + 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 index 716e81b62..8da896eea 100644 --- a/pcweb/pages/migration/common/explore.py +++ b/pcweb/pages/migration/common/explore.py @@ -14,7 +14,9 @@ def feature_card(feature: Feature) -> rx.Component: return rx.el.div( rx.el.div( ui.icon( - feature["icon"], class_name="text-primary-10 dark:text-primary-9 size-5" + feature["icon"], + stroke_width=1.5, + class_name="text-primary-10 dark:text-primary-9 size-5 shrink-0", ), rx.el.span( feature["title"], @@ -50,7 +52,7 @@ def explore( rx.el.div( rx.el.p( kicker, - class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-m-slate-6", + class_name="text-sm font-[525] text-primary-10 max-lg:text-center dark:text-primary-9", ), rx.el.div( rx.el.h1( @@ -65,7 +67,7 @@ def explore( ), class_name="flex lg:flex-row flex-col gap-8 lg:gap-36", ), - class_name="relative flex flex-col gap-6 lg:py-24 py-16", + 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", diff --git a/pcweb/pages/migration/common/hero.py b/pcweb/pages/migration/common/hero.py index 117f33f09..402ac1fb9 100644 --- a/pcweb/pages/migration/common/hero.py +++ b/pcweb/pages/migration/common/hero.py @@ -36,7 +36,7 @@ def gradient_logo() -> rx.Component: loading="eager", custom_attrs={"fetchPriority": "high"}, ), - class_name="size-24 rounded-[1rem] bg-gradient-to-b from-m-slate-2 to-white-1 dark:from-m-slate-11 dark:to-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 absolute left-1/2 -translate-x-1/2 -translate-y-1/2 z-[1] pointer-events-none top-[13.5rem]", + 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]", ) diff --git a/pcweb/pages/migration/common/quotes.py b/pcweb/pages/migration/common/quotes.py index a59876981..d2a64b4b8 100644 --- a/pcweb/pages/migration/common/quotes.py +++ b/pcweb/pages/migration/common/quotes.py @@ -109,5 +109,5 @@ def quotes( quote_card(companies[0]), ), on_mount=active_company_cs.set_value(default_active_key), - class_name="flex lg:flex-row flex-col pb-24", + 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 index 463afa92c..ef446472c 100644 --- a/pcweb/pages/migration/low_code/__init__.py +++ b/pcweb/pages/migration/low_code/__init__.py @@ -1,16 +1,13 @@ import reflex as rx -import reflex_ui as ui -from pcweb.components.hosting_banner import HostingBannerState from pcweb.meta.meta import create_meta_tags from pcweb.pages.about.views.divider import divider -from pcweb.pages.framework.views.footer_index import footer_index from pcweb.pages.migration.low_code.views import compare, explore, hero, quotes -from pcweb.views.marketing_navbar import marketing_navbar +from pcweb.templates.marketing_page import marketing_page -@rx.page( - route="/migration/low-code", +@marketing_page( + path="/migration/low-code", title="Switch from Low Code to Reflex", meta=create_meta_tags( title="Switch from Low Code to Reflex", @@ -20,27 +17,14 @@ ) def low_code_migration_page() -> rx.Component: return rx.el.div( - marketing_navbar(), - rx.el.main( - rx.el.div( - hero(), - quotes(), - divider(), - compare(), - divider(), - explore(), - divider(), - footer_index(), - 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", - ), - class_name=ui.cn( - "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", - rx.cond( - HostingBannerState.is_banner_visible, - "lg:pt-[7rem] pt-[3.5rem]", - "lg:pt-[4.5rem] pt-[3.5rem]", - ), + 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/compare.py b/pcweb/pages/migration/low_code/views/compare.py index 1ef453246..4797e1ee5 100644 --- a/pcweb/pages/migration/low_code/views/compare.py +++ b/pcweb/pages/migration/low_code/views/compare.py @@ -5,7 +5,6 @@ { "title": "Architecture and state management.", "icon": "SquareArrowExpand02Icon", - "description": 'Streamlit uses a "script rerun" model where every widget change re-executes the entire Python script from top to bottom. Dash uses a callback-based architecture that becomes "callback spaghetti" as apps grow. Gradio is designed specifically for ML model demos. Reflex takes a declarative, state-driven approach where you define state classes and UI components in Python, and changes propagate reactively via WebSockets. Only affected components re-render.', "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", @@ -20,7 +19,6 @@ { "title": "Real-time and interactivity.", "icon": "ZapIcon", - "description": "Streamlit has no server push — real-time or background updates need client polling or workarounds. Dash has no native server-push feature. Gradio's interactivity is limited to input-output pairs for ML model inference. Reflex uses automatic WebSocket sync where state changes on the server instantly propagate to the browser.", "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", @@ -35,7 +33,6 @@ { "title": "Code structure and maintainability.", "icon": "SourceCodeSquareIcon", - "description": "Real Reflex projects cut approximately 50% of the code compared to equivalent Dash apps. Reflex's Python class-based state model keeps code organized. In Dash, the callback model fragments logic across scattered decorator functions. In Streamlit, the linear script model breaks down when you need complex page flows or shared state across views.", "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", @@ -50,7 +47,6 @@ { "title": "Customization and UI components.", "icon": "WebDesign01Icon", - "description": "Streamlit has a customization ceiling — deep CSS or HTML tweaks are difficult, and building truly bespoke widgets requires writing a Streamlit Component in React and TypeScript. Dash has a robust set of components but custom ones still require React. Gradio's customization is similarly limited. Reflex lets you wrap any React component directly from Python with fine-grained CSS control.", "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", @@ -63,7 +59,6 @@ { "title": "Built-in functionality.", "icon": "Settings01Icon", - "description": "Streamlit and Dash both lack built-in essentials for production apps — no auth, background tasks, or ORM. Gradio is focused narrowly on ML model demos. Reflex ships with ORM, database migrations, background jobs, file uploads, and role-based auth out of the box.", "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", @@ -78,7 +73,6 @@ { "title": "Deployment and the prototype-to-production gap.", "icon": "UserSwitchIcon", - "description": "Low-code Python frameworks are good for getting a first version up quickly, but not designed to take apps to production. Streamlit apps hit out-of-memory errors under load. Open-source Dash runs on Flask and requires manual infrastructure setup. Gradio struggles to scale for production. Reflex compiles to a FastAPI backend with a React frontend — production-ready and container-friendly from day one.", "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", diff --git a/pcweb/pages/migration/no_code/__init__.py b/pcweb/pages/migration/no_code/__init__.py index f9ca9c70b..061e6d6f6 100644 --- a/pcweb/pages/migration/no_code/__init__.py +++ b/pcweb/pages/migration/no_code/__init__.py @@ -1,16 +1,13 @@ import reflex as rx -import reflex_ui as ui -from pcweb.components.hosting_banner import HostingBannerState from pcweb.meta.meta import create_meta_tags from pcweb.pages.about.views.divider import divider -from pcweb.pages.framework.views.footer_index import footer_index from pcweb.pages.migration.no_code.views import compare, explore, hero, quotes -from pcweb.views.marketing_navbar import marketing_navbar +from pcweb.templates.marketing_page import marketing_page -@rx.page( - route="/migration/no-code", +@marketing_page( + path="/migration/no-code", title="Switch from No Code to Reflex", meta=create_meta_tags( title="Switch from No Code to Reflex", @@ -20,27 +17,14 @@ ) def no_code_migration_page() -> rx.Component: return rx.el.div( - marketing_navbar(), - rx.el.main( - rx.el.div( - hero(), - quotes(), - divider(), - compare(), - divider(), - explore(), - divider(), - footer_index(), - 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", - ), - class_name=ui.cn( - "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", - rx.cond( - HostingBannerState.is_banner_visible, - "lg:pt-[7rem] pt-[3.5rem]", - "lg:pt-[4.5rem] pt-[3.5rem]", - ), + 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/compare.py b/pcweb/pages/migration/no_code/views/compare.py index 559ff8ac5..ac0c15863 100644 --- a/pcweb/pages/migration/no_code/views/compare.py +++ b/pcweb/pages/migration/no_code/views/compare.py @@ -5,7 +5,6 @@ { "title": "Full control without the ceiling.", "icon": "CodesandboxIcon", - "description": "No-code tools (PowerBI, Tableau, Retool) get you to v1 fast, but you hit walls — custom logic, complex data flows, performance optimization, or anything the platform didn't anticipate. Despite being \"no-code,\" there is a significant learning curve for advanced features. With Reflex, you're writing Python, so there's no ceiling. You can do anything a full-stack app can do.", "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", @@ -20,7 +19,6 @@ { "title": "You own your code.", "icon": "SourceCodeSquareIcon", - "description": "No-code platforms create vendor lock-in. Your app lives on their infrastructure, in their proprietary format. With Reflex, it's your Python code — you can deploy it anywhere, version control it, and you're never hostage to a platform's pricing changes or shutdown.", "pros": [ "It's your Python code — deploy it anywhere, on any infrastructure", "Full version control so your codebase is portable and auditable", @@ -35,7 +33,6 @@ { "title": "Python ecosystem access.", "icon": "PythonIcon", - "description": "Data scientists, ML engineers, and backend devs already live in Python. Reflex lets them build internal tools or customer-facing apps using libraries they already know (pandas, scikit-learn, whatever) without learning JavaScript or being constrained by a drag-and-drop builder's integrations.", "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", @@ -50,7 +47,6 @@ { "title": "Scales with complexity.", "icon": "SquareArrowExpand02Icon", - "description": "No-code works great for simple dashboards, but even basic interactivity is a problem. Tools like Tableau and Power BI don't natively support CRUD operations at all. Once you need users to create, edit, or delete data, plus auth flows, real-time features, complex state management, or custom APIs, you're fighting the tool instead of building. Tools also struggle with performance at scale — whether it's dataset size limits, reliance on scheduled refreshes instead of real-time data, or apps slowing down as complexity grows. Reflex handles that complexity natively because it's just code.", "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", @@ -65,7 +61,6 @@ { "title": "Production-ready from day one.", "icon": "UserSwitchIcon", - "description": "No-code tools get you a prototype, but when it's time to hand it to IT or take it to production, you hit a wall. None of these tools support native version control, git integration, code review, or CI/CD pipelines. With Reflex, your app is built on real code from the start. It fits into the workflows your engineering team already uses — Git, PRs, automated testing, staging environments — so there's no painful \"rewrite it properly\" phase. What you demo is what you ship.", "pros": [ "Fits into Git, PRs, automated testing, staging environments from the start", 'What you demo is what you ship — no "rewrite it properly" phase', diff --git a/pcweb/pages/migration/other_ai_tools/__init__.py b/pcweb/pages/migration/other_ai_tools/__init__.py index 925455ae4..730134cad 100644 --- a/pcweb/pages/migration/other_ai_tools/__init__.py +++ b/pcweb/pages/migration/other_ai_tools/__init__.py @@ -1,16 +1,13 @@ import reflex as rx -import reflex_ui as ui -from pcweb.components.hosting_banner import HostingBannerState from pcweb.meta.meta import create_meta_tags from pcweb.pages.about.views.divider import divider -from pcweb.pages.framework.views.footer_index import footer_index from pcweb.pages.migration.other_ai_tools.views import compare, explore, hero, quotes -from pcweb.views.marketing_navbar import marketing_navbar +from pcweb.templates.marketing_page import marketing_page -@rx.page( - route="/migration/other-ai-tools", +@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", @@ -20,27 +17,14 @@ ) def other_ai_tools_migration_page() -> rx.Component: return rx.el.div( - marketing_navbar(), - rx.el.main( - rx.el.div( - hero(), - quotes(), - divider(), - compare(), - divider(), - explore(), - divider(), - footer_index(), - 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", - ), - class_name=ui.cn( - "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", - rx.cond( - HostingBannerState.is_banner_visible, - "lg:pt-[7rem] pt-[3.5rem]", - "lg:pt-[4.5rem] pt-[3.5rem]", - ), + 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/compare.py b/pcweb/pages/migration/other_ai_tools/views/compare.py index eeeb3f7aa..c11322006 100644 --- a/pcweb/pages/migration/other_ai_tools/views/compare.py +++ b/pcweb/pages/migration/other_ai_tools/views/compare.py @@ -5,7 +5,6 @@ { "title": "Full control without the ceiling.", "icon": "CodesandboxIcon", - "description": "AI app builders (ChatGPT, Claude, Replit, Lovable) get you to v1 fast, but you hit walls — custom logic, integrations beyond what the AI knows, or anything the platform didn't anticipate. What you get is what they generate. With Reflex, you're writing Python, so there's no ceiling. You can do anything a full-stack app can do.", "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", @@ -20,7 +19,6 @@ { "title": "You own your code.", "icon": "SourceCodeSquareIcon", - "description": "AI app builders create output that lives on their infrastructure, in their proprietary format. Your app is tied to their platform — you can't export it, version it properly, or deploy it yourself. With Reflex, it's your Python code — you can deploy it anywhere, version control it, and you're never hostage to a platform's pricing changes or shutdown.", "pros": [ "It's your Python code — deploy it anywhere, on any infrastructure", "Full version control so your codebase is portable and auditable", @@ -35,7 +33,6 @@ { "title": "Python ecosystem access.", "icon": "PythonIcon", - "description": "Data scientists, ML engineers, and backend devs already live in Python. Reflex lets them build internal tools or customer-facing apps using libraries they already know (pandas, scikit-learn, whatever) without being constrained by an AI's pre-built integrations or learning JavaScript. AI tools are limited to what the model knows how to integrate.", "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 pre-built integrations", @@ -50,7 +47,6 @@ { "title": "Scales with complexity.", "icon": "SquareArrowExpand02Icon", - "description": "AI app builders work great for simple demos, but once you need auth flows, real-time features, complex state management, custom APIs, or production-grade performance, you hit a wall. The generated output isn't designed for that. Reflex handles that complexity natively because it's just code.", "pros": [ "CRUD, auth flows, real-time features, complex state management, and custom APIs are all native", "Handles complexity natively because it's just code", @@ -65,7 +61,6 @@ { "title": "Production-ready from day one.", "icon": "UserSwitchIcon", - "description": "AI app builders get you a prototype, but when it's time to hand it to IT or take it to production, you hit a wall. None of these tools support native version control, git integration, code review, or CI/CD pipelines. With Reflex, your app is built on real code from the start. It fits into the workflows your engineering team already uses — Git, PRs, automated testing, staging environments — so there's no painful \"rewrite it properly\" phase. What you demo is what you ship.", "pros": [ "Fits into Git, PRs, automated testing, staging environments from the start", 'What you demo is what you ship — no "rewrite it properly" phase', diff --git a/pcweb/pages/migration/other_frameworks/__init__.py b/pcweb/pages/migration/other_frameworks/__init__.py index c14ec3c1f..06e496b6b 100644 --- a/pcweb/pages/migration/other_frameworks/__init__.py +++ b/pcweb/pages/migration/other_frameworks/__init__.py @@ -1,16 +1,13 @@ import reflex as rx -import reflex_ui as ui -from pcweb.components.hosting_banner import HostingBannerState from pcweb.meta.meta import create_meta_tags from pcweb.pages.about.views.divider import divider -from pcweb.pages.framework.views.footer_index import footer_index from pcweb.pages.migration.other_frameworks.views import compare, explore, hero, quotes -from pcweb.views.marketing_navbar import marketing_navbar +from pcweb.templates.marketing_page import marketing_page -@rx.page( - route="/migration/other-frameworks", +@marketing_page( + path="/migration/other-frameworks", title="Switch from Other Frameworks to Reflex", meta=create_meta_tags( title="Switch from Other Frameworks to Reflex", @@ -20,27 +17,14 @@ ) def other_frameworks_migration_page() -> rx.Component: return rx.el.div( - marketing_navbar(), - rx.el.main( - rx.el.div( - hero(), - quotes(), - divider(), - compare(), - divider(), - explore(), - divider(), - footer_index(), - 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", - ), - class_name=ui.cn( - "flex flex-col w-full justify-center items-center relative dark:bg-m-slate-12 bg-m-slate-1", - rx.cond( - HostingBannerState.is_banner_visible, - "lg:pt-[7rem] pt-[3.5rem]", - "lg:pt-[4.5rem] pt-[3.5rem]", - ), + 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/compare.py b/pcweb/pages/migration/other_frameworks/views/compare.py index e3b36c39e..b7c33283c 100644 --- a/pcweb/pages/migration/other_frameworks/views/compare.py +++ b/pcweb/pages/migration/other_frameworks/views/compare.py @@ -3,93 +3,77 @@ COMPARISON_ITEMS: list[ComparisonItem] = [ { - "title": "One language for frontend and backend.", + "title": "One language, one codebase", "icon": "PythonIcon", - "description": "React and JavaScript require a split stack — you maintain frontend in JS/TypeScript and backend in Python, Go, or Node. Django is full-stack Python but server-rendered, with a different paradigm for modern SPAs. FastAPI is backend only — you still need React or Vue for the UI. Reflex gives you both in Python: declarative UI components and backend logic in one codebase.", "pros": [ - "One language end to end — no context switching between JavaScript and Python", - "Data scientists, ML engineers, and backend devs build UIs without learning React", - "Single codebase for frontend and backend — simpler architecture, easier to maintain", + "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": [ - "React requires JavaScript or TypeScript for the frontend — a separate stack to learn and maintain", - "Django is server-rendered — building modern SPAs with real-time updates requires additional tooling", - "FastAPI is backend only — you still need a separate frontend framework and two deployments", + "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": "Architecture and state management.", - "icon": "SquareArrowExpand02Icon", - "description": "React uses a component-based model with hooks and external state libraries. Django uses server-side request/response. FastAPI has no built-in frontend. Reflex takes a declarative, state-driven approach where you define state classes and UI components in Python, and changes propagate reactively via WebSockets. Only affected components re-render.", + "title": "Built-in features vs. assembly required", + "icon": "Settings01Icon", "pros": [ - "Declarative state and event-driven updates — only affected components re-render", - "User sessions remember where they are — multi-step workflows and real-time updates work without extra effort", - "The event-driven model keeps your code clean and organized as your app grows", + "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": [ - "React's ecosystem of state libraries (Redux, Zustand, etc.) adds complexity — you choose and maintain the stack", - "Django's request/response model doesn't natively support real-time or reactive updates", - "FastAPI has no frontend — real-time state sync requires building it yourself", + "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": "Real-time and interactivity.", + "title": "Development speed", "icon": "ZapIcon", - "description": "React can do real-time but requires manual WebSocket setup or third-party services. Django has no native server-push. FastAPI supports WebSockets but you build the frontend integration yourself. Reflex uses automatic WebSocket sync where state changes on the server instantly propagate to the browser.", "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 reacts to user actions as they happen", + "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": [ - "React has no built-in server push — real-time needs manual WebSocket setup or services like Pusher", - "Django has no native real-time — you add Channels and more infrastructure", - "FastAPI has WebSockets but no integrated frontend — you wire it up yourself", + "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": "Code structure and maintainability.", - "icon": "SourceCodeSquareIcon", - "description": "React apps split logic across components, hooks, and often a separate API layer. Django keeps things in one place but with a different mental model for SPAs. FastAPI + React means two codebases, two test suites. Reflex's Python class-based state model keeps frontend and backend logic organized in one place.", + "title": "Modern frontend without JavaScript", + "icon": "WebDesign01Icon", "pros": [ - "Clean Python class structure keeps your code organized, even as apps grow to multiple pages and features", - "Frontend and backend logic live together — no API contract drift, no separate deployments to coordinate", - "One test suite, one deployment — simpler CI/CD and developer experience", + "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": [ - "React + backend means two codebases, two languages, API contracts to maintain", - "Django's templates and views are a different paradigm from modern component-based UIs", - "FastAPI + React requires coordinating two deployments and keeping frontend and backend in sync", + "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": "Built-in functionality.", - "icon": "Settings01Icon", - "description": "React is a UI library — no auth, database, or background jobs. Django has these but with a server-rendered focus. FastAPI is minimal by design. Reflex ships with ORM, database migrations, background jobs, file uploads, and role-based auth out of the box — all integrated with your Python UI code.", + "title": "Performance and real-time capabilities", + "icon": "SquareArrowExpand02Icon", "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 libraries", - "SSO and user management are included — no third-party auth services required", + "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": [ - "React is UI only — auth, database, and backend logic each need separate libraries and services", - "Django has built-ins but they're built for server-rendered apps — adapting for SPAs takes work", - "FastAPI is minimal — you add each piece (auth, ORM, etc.) yourself", + "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": "Deployment and production readiness.", - "icon": "UserSwitchIcon", - "description": "React apps need a separate backend deployment. Django and FastAPI need proper WSGI/ASGI setup and often separate static hosting. Reflex compiles to a FastAPI backend with a React frontend — production-ready and container-friendly from day one. One build, one deploy.", + "title": "Scaling and maintainability", + "icon": "SourceCodeSquareIcon", "pros": [ - "Compiles to a FastAPI backend with a React frontend on an async web server — production-ready from the start", - "Fits into Git, pull requests, automated testing, and CI/CD from day one", - "What you build is what you ship — one deployment, no separate frontend and backend to orchestrate", + "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": [ - "React requires a separate backend and often a CDN for static assets — two deployments to manage", - "Django and FastAPI need manual configuration for production — WSGI, ASGI, static files, CORS", - "Split stack means more moving parts when it's time to deploy and scale", + "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", ], }, ] diff --git a/pcweb/pages/migration/other_frameworks/views/explore.py b/pcweb/pages/migration/other_frameworks/views/explore.py index f033f2a75..3ae3d65a8 100644 --- a/pcweb/pages/migration/other_frameworks/views/explore.py +++ b/pcweb/pages/migration/other_frameworks/views/explore.py @@ -3,34 +3,34 @@ FEATURES: list[Feature] = [ { - "title": "One Language End to End", - "description": "Python for frontend and backend. No JavaScript required. Data scientists and backend devs build UIs without learning React.", + "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": "Architecture That Scales", - "description": "Declarative state, event-driven updates, and reactive re-renders. Only affected components update — no callback spaghetti.", - "icon": "SquareArrowExpand02Icon", + "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": "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.", + "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": "Clean, Maintainable Code", - "description": "Python class-based state keeps logic organized. Single codebase for frontend and backend.", - "icon": "SourceCodeSquareIcon", + "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": "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": "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": "What You Build Is What You Ship", - "description": "Compiles to FastAPI + React. Fits Git, CI/CD, and container deployment from day one. One build, one deploy.", - "icon": "UserSwitchIcon", + "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", }, ] 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 3989ed27d..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 @@ -382,22 +387,22 @@ def solutions_content() -> rx.Component: ( "Switch from No Code", "WebDesign01Icon", - "/migration/no-code", + no_code_migration_page.path, ), ( "Switch from Low Code", "SourceCodeSquareIcon", - "/migration/low-code", + low_code_migration_page.path, ), ( "Switch from Other Frameworks", "CodeIcon", - "/migration/other-frameworks", + other_frameworks_migration_page.path, ), ( "Switch from Other AI tools", "ArtificialIntelligence04Icon", - "/migration/other-ai-tools", + other_ai_tools_migration_page.path, ), ], ), @@ -443,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", ), From cd766b358f13d622aecc498920955c46471391d0 Mon Sep 17 00:00:00 2001 From: Carlos Date: Fri, 6 Mar 2026 14:03:54 +0100 Subject: [PATCH 10/10] update ai app builder page --- assets/migration/dark/chatgpt.svg | 1 - assets/migration/dark/cursor.svg | 1 + assets/migration/light/chatgpt.svg | 1 - assets/migration/light/cursor.svg | 1 + .../migration/other_ai_tools/views/compare.py | 164 ++++++++++++------ .../migration/other_ai_tools/views/explore.py | 34 ++-- .../migration/other_ai_tools/views/hero.py | 4 +- 7 files changed, 134 insertions(+), 72 deletions(-) delete mode 100644 assets/migration/dark/chatgpt.svg create mode 100644 assets/migration/dark/cursor.svg delete mode 100644 assets/migration/light/chatgpt.svg create mode 100644 assets/migration/light/cursor.svg diff --git a/assets/migration/dark/chatgpt.svg b/assets/migration/dark/chatgpt.svg deleted file mode 100644 index 4268c44de..000000000 --- a/assets/migration/dark/chatgpt.svg +++ /dev/null @@ -1 +0,0 @@ - \ 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/light/chatgpt.svg b/assets/migration/light/chatgpt.svg deleted file mode 100644 index 4268c44de..000000000 --- a/assets/migration/light/chatgpt.svg +++ /dev/null @@ -1 +0,0 @@ - \ 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/pcweb/pages/migration/other_ai_tools/views/compare.py b/pcweb/pages/migration/other_ai_tools/views/compare.py index c11322006..9588a648a 100644 --- a/pcweb/pages/migration/other_ai_tools/views/compare.py +++ b/pcweb/pages/migration/other_ai_tools/views/compare.py @@ -1,92 +1,154 @@ +import reflex as rx + from pcweb.pages.migration.common.compare import ComparisonItem from pcweb.pages.migration.common.compare import compare as common_compare -COMPARISON_ITEMS: list[ComparisonItem] = [ +AI_APP_BUILDERS_ITEMS: list[ComparisonItem] = [ { - "title": "Full control without the ceiling.", - "icon": "CodesandboxIcon", + "title": "Built on a real Python framework, not a black box.", + "icon": "PythonIcon", "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", - "You own every line of code — no black-box AI output you can't modify", + "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": [ - "AI tools hit walls on custom logic, integrations, and anything the platform didn't anticipate", - "What you get is what they generate — no deep customization without fighting the tool", - "Platform limitations dictate what's possible, not your requirements", + "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": "You own your code.", - "icon": "SourceCodeSquareIcon", + "title": "Works with your existing infrastructure.", + "icon": "CloudServerIcon", "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", + "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": [ - "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", + "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": "Python ecosystem access.", - "icon": "PythonIcon", + "title": "Enterprise guardrails and governance.", + "icon": "Layers01Icon", "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 pre-built integrations", - "Data scientists, ML engineers, and backend devs can build internal tools or customer-facing apps directly", + "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": [ - "AI tools constrain you to their pre-built integrations and what the model knows", - "Requires workarounds or is impossible for custom libraries and data sources", - "Data scientists and ML engineers can't use the Python libraries they already know", + "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": "Scales with complexity.", + "title": "Deploy anywhere, scale without limits.", "icon": "SquareArrowExpand02Icon", "pros": [ - "CRUD, auth flows, real-time features, complex state management, and custom APIs are all native", - "Handles complexity natively because it's just code", - "No artificial boundaries on what you can build", + "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": [ - "AI-generated apps break down once you need real complexity — auth, real-time, or production scale", - "The output isn't designed for maintainable, extensible codebases", - "Once you need users to do more than view a demo, you're fighting the tool instead of building", + "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": "Production-ready from day one.", - "icon": "UserSwitchIcon", + "title": "Enterprise security and data privacy.", + "icon": "DatabaseIcon", "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", + "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": [ - "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", + "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 common_compare( - kicker="Compare", - heading_lines=[ - "How You Benefit ", - "With Reflex vs. ", - "ChatGPT, Claude, Replit, Lovable", - ], - description="AI app builders get you prototyping fast. Reflex lets you finish. Here's how Reflex compares to platforms like ChatGPT, Claude, Replit, and Lovable.", - top_left_title="Reflex", - top_right_title="ChatGPT, Claude, Replit, Lovable", - comparison_items=COMPARISON_ITEMS, + 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", ) diff --git a/pcweb/pages/migration/other_ai_tools/views/explore.py b/pcweb/pages/migration/other_ai_tools/views/explore.py index 051e62503..4c450f123 100644 --- a/pcweb/pages/migration/other_ai_tools/views/explore.py +++ b/pcweb/pages/migration/other_ai_tools/views/explore.py @@ -8,29 +8,29 @@ "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": "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": "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": "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": "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": "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": "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": "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": "Data Stack Integrations", - "description": "Connect databases, APIs, and internal services without platform workarounds. No lock-in to what the AI knows.", - "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", }, ] @@ -39,8 +39,8 @@ def explore(): return common_explore( kicker="Explore", title_prefix="Why Reflex Over ", - title_suffix="ChatGPT, Claude, Replit, Lovable", - description="AI app builders get you prototyping fast, but Reflex lets you finish. Pure Python, no ceiling, you own your code.", + 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, ) diff --git a/pcweb/pages/migration/other_ai_tools/views/hero.py b/pcweb/pages/migration/other_ai_tools/views/hero.py index 854a66a34..c65aeac6b 100644 --- a/pcweb/pages/migration/other_ai_tools/views/hero.py +++ b/pcweb/pages/migration/other_ai_tools/views/hero.py @@ -3,8 +3,8 @@ HERO_LOGOS: list[HeroLogo] = [ { - "image_name": "chatgpt.svg", - "alt": "ChatGPT Logo", + "image_name": "cursor.svg", + "alt": "Cursor Logo", "class_name": "top-[9.5rem] -ml-[10.5rem]", }, {