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