From 71ffeecf644ba1c1e11359dfdd7c0d43eb3c6348 Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 15 Dec 2025 16:57:25 +0100 Subject: [PATCH 01/10] ENG-8503: finance landing --- assets/companies/dark/bayesline.svg | 1 + assets/companies/dark/credit_agricole.svg | 1 + assets/companies/dark/man_group.svg | 1 + assets/companies/dark/world_bank.svg | 1 + assets/companies/light/bayesline.svg | 1 + assets/companies/light/credit_agricole.svg | 1 + assets/companies/light/man_group.svg | 1 + assets/companies/light/world_bank.svg | 1 + assets/custom-colors.css | 55 +++ assets/tailwind-theme.css | 28 ++ pcweb/components/icons/icons.py | 120 ++--- pcweb/pages/__init__.py | 2 +- pcweb/pages/gallery/gallery.py | 2 +- pcweb/pages/pricing/plan_cards.py | 7 +- pcweb/pages/use_cases/finance/__init__.py | 33 ++ .../use_cases/finance/views/features_1.py | 41 ++ .../use_cases/finance/views/features_2.py | 49 ++ .../use_cases/finance/views/final_section.py | 63 +++ pcweb/pages/use_cases/finance/views/hero.py | 90 ++++ pcweb/pages/use_cases/finance/views/quotes.py | 64 +++ .../use_cases/finance/views/social_proof.py | 40 ++ pcweb/pages/use_cases/finance/views/stats.py | 42 ++ .../use_cases/finance/views/text_section_1.py | 26 + .../use_cases/finance/views/text_section_2.py | 26 + .../use_cases/finance/views/text_section_3.py | 22 + .../use_cases/finance/views/text_section_4.py | 22 + pcweb/pages/use_cases/finance_landing.py | 462 ------------------ pcweb/pages/use_cases/finance_use_case.py | 7 - pcweb/pages/use_cases/use_cases.md | 2 +- 29 files changed, 660 insertions(+), 551 deletions(-) create mode 100644 assets/companies/dark/bayesline.svg create mode 100644 assets/companies/dark/credit_agricole.svg create mode 100644 assets/companies/dark/man_group.svg create mode 100644 assets/companies/dark/world_bank.svg create mode 100644 assets/companies/light/bayesline.svg create mode 100644 assets/companies/light/credit_agricole.svg create mode 100644 assets/companies/light/man_group.svg create mode 100644 assets/companies/light/world_bank.svg create mode 100644 pcweb/pages/use_cases/finance/__init__.py create mode 100644 pcweb/pages/use_cases/finance/views/features_1.py create mode 100644 pcweb/pages/use_cases/finance/views/features_2.py create mode 100644 pcweb/pages/use_cases/finance/views/final_section.py create mode 100644 pcweb/pages/use_cases/finance/views/hero.py create mode 100644 pcweb/pages/use_cases/finance/views/quotes.py create mode 100644 pcweb/pages/use_cases/finance/views/social_proof.py create mode 100644 pcweb/pages/use_cases/finance/views/stats.py create mode 100644 pcweb/pages/use_cases/finance/views/text_section_1.py create mode 100644 pcweb/pages/use_cases/finance/views/text_section_2.py create mode 100644 pcweb/pages/use_cases/finance/views/text_section_3.py create mode 100644 pcweb/pages/use_cases/finance/views/text_section_4.py delete mode 100644 pcweb/pages/use_cases/finance_landing.py delete mode 100644 pcweb/pages/use_cases/finance_use_case.py diff --git a/assets/companies/dark/bayesline.svg b/assets/companies/dark/bayesline.svg new file mode 100644 index 0000000000..c8de1749d7 --- /dev/null +++ b/assets/companies/dark/bayesline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/dark/credit_agricole.svg b/assets/companies/dark/credit_agricole.svg new file mode 100644 index 0000000000..aadf9fa147 --- /dev/null +++ b/assets/companies/dark/credit_agricole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/dark/man_group.svg b/assets/companies/dark/man_group.svg new file mode 100644 index 0000000000..4d7e7bbec3 --- /dev/null +++ b/assets/companies/dark/man_group.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/dark/world_bank.svg b/assets/companies/dark/world_bank.svg new file mode 100644 index 0000000000..28e1c812bb --- /dev/null +++ b/assets/companies/dark/world_bank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/light/bayesline.svg b/assets/companies/light/bayesline.svg new file mode 100644 index 0000000000..67b3bf3ebf --- /dev/null +++ b/assets/companies/light/bayesline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/light/credit_agricole.svg b/assets/companies/light/credit_agricole.svg new file mode 100644 index 0000000000..66563a6803 --- /dev/null +++ b/assets/companies/light/credit_agricole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/light/man_group.svg b/assets/companies/light/man_group.svg new file mode 100644 index 0000000000..14d8ed4be2 --- /dev/null +++ b/assets/companies/light/man_group.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/light/world_bank.svg b/assets/companies/light/world_bank.svg new file mode 100644 index 0000000000..78543be374 --- /dev/null +++ b/assets/companies/light/world_bank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/custom-colors.css b/assets/custom-colors.css index d371e95b39..06b1dba0a0 100644 --- a/assets/custom-colors.css +++ b/assets/custom-colors.css @@ -39,6 +39,34 @@ --glow: #EBE4FF; --wave-line-1: #D4CAFE; --wave-line-2: #EBE4FF; + /* Marketing Colors */ + --m-slate-1: #FCFCFD; + --m-slate-2: #F9F9FB; + --m-slate-3: #F0F0F3; + --m-slate-4: #E8E8EC; + --m-slate-5: #E0E1E6; + --m-slate-6: #D9D9E0; + --m-slate-7: #CDCED6; + --m-slate-8: #B9BBC6; + --m-slate-9: #8B8D98; + --m-slate-10: #80838D; + --m-slate-11: #60646C; + --m-slate-12: #262B31; + --m-slate-13: #1C2024; + --m-slate-14: #1A1B1D; + --m-slate-15: #151618; + --m-violet-1: #FDFCFE; + --m-violet-2: #FAF8FF; + --m-violet-3: #F4F0FE; + --m-violet-4: #EBE4FF; + --m-violet-5: #E1D9FF; + --m-violet-6: #D4CAFE; + --m-violet-7: #C2B5F5; + --m-violet-8: #AA99EC; + --m-violet-9: #6E56CF; + --m-violet-10: #654DC4; + --m-violet-11: #6550B9; + --m-violet-12: #2F265F; } .dark, @@ -92,4 +120,31 @@ --glow: #261958; --wave-line-1: #2F1C78; --wave-line-2: #261958; + --m-slate-1: #FCFCFD; + --m-slate-2: #F9F9FB; + --m-slate-3: #F0F0F3; + --m-slate-4: #E8E8EC; + --m-slate-5: #E0E1E6; + --m-slate-6: #D9D9E0; + --m-slate-7: #CDCED6; + --m-slate-8: #B9BBC6; + --m-slate-9: #8B8D98; + --m-slate-10: #80838D; + --m-slate-11: #60646C; + --m-slate-12: #262B31; + --m-slate-13: #1C2024; + --m-slate-14: #1A1B1D; + --m-slate-15: #151618; + --m-violet-1: #FDFCFE; + --m-violet-2: #FAF8FF; + --m-violet-3: #F4F0FE; + --m-violet-4: #EBE4FF; + --m-violet-5: #E1D9FF; + --m-violet-6: #D4CAFE; + --m-violet-7: #C2B5F5; + --m-violet-8: #AA99EC; + --m-violet-9: #6E56CF; + --m-violet-10: #654DC4; + --m-violet-11: #6550B9; + --m-violet-12: #2F265F; } \ No newline at end of file diff --git a/assets/tailwind-theme.css b/assets/tailwind-theme.css index ef28fe5722..33ca88049a 100644 --- a/assets/tailwind-theme.css +++ b/assets/tailwind-theme.css @@ -1071,6 +1071,34 @@ --color-bronze-a10: var(--bronze-a10); --color-bronze-a11: var(--bronze-a11); --color-bronze-a12: var(--bronze-a12); + /* Marketing Colors */ + --color-m-slate-1: var(--m-slate-1); + --color-m-slate-2: var(--m-slate-2); + --color-m-slate-3: var(--m-slate-3); + --color-m-slate-4: var(--m-slate-4); + --color-m-slate-5: var(--m-slate-5); + --color-m-slate-6: var(--m-slate-6); + --color-m-slate-7: var(--m-slate-7); + --color-m-slate-8: var(--m-slate-8); + --color-m-slate-9: var(--m-slate-9); + --color-m-slate-10: var(--m-slate-10); + --color-m-slate-11: var(--m-slate-11); + --color-m-slate-12: var(--m-slate-12); + --color-m-slate-13: var(--m-slate-13); + --color-m-slate-14: var(--m-slate-14); + --color-m-slate-15: var(--m-slate-15); + --color-m-violet-1: var(--m-violet-1); + --color-m-violet-2: var(--m-violet-2); + --color-m-violet-3: var(--m-violet-3); + --color-m-violet-4: var(--m-violet-4); + --color-m-violet-5: var(--m-violet-5); + --color-m-violet-6: var(--m-violet-6); + --color-m-violet-7: var(--m-violet-7); + --color-m-violet-8: var(--m-violet-8); + --color-m-violet-9: var(--m-violet-9); + --color-m-violet-10: var(--m-violet-10); + --color-m-violet-11: var(--m-violet-11); + --color-m-violet-12: var(--m-violet-12); /* Font */ --font-sans: var(--font-instrument-sans); diff --git a/pcweb/components/icons/icons.py b/pcweb/components/icons/icons.py index e99c1bb90e..6e9e218c9d 100644 --- a/pcweb/components/icons/icons.py +++ b/pcweb/components/icons/icons.py @@ -1,5 +1,3 @@ -from typing import Literal - import reflex as rx github = """ @@ -485,6 +483,39 @@ """ +ai_04 = """ + +""" + +flow_connection = """ + +""" + +refresh_dot = """ + +""" + +layers_01 = """ + + + +""" + +zap_01 = """ + +""" + +python_01 = """ + +""" + +shield_key = """ + +""" + +chart_up = """ + +""" ICONS = { # Socials @@ -557,83 +588,18 @@ "db": db, "api": api, "doc": doc, + "ai-04": ai_04, + "flow-connection": flow_connection, + "refresh-dot": refresh_dot, + "layers-01": layers_01, + "zap-01": zap_01, + "python-01": python_01, + "shield-key": shield_key, + "chart-up": chart_up, } -LiteralIcon = Literal[ - "github", - "discord", - "twitter", - "sun", - "moon", - "arrow_right", - "copy", - "arrow_down", - "arrow_down_big", - "new_tab", - "eye", - "select", - "history", - "clipboard", - "bottom_logo", - "radial_small", - "radial_big", - "feather", - "cloud", - "database", - "star", - "fork", - "eye_big", - "image_ai", - "dice", - "contributors", - "badge_logo", - "github_navbar", - "discord_navbar", - "send", - "chat_bubble", - "image_ai_small", - "chart", - "code_custom", - "message_form", - "wave_pattern", - "backend_db", - "backend_async", - "backend_compatible", - "backend_auth", - "copy_pip", - "forum", - "python", - "package", - "document_code", - "infinity", - "analytics", - "globe", - "chevron_right", - "ai-chat-02", - "dollar", - "webpage", - "arrow_top_right", - "quote", - "linkedin", - "image-03", - "shield", - "play_video", - "zap", - "cancel-circle", - "arrow-fill-down", - "alert", - "browser", - "checkmark", - "feather_unstyled", - "db", -] - - -def get_icon(icon: LiteralIcon, class_name: str = "", **props) -> rx.Component: - if icon not in ICONS: - raise ValueError( - f"Icon '{icon}' not found. Available icons: {list(ICONS.keys())}" - ) + +def get_icon(icon: str, class_name: str = "", **props) -> rx.Component: return rx.html( ICONS[icon], class_name=f"flex justify-center items-center {class_name}", diff --git a/pcweb/pages/__init__.py b/pcweb/pages/__init__.py index 10ba7d0a9a..136a17d8f2 100644 --- a/pcweb/pages/__init__.py +++ b/pcweb/pages/__init__.py @@ -20,7 +20,7 @@ from .sales import sales as sales from .security.security import security_page as security_page from .to_be_booked import to_be_booked as to_be_booked -from .use_cases.finance_use_case import finance_use_case_page as finance_use_case_page +from .use_cases.finance import finance_use_case_page as finance_use_case_page from .use_cases.use_cases import use_cases_page as use_cases_page routes = [ diff --git a/pcweb/pages/gallery/gallery.py b/pcweb/pages/gallery/gallery.py index 03065d495f..a4ef3ffa3e 100644 --- a/pcweb/pages/gallery/gallery.py +++ b/pcweb/pages/gallery/gallery.py @@ -169,7 +169,7 @@ def extended_gallery_grid_item( rx.el.div( rx.el.span( app_name, - class_name="text-sm font-semibold text-m-slate-13 dark:text-m-slate-3 truncate min-w-0 max-w-[90%]", + class_name="text-sm font-semibold text-slate-12 dark:text-m-slate-3 truncate min-w-0 max-w-[90%]", ), rx.el.div( rx.el.span( diff --git a/pcweb/pages/pricing/plan_cards.py b/pcweb/pages/pricing/plan_cards.py index a110f20a35..e7110ed068 100644 --- a/pcweb/pages/pricing/plan_cards.py +++ b/pcweb/pages/pricing/plan_cards.py @@ -53,11 +53,12 @@ class Feature(NamedTuple): component: rx.Component | None = None -def radial_circle(violet: bool = False) -> rx.Component: +def radial_circle(violet: bool = False, class_name: str = "") -> rx.Component: """Create a radial circle background image component. Args: violet: Whether to use the violet variant. Defaults to False. + class_name: Additional class names to add to the component. Returns: A Reflex image component configured as a radial circle background. @@ -71,7 +72,9 @@ def radial_circle(violet: bool = False) -> rx.Component: ), alt="Radial circle", loading="lazy", - class_name="top-0 right-0 absolute pointer-events-none z-[-1]", + class_name=ui.cn( + "top-0 right-0 absolute pointer-events-none z-[-1]", class_name + ), ) diff --git a/pcweb/pages/use_cases/finance/__init__.py b/pcweb/pages/use_cases/finance/__init__.py new file mode 100644 index 0000000000..72a3ef7fe4 --- /dev/null +++ b/pcweb/pages/use_cases/finance/__init__.py @@ -0,0 +1,33 @@ +import reflex as rx + +from pcweb.meta.meta import meta_tags +from pcweb.pages.use_cases.finance.views.features_1 import features_1 +from pcweb.pages.use_cases.finance.views.features_2 import features_2 +from pcweb.pages.use_cases.finance.views.final_section import final_section +from pcweb.pages.use_cases.finance.views.hero import hero +from pcweb.pages.use_cases.finance.views.quotes import quotes +from pcweb.pages.use_cases.finance.views.social_proof import social_proof +from pcweb.pages.use_cases.finance.views.stats import stats +from pcweb.pages.use_cases.finance.views.text_section_1 import text_section_1 +from pcweb.pages.use_cases.finance.views.text_section_2 import text_section_2 +from pcweb.pages.use_cases.finance.views.text_section_3 import text_section_3 +from pcweb.pages.use_cases.finance.views.text_section_4 import text_section_4 +from pcweb.templates.mainpage import mainpage + + +@mainpage(path="/use-cases/finance", title="Finance Use Case - Reflex", meta=meta_tags) +def finance_use_case_page() -> rx.Component: + return rx.el.div( + hero(), + social_proof(), + text_section_1(), + features_1(), + text_section_2(), + quotes(), + text_section_3(), + features_2(), + text_section_4(), + stats(), + final_section(), + class_name="flex flex-col size-full justify-center items-center max-w-[calc(100vw-2rem)] mx-auto", + ) diff --git a/pcweb/pages/use_cases/finance/views/features_1.py b/pcweb/pages/use_cases/finance/views/features_1.py new file mode 100644 index 0000000000..d6b354299c --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/features_1.py @@ -0,0 +1,41 @@ +import reflex as rx + +from pcweb.components.icons import get_icon + + +def feature_card(icon: str, title: str, description: str) -> rx.Component: + return rx.el.div( + get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), + rx.el.span(title, class_name="font-semibold text-slate-12 text-lg mt-2"), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + class_name="flex flex-col items-start gap-2 p-10 lg:border-r border-b border-slate-3", + ) + + +def features_1() -> rx.Component: + return rx.el.section( + feature_card( + "ai-04", + "Ship AI-Powered Tools Securely", + "Build chat-based assistants and RAG apps in Python, deployed inside your own cloud or on-prem, with full control over where data lives.", + ), + feature_card( + "refresh-dot", + "Modernize Legacy Internal Apps", + "Replace fragile in-house dashboards with maintainable Python apps that plug into your existing data stack.", + ), + feature_card( + "flow-connection", + "Automate Workflows, Not Just Reports", + "Turn manual compliance checks, KYC workflows, and operations processes into interactive apps—tied to your systems, not screenshots.", + ), + feature_card( + "layers-01", + "Orchestrate End-to-End Lifecycles", + "Let researchers, analysts, and quants move from 'run a script in a Jupyter notebook' to 'share a full app' using the same language they already know.", + ), + class_name="grid lg:grid-cols-2 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-l border-slate-3 relative overflow-hidden border-t", + ) diff --git a/pcweb/pages/use_cases/finance/views/features_2.py b/pcweb/pages/use_cases/finance/views/features_2.py new file mode 100644 index 0000000000..4020348ae2 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/features_2.py @@ -0,0 +1,49 @@ +import reflex as rx + +from pcweb.components.icons import get_icon + + +def feature_card(icon: str, stat: str, title: str, description: str) -> rx.Component: + return rx.el.div( + get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), + rx.el.span( + stat, + class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-sm mt-4", + ), + rx.el.span(title, class_name="font-semibold text-slate-12 text-lg mt-4"), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium mt-2", + ), + class_name="flex flex-col items-start p-10", + ) + + +def features_2() -> rx.Component: + return rx.el.section( + feature_card( + "zap-01", + "Speed to Production", + "Ship Internal Tools 10x Faster", + "Reflex lets Python teams build production-grade apps without leaving their language. Crédit Agricole’s R&D team built a full chatbot analytics dashboard in two days and is rolling it out to 100+ users, without adding a single React engineer.", + ), + feature_card( + "python-01", + "Python-first Flexibility", + "Let Experts Build, Not Just Consume", + "At Man Group, 50+ researchers write Python, not JavaScript. Reflex gives them a full-Python framework to create dashboards and model views without touching javascript front-end code, while the platform team wraps their internal design system.", + ), + feature_card( + "shield-key", + "Full Control & Enterprise Deployment", + "Run in Your Cloud, Offline if Needed", + "Reflex Enterprise runs fully on-prem or in your own cloud. Man Group deploys Reflex apps in air-gapped environments; CACIB and the World Bank run Reflex inside internal AWS and Azure environments with their own SSO, logging, and infra.", + ), + feature_card( + "chart-up", + "Agility & Cost Efficiency", + "Do More With Your Python Team", + "Bayesline avoided hiring a front-end engineer and shipped a fintech SaaS app entirely in Python; One engineer can do the work of two by collapsing front- and back-end into a single Reflex codebase.", + ), + class_name="grid lg:grid-cols-4 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden border-t lg:divide-x divide-slate-3 max-lg:divide-y", + ) diff --git a/pcweb/pages/use_cases/finance/views/final_section.py b/pcweb/pages/use_cases/finance/views/final_section.py new file mode 100644 index 0000000000..b50eb6bed1 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/final_section.py @@ -0,0 +1,63 @@ +import reflex as rx +import reflex_ui as ui +from reflex_ui.blocks.calcom import get_cal_attrs + +from pcweb.constants import REFLEX_BUILD_URL +from pcweb.pages.pricing.plan_cards import radial_circle + + +def right_content() -> rx.Component: + return rx.el.div( + rx.el.h2( + "Spin Up Your First Finance App", + class_name="text-slate-12 text-2xl font-semibold", + ), + rx.el.p( + "Connect your data source, and ship a working internal tool in an afternoon—no JavaScript required.", + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium mt-2", + ), + ui.link( + render_=ui.button( + "Go to the builder", + size="lg", + variant="outline", + class_name="w-fit font-semibold lg:mt-auto mt-8 text-m-slate-11 dark:text-m-slate-9 border-m-slate-5 dark:border-m-slate-12", + ), + to=REFLEX_BUILD_URL, + target="_blank", + ), + class_name="flex flex-col lg:p-20 p-8 h-full", + ) + + +def text() -> rx.Component: + return rx.el.div( + radial_circle(class_name="dark:opacity-50"), + rx.el.h2( + "Make Your Toughest Internal Tool Real With Reflex", + class_name="text-slate-12 lg:text-3xl text-2xl font-semibold", + ), + rx.el.p( + "Have a spreadsheet-driven workflow, a fragile Streamlit app, or a dashboard that never quite got to production? We’ll show you what it looks like as a Reflex app in pure Python.", + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + ui.button( + ui.icon("Calendar04Icon"), + "Schedule a demo", + size="lg", + custom_attrs=get_cal_attrs(), + class_name="w-fit font-semibold mt-4", + ), + class_name="flex flex-col gap-4 items-start justify-center lg:py-20 py-8 lg:pl-20 pl-8 lg:pr-[7.5rem] pr-8 relative overflow-hidden min-h-fit", + ) + + +def final_section() -> rx.Component: + return rx.el.section( + rx.el.div( + text(), + right_content(), + class_name="flex lg:flex-row flex-col w-full rounded-2xl border border-m-slate-4 dark:border-m-slate-12 bg-white-1 dark:bg-m-slate-14 z-5 lg:divide-x divide-slate-3 max-lg:divide-y", + ), + class_name="mx-auto w-full max-w-[71.125rem] relative rounded-4xl border border-slate-4 backdrop-blur-[6px] bg-slate-2/48 p-4 flex z-1 max-lg:mb-6 -mb-px", + ) diff --git a/pcweb/pages/use_cases/finance/views/hero.py b/pcweb/pages/use_cases/finance/views/hero.py new file mode 100644 index 0000000000..c0ef1c5b75 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/hero.py @@ -0,0 +1,90 @@ +import reflex as rx +import reflex_ui as ui +from reflex_ui.blocks.calcom import get_cal_attrs + +from pcweb.components.numbers_pattern import numbers_pattern + + +def left_content() -> rx.Component: + return rx.el.div( + rx.el.h1( + "The Future Of Finance Is", + rx.el.span( + " Python, Data, and AI", + class_name="text-m-violet-11", + ), + class_name="text-slate-12 lg:text-5xl text-3xl font-semibold", + ), + rx.el.h2( + "Give quants, risk teams, and operations the power to build production-grade dashboards and AI tools in pure Python—without waiting on front-end teams.", + class_name="text-m-slate-11 dark:text-slate-9 text-base font-medium", + ), + rx.el.div( + ui.button( + "Talk to a solutions engineer", + size="lg", + class_name="font-semibold", + custom_attrs=get_cal_attrs(), + ), + ui.button( + "Book a financial services demo", + size="lg", + variant="outline", + class_name="font-semibold text-m-slate-11 dark:text-slate-9 border-m-slate-5 dark:border-m-slate-12", + custom_attrs=get_cal_attrs(), + ), + class_name="flex lg:flex-row flex-col items-center max-lg:justify-center gap-4 mt-2", + ), + class_name="flex flex-col gap-6 max-lg:items-center max-lg:justify-center max-lg:text-center", + ) + + +def feature_row(icon: str, title: str) -> rx.Component: + return rx.el.div( + ui.icon( + icon, + class_name="size-5 text-m-violet-11 dark:text-m-violet-10 shrink-0", + stroke_width=1.5, + ), + rx.el.span(title, class_name="font-medium text-slate-12 text-sm"), + class_name="flex flex-row items-start gap-2.5", + ) + + +def right_content() -> rx.Component: + return rx.el.div( + rx.el.span( + "Why Reflex?", + class_name="font-semibold text-slate-12 text-base", + ), + rx.el.div( + feature_row( + "ShieldEnergyIcon", "Build secure internal tools and data apps" + ), + feature_row( + "DashboardSpeed01Icon", "Develop up to 10x faster in pure Python" + ), + feature_row("PythonIcon", "Go in Python from prototype to production"), + feature_row( + "BrowserIcon", + "From risk dashboards and model validation portals to AI-powered RAG chatbots", + ), + class_name="flex flex-col gap-4", + ), + class_name="shadow-large rounded-xl border-m-slate-4 border p-8 bg-white-1 dark:bg-m-slate-14 dark:border-m-slate-12 flex flex-col gap-6 max-w-[24.25rem] w-full shrink-0", + ) + + +def hero() -> rx.Component: + return rx.el.section( + numbers_pattern( + side="right", + class_name="lg:top-[65px] top-[45px] lg:h-[calc(100%-65px)] h-[calc(100%-45px)] max-lg:hidden", + ), + rx.el.div( + left_content(), + right_content(), + class_name="flex lg:flex-row flex-col lg:gap-20 gap-10 max-lg:items-center max-lg:justify-center max-lg:text-center", + ), + class_name="flex flex-col justify-center items-center gap-4 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 pb-[3rem] pt-32 lg:pt-[11.5rem] lg:pb-[7.5rem] relative lg:overflow-hidden overflow-hidden z-[1] lg:px-10", + ) diff --git a/pcweb/pages/use_cases/finance/views/quotes.py b/pcweb/pages/use_cases/finance/views/quotes.py new file mode 100644 index 0000000000..bbe782b212 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/quotes.py @@ -0,0 +1,64 @@ +import reflex as rx + + +def card(h1: str, h2: str, description: str, quote: str, name: str) -> rx.Component: + return rx.el.div( + rx.el.div( + rx.el.div( + rx.el.h1(h1, class_name="text-slate-12 text-2xl font-semibold"), + rx.el.h2( + h2, + class_name="text-m-violet-11 dark:text-m-violet-10 text-2xl font-semibold", + ), + class_name="flex flex-col", + ), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + class_name="flex flex-col gap-6 border-b border-m-slate-4 dark:border-m-slate-12 p-10", + ), + rx.el.div( + rx.el.p(quote, class_name="text-slate-12 text-lg font-semibold"), + rx.el.p( + name, + class_name="text-m-slate-11 dark:text-m-slate-9 text-base font-medium", + ), + class_name="flex flex-col gap-2 p-10", + ), + class_name="flex flex-col border border-m-slate-4 dark:border-m-slate-12 shadow-small rounded-[1.125rem] bg-white-1 dark:bg-m-slate-14", + ) + + +def quotes() -> rx.Component: + return rx.el.section( + card( + "Automate Analytics for Internal AI Tools.", + "Deploy Bank-Grade Internal Dashboards in Days, Not Months", + "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", + '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', + "FirstName LastName, Crédit Agricole CIB", + ), + card( + "Automate Analytics for Internal AI Tools.", + "Deploy Bank-Grade Internal Dashboards in Days, Not Months", + "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", + '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', + "FirstName LastName, Crédit Agricole CIB", + ), + card( + "Automate Analytics for Internal AI Tools.", + "Deploy Bank-Grade Internal Dashboards in Days, Not Months", + "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", + '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', + "FirstName LastName, Crédit Agricole CIB", + ), + card( + "Automate Analytics for Internal AI Tools.", + "Deploy Bank-Grade Internal Dashboards in Days, Not Months", + "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", + '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', + "FirstName LastName, Crédit Agricole CIB", + ), + class_name="grid lg:grid-cols-2 grid-cols-1 gap-4 mx-auto w-full max-w-[84.5rem] relative overflow-hidden", + ) diff --git a/pcweb/pages/use_cases/finance/views/social_proof.py b/pcweb/pages/use_cases/finance/views/social_proof.py new file mode 100644 index 0000000000..e2236bea1b --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/social_proof.py @@ -0,0 +1,40 @@ +import reflex as rx +import reflex_ui as ui + + +def first_card() -> rx.Component: + return rx.el.div( + ui.icon( + "CheckmarkBadge02Icon", + class_name="text-m-slate-11 dark:text-m-slate-9 shrink-0", + ), + rx.el.span( + "Trusted by innovative finance teams", + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium text-nowrap", + ), + class_name="flex flex-row gap-2.5 items-center max-lg:justify-center lg:col-span-2 px-10 h-full max-lg:h-[10.75rem] max-lg:w-full", + ) + + +def social_proof_card(image: str) -> rx.Component: + return rx.el.div( + rx.image( + src=rx.color_mode_cond( + f"/companies/light/{image}.svg", f"/companies/dark/{image}.svg" + ), + loading="lazy", + alt=f"{image} logo", + ), + class_name="flex justify-center items-center lg:size-[10.75rem] max-lg:h-[10.75rem] max-lg:w-full", + ) + + +def social_proof() -> rx.Component: + return rx.el.div( + first_card(), + social_proof_card("man_group"), + social_proof_card("world_bank"), + social_proof_card("credit_agricole"), + social_proof_card("bayesline"), + class_name="grid lg:grid-cols-6 grid-cols-1 justify-center items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 lg:divide-x divide-slate-3 lg:border-t max-lg:divide-y", + ) diff --git a/pcweb/pages/use_cases/finance/views/stats.py b/pcweb/pages/use_cases/finance/views/stats.py new file mode 100644 index 0000000000..0a46a3e622 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/stats.py @@ -0,0 +1,42 @@ +import reflex as rx + + +def stat_card(stat: str, title: str, description: str) -> rx.Component: + return rx.el.div( + rx.el.span( + stat, + class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-3xl", + ), + rx.el.span(title, class_name="font-semibold text-slate-12 text-sm"), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + class_name="flex flex-col items-start p-10 gap-2", + ) + + +def stats() -> rx.Component: + return rx.el.section( + stat_card( + "10x", + "Faster Development", + "Vs. legacy front-end stacks (Crédit Agricole CIB)", + ), + stat_card( + "50+", + "Quant Researchers", + "Building dashboards in Python (Man Group)", + ), + stat_card( + "100+", + "Legal Professionals", + "Using AI tools replacing Tableau (World Bank)", + ), + stat_card( + "4x", + "Faster & 50% Less Code", + "Vs. Dash/React for fintech analytics (Bayesline)", + ), + class_name="grid lg:grid-cols-4 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden border-t lg:divide-x divide-slate-3 max-lg:divide-y", + ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_1.py b/pcweb/pages/use_cases/finance/views/text_section_1.py new file mode 100644 index 0000000000..edd2a28ca8 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/text_section_1.py @@ -0,0 +1,26 @@ +import reflex as rx + +from pcweb.components.numbers_pattern import numbers_pattern + + +def header() -> rx.Component: + return rx.el.div( + rx.el.h2( + "Balance Resilience and Innovation", + class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", + ), + rx.el.p( + "Financial organizations are under pressure from every side: volatile markets, new regulations, GenAI, and rising expectations. Most internal tools haven't kept up.", + class_name="text-m-slate-11 dark:text-slate-9 text-sm font-medium text-center", + ), + class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", + ) + + +def text_section_1() -> rx.Component: + return rx.el.section( + numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), + numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), + header(), + class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20 border-t", + ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_2.py b/pcweb/pages/use_cases/finance/views/text_section_2.py new file mode 100644 index 0000000000..9ebf2788e6 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/text_section_2.py @@ -0,0 +1,26 @@ +import reflex as rx + +from pcweb.components.numbers_pattern import numbers_pattern + + +def header() -> rx.Component: + return rx.el.div( + rx.el.h2( + "Proven at the World's Leading Institutions", + class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", + ), + rx.el.p( + "From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", + class_name="text-m-slate-11 dark:text-slate-9 text-sm font-medium text-center", + ), + class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", + ) + + +def text_section_2() -> rx.Component: + return rx.el.section( + numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), + numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), + header(), + class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_3.py b/pcweb/pages/use_cases/finance/views/text_section_3.py new file mode 100644 index 0000000000..8a75abb131 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/text_section_3.py @@ -0,0 +1,22 @@ +import reflex as rx + +from pcweb.components.numbers_pattern import numbers_pattern + + +def header() -> rx.Component: + return rx.el.div( + rx.el.h2( + "Why Financial Organizations Choose Reflex", + class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", + ), + class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", + ) + + +def text_section_3() -> rx.Component: + return rx.el.section( + numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), + numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), + header(), + class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_4.py b/pcweb/pages/use_cases/finance/views/text_section_4.py new file mode 100644 index 0000000000..db37a25f96 --- /dev/null +++ b/pcweb/pages/use_cases/finance/views/text_section_4.py @@ -0,0 +1,22 @@ +import reflex as rx + +from pcweb.components.numbers_pattern import numbers_pattern + + +def header() -> rx.Component: + return rx.el.div( + rx.el.h2( + "Reflex as a Strategic Platform for Finance Teams", + class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", + ), + class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", + ) + + +def text_section_4() -> rx.Component: + return rx.el.section( + numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), + numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), + header(), + class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + ) diff --git a/pcweb/pages/use_cases/finance_landing.py b/pcweb/pages/use_cases/finance_landing.py deleted file mode 100644 index 31682c72b2..0000000000 --- a/pcweb/pages/use_cases/finance_landing.py +++ /dev/null @@ -1,462 +0,0 @@ -import reflex as rx - -from pcweb.constants import REFLEX_BUILD_URL - - -def hero_section() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - rx.el.div( - class_name="absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]" - ), - rx.el.div( - rx.el.div( - rx.el.div( - rx.el.h1( - rx.el.span( - "The future of", class_name="block text-gray-900" - ), - rx.el.span( - "finance is", class_name="block text-gray-900" - ), - rx.el.span( - "Python, Data, and AI", - class_name="block text-transparent bg-clip-text bg-gradient-to-r from-violet-600 via-purple-600 to-indigo-600", - ), - class_name="text-4xl sm:text-5xl lg:text-6xl font-extrabold tracking-tight leading-[1.1] mb-8", - ), - rx.el.p( - "Give quants, risk teams, and operations the power to build production-grade dashboards and AI tools in pure Python—without waiting on front-end teams.", - class_name="text-xl text-gray-600 font-medium mb-10 leading-relaxed max-w-2xl", - ), - rx.el.div( - rx.el.a( - "Talk to a solutions engineer", - rx.icon( - "messages-square", class_name="h-5 w-5 ml-2" - ), - href="https://cal.com/team/reflex/demo-call-1", - target="_blank", - class_name="flex items-center justify-center w-full sm:w-auto bg-violet-600 hover:bg-violet-700 text-white px-8 py-4 rounded-xl text-base font-semibold transition-all duration-200 shadow-sm hover:shadow-md hover:-translate-y-0.5 cursor-pointer", - ), - rx.el.a( - "Book a financial services demo", - rx.icon("calendar", class_name="h-5 w-5 ml-2"), - href="https://cal.com/team/reflex/reflex-intro", - target="_blank", - class_name="flex items-center justify-center w-full sm:w-auto bg-white text-gray-700 border border-gray-200 hover:border-violet-200 hover:bg-gray-50 px-8 py-4 rounded-xl text-base font-semibold transition-all duration-200 shadow-sm hover:shadow-md hover:-translate-y-0.5 cursor-pointer", - ), - class_name="flex flex-col sm:flex-row items-start gap-4 w-full", - ), - class_name="flex flex-col items-start justify-center lg:pr-12 lg:col-span-3", - ), - rx.el.div( - rx.el.div( - rx.el.div( - rx.icon( - "zap", class_name="h-6 w-6 text-violet-600 mb-2" - ), - rx.el.h3( - "Why Reflex?", - class_name="text-sm font-bold uppercase tracking-wider text-violet-600 mb-3", - ), - class_name="flex flex-col items-start mb-2", - ), - rx.el.p( - "Reflex helps banks, asset managers, fintechs, and hedge funds build secure internal tools and data apps up to 10x faster in pure Python.", - class_name="text-lg text-gray-700 mb-4 leading-relaxed", - ), - rx.el.p( - "Teams ship everything from risk dashboards and model validation portals to AI-powered RAG chatbots, all without leaving Python, from prototype to production.", - class_name="text-lg text-gray-700 leading-relaxed", - ), - class_name="bg-white/60 backdrop-blur-xl border border-gray-100 p-8 rounded-2xl shadow-lg", - ), - class_name="flex items-center justify-center lg:pl-4 mt-16 lg:mt-0 w-full lg:col-span-2", - ), - class_name="grid grid-cols-1 lg:grid-cols-5 gap-12 items-center pt-32 pb-24 px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto relative z-10", - ), - class_name="relative w-full max-w-[1440px] mx-auto", - ), - rx.el.div( - class_name="absolute top-0 right-0 -z-10 w-[800px] h-[800px] bg-radial-gradient from-violet-100/40 to-transparent opacity-60 blur-3xl rounded-bl-full" - ), - rx.el.div( - class_name="absolute top-[200px] left-[-200px] -z-10 w-[600px] h-[600px] bg-radial-gradient from-purple-100/40 to-transparent opacity-50 blur-3xl rounded-tr-full" - ), - ), - class_name="relative w-full overflow-hidden", - ), - class_name="w-full", - ) - - -def logo_item(name: str, icon_name: str) -> rx.Component: - return rx.el.div( - rx.icon(icon_name, class_name="h-6 w-6 mr-2 opacity-50"), - rx.el.span( - name, - class_name="text-lg font-bold tracking-tight text-gray-500 group-hover:text-gray-800 transition-colors", - ), - class_name="flex items-center opacity-60 grayscale hover:grayscale-0 hover:opacity-100 transition-all duration-300 cursor-default group", - ) - - -def logo_row() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.p( - "TRUSTED BY INNOVATIVE FINANCE TEAMS AT", - class_name="text-center text-xs font-bold tracking-[0.2em] text-gray-400 mb-8 uppercase", - ), - rx.el.div( - logo_item("Man Group", "bar-chart-2"), - logo_item("Crédit Agricole CIB", "building-2"), - logo_item("Bayesline", "network"), - logo_item("World Bank", "globe"), - class_name="flex flex-wrap justify-center gap-x-12 gap-y-8 items-center max-w-5xl mx-auto px-6", - ), - class_name="border-y border-gray-100 bg-white/50 py-12 backdrop-blur-sm", - ), - class_name="w-full", - ) - - -def feature_card(icon: str, title: str, description: str) -> rx.Component: - return rx.el.div( - rx.el.div( - rx.icon(icon, class_name="h-7 w-7 text-violet-600"), - class_name="mb-5 inline-flex h-12 w-12 items-center justify-center rounded-xl bg-violet-50/80", - ), - rx.el.h3( - title, class_name="mb-3 text-lg font-bold text-gray-900 tracking-tight" - ), - rx.el.p(description, class_name="text-base leading-relaxed text-gray-600"), - class_name="group relative rounded-2xl border border-gray-200/60 bg-white p-8 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-md hover:border-violet-100", - ) - - -def features_section() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - rx.el.h2( - "Balance resilience and innovation", - class_name="text-3xl font-extrabold text-gray-900 sm:text-4xl mb-4", - ), - rx.el.p( - "Financial organizations are under pressure from every side: volatile markets, new regulations, GenAI, and rising expectations. Most internal tools haven't kept up.", - class_name="mx-auto max-w-2xl text-lg text-gray-600", - ), - class_name="mb-16 text-center max-w-3xl mx-auto", - ), - rx.el.div( - feature_card( - "shield-check", - "Ship AI-powered tools securely", - "Build chat-based assistants and RAG apps in Python, deployed inside your own cloud or on-prem, with full control over where data lives.", - ), - feature_card( - "refresh-cw", - "Modernize legacy internal apps", - "Replace fragile in-house dashboards with maintainable Python apps that plug into your existing data stack.", - ), - feature_card( - "workflow", - "Automate workflows, not just reports", - "Turn manual compliance checks, KYC workflows, and operations processes into interactive apps—tied to your systems, not screenshots.", - ), - feature_card( - "layers", - "Orchestrate end-to-end lifecycles", - "Let researchers, analysts, and quants move from 'run a script in a Jupyter notebook' to 'share a full app' using the same language they already know.", - ), - class_name="grid gap-8 md:grid-cols-2 lg:grid-cols-4", - ), - class_name="mx-auto max-w-7xl px-4 py-20 sm:px-6 lg:px-8", - ), - class_name="bg-white w-full", - ) - - -def case_study_card( - company: str, - title: str, - subheading: str, - body: str, - quote: str, - icon: str, - theme_color: str = "violet", -) -> rx.Component: - color_class = ( - "violet" if theme_color in ["sky", "blue", "indigo", "teal"] else theme_color - ) - return rx.el.div( - rx.el.div( - rx.el.div( - rx.icon(icon, class_name=f"h-8 w-8 text-{color_class}-600 mb-4"), - rx.el.span( - company, - class_name=f"inline-block rounded-full bg-{color_class}-50 px-3 py-1 text-xs font-bold uppercase tracking-wider text-{color_class}-600 mb-5 border border-{color_class}-100", - ), - class_name="flex flex-col items-start", - ), - rx.el.h3( - title, class_name="mb-3 text-2xl font-bold text-gray-900 tracking-tight" - ), - rx.el.p( - subheading, - class_name=f"mb-5 text-sm font-bold text-{color_class}-600 uppercase tracking-wide", - ), - rx.el.p(body, class_name="mb-8 text-gray-600 leading-relaxed"), - rx.el.blockquote( - rx.el.p(f'"{quote}"', class_name="italic text-gray-800 font-medium"), - class_name=f"border-l-2 border-{color_class}-500 bg-gray-50/50 p-5 rounded-r-lg", - ), - class_name="flex-grow", - ), - class_name="flex flex-col h-full rounded-2xl border border-gray-200 bg-white p-8 shadow-sm transition-all duration-300 hover:shadow-lg hover:-translate-y-1 hover:border-violet-100", - ) - - -def case_studies_section() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - rx.el.h2( - "Proven at the world's leading institutions", - class_name="text-3xl font-extrabold text-gray-900 sm:text-4xl mb-4 tracking-tight", - ), - rx.el.p( - "From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", - class_name="mx-auto max-w-2xl text-lg text-gray-600 mb-20", - ), - class_name="text-center max-w-3xl mx-auto", - ), - rx.el.div( - case_study_card( - company="Crédit Agricole CIB", - title="Automate analytics for internal AI tools", - subheading="Deploy bank-grade internal dashboards in days, not months", - body="Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", - quote="It's like comparing a bike to a supercar. (Comparing Dash to Reflex)", - icon="building-2", - ), - case_study_card( - company="Man Group - AHL", - title="Self-service dashboards in pure Python", - subheading="Empower 50+ researchers with a Python-native platform", - body="Man Group's AHL division is rebuilding its internal model validation platform so 50+ PhD-level researchers can create dashboards directly in Python, kept fully offline in air-gapped environments with no SaaS dependencies.", - quote="The ideal state is researchers write high-level Python and get a dashboard — and Reflex gets us very close to that.", - icon="bar-chart-2", - theme_color="indigo", - ), - case_study_card( - company="World Bank", - title="Replace brittle prototypes with production apps", - subheading="Go straight from idea to production", - body="Teams were stuck jumping between Tableau, Streamlit, and custom JS. With Reflex, they're building production-grade data platforms from day one, including an AI-powered legal assistant used by 100+ lawyers.", - quote="You wouldn't want to use Dash or Streamlit to build a real production-grade app... We have them go straight into Reflex.", - icon="globe", - theme_color="blue", - ), - case_study_card( - company="Bayesline", - title="Ship fintech-grade SaaS without a front-end team", - subheading="From YC prototype to fintech SaaS", - body="Bayesline's founders built a full risk analytics platform on Reflex—wrapping AG Grid and handling 100k+ instruments. They achieved ~4x faster development vs React and wrote 50% less code than their previous Dash implementation.", - quote="Using Reflex instead of Plotly Dash was like the difference between organized Legos and a plate of spaghetti.", - icon="network", - theme_color="teal", - ), - class_name="grid gap-8 md:grid-cols-2", - ), - class_name="mx-auto max-w-7xl px-4 py-24 sm:px-6 lg:px-8", - ), - class_name="bg-gray-50/50 w-full border-y border-gray-200/60", - ) - - -def pillar_card(label: str, title: str, body: str, icon: str) -> rx.Component: - return rx.el.div( - rx.el.div( - rx.icon(icon, class_name="h-6 w-6 text-violet-600"), - class_name="mb-6 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-violet-50", - ), - rx.el.div( - rx.el.span( - label, - class_name="mb-2 block text-xs font-bold uppercase tracking-wider text-violet-600", - ), - rx.el.h3( - title, class_name="mb-3 text-lg font-bold text-gray-900 tracking-tight" - ), - rx.el.p(body, class_name="text-base leading-relaxed text-gray-600"), - ), - class_name="flex flex-col rounded-2xl border border-gray-200/60 bg-white p-8 shadow-sm transition-all duration-300 hover:shadow-lg hover:border-violet-100 hover:-translate-y-1", - ) - - -def pillars_section() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - rx.el.h2( - "Why financial organizations choose Reflex", - class_name="text-3xl font-extrabold text-gray-900 sm:text-4xl mb-12 text-center", - ), - class_name="max-w-7xl mx-auto", - ), - rx.el.div( - pillar_card( - label="Speed to production", - title="Ship internal tools 10x faster", - body="Reflex lets Python teams build production-grade apps without leaving their language. Crédit Agricole’s R&D team built a full chatbot analytics dashboard in two days and is rolling it out to 100+ users, without adding a single React engineer.", - icon="zap", - ), - pillar_card( - label="Python-first flexibility", - title="Let experts build, not just consume", - body="At Man Group, 50+ researchers write Python, not JavaScript. Reflex gives them a full-Python framework to create dashboards and model views without touching javascript front-end code, while the platform team wraps their internal design system.", - icon="code-2", - ), - pillar_card( - label="Full control & enterprise deployment", - title="Run in your cloud, offline if needed", - body="Reflex Enterprise runs fully on-prem or in your own cloud. Man Group deploys Reflex apps in air-gapped environments; CACIB and the World Bank run Reflex inside internal AWS and Azure environments with their own SSO, logging, and infra.", - icon="shield-check", - ), - pillar_card( - label="Agility & cost efficiency", - title="Do more with your Python team", - body="Bayesline avoided hiring a front-end engineer and shipped a fintech SaaS app entirely in Python; One engineer can do the work of two by collapsing front- and back-end into a single Reflex codebase.", - icon="trending-up", - ), - class_name="grid gap-8 md:grid-cols-2 lg:grid-cols-4", - ), - class_name="mx-auto max-w-7xl px-4 py-24 sm:px-6 lg:px-8", - ), - class_name="bg-gray-50 w-full border-t border-gray-200", - ) - - -def stat_item(metric: str, description: str, subtext: str) -> rx.Component: - return rx.el.div( - rx.el.div( - metric, - class_name="text-4xl sm:text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-violet-600 to-purple-600 mb-3", - ), - rx.el.div(description, class_name="text-lg font-bold text-gray-900 mb-1"), - rx.el.div(subtext, class_name="text-sm text-gray-500 font-medium"), - class_name="flex flex-col items-center text-center p-8", - ) - - -def stats_section() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - rx.el.h2( - "Reflex as a strategic platform for Finance Teams", - class_name="text-3xl font-extrabold text-gray-900 sm:text-4xl mb-16 text-center", - ), - rx.el.div( - stat_item( - "10x", - "Faster Development", - "vs legacy front-end stacks (Crédit Agricole CIB)", - ), - stat_item( - "50+", - "Quant Researchers", - "building dashboards in Python (Man Group)", - ), - stat_item( - "100+", - "Legal Professionals", - "using AI tools replacing Tableau (World Bank)", - ), - stat_item( - "4x", - "Faster & 50% Less Code", - "vs Dash/React for fintech analytics (Bayesline)", - ), - class_name="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4 divide-y sm:divide-y-0 sm:divide-x divide-gray-100", - ), - class_name="max-w-7xl mx-auto", - ), - class_name="mx-auto max-w-7xl px-4 py-24 sm:px-6 lg:px-8", - ), - class_name="bg-white w-full border-t border-gray-200", - ) - - -def cta_block( - title: str, description: str, button_text: str, href: str, is_primary: bool = True -) -> rx.Component: - return rx.el.div( - rx.el.div( - rx.el.h3( - title, class_name="text-2xl font-bold text-gray-900 mb-4 tracking-tight" - ), - rx.el.p( - description, class_name="text-lg text-gray-600 mb-8 leading-relaxed" - ), - rx.el.a( - button_text, - rx.icon("arrow-right", class_name="ml-2 h-5 w-5"), - href=href, - target="_blank", - class_name=rx.cond( - is_primary, - "inline-flex items-center justify-center rounded-xl bg-violet-600 px-6 py-3 text-base font-semibold text-white shadow-sm hover:bg-violet-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-violet-600 transition-all duration-200 hover:-translate-y-0.5 cursor-pointer", - "inline-flex items-center justify-center rounded-xl bg-white px-6 py-3 text-base font-semibold text-gray-900 ring-1 ring-inset ring-gray-200 hover:bg-gray-50 transition-all duration-200 hover:-translate-y-0.5 cursor-pointer", - ), - ), - class_name="max-w-xl", - ), - class_name=f"relative isolate overflow-hidden rounded-3xl px-6 py-12 shadow-lg sm:px-12 md:pt-12 lg:flex lg:gap-x-20 lg:px-16 items-center {('bg-violet-50/30 border border-violet-100' if is_primary else 'bg-white border border-gray-200')}", - ) - - -def cta_section() -> rx.Component: - return rx.el.section( - rx.el.div( - rx.el.div( - cta_block( - "Give us your toughest internal tool", - "Have a spreadsheet-driven workflow, a fragile Streamlit app, or a dashboard that never quite got to production? We’ll show you what it looks like as a Reflex app in pure Python.", - "Schedule demo", - href="https://cal.com/team/reflex/reflex-intro", - is_primary=True, - ), - cta_block( - "Spin up your first finance app", - "Connect your data source, and ship a working internal tool in an afternoon—no JavaScript required.", - "Go to the Builder", - href=REFLEX_BUILD_URL, - is_primary=False, - ), - class_name="grid gap-8 lg:grid-cols-2 max-w-7xl mx-auto", - ), - class_name="mx-auto max-w-7xl px-4 py-24 sm:px-6 lg:px-8", - ), - class_name="bg-white w-full", - ) - - -def finance_landing_page() -> rx.Component: - return rx.el.div( - rx.el.main( - hero_section(), - logo_row(), - features_section(), - case_studies_section(), - pillars_section(), - stats_section(), - cta_section(), - class_name="w-full", - ), - class_name="font-['Instrument_Sans'] antialiased text-gray-900 bg-white selection:bg-violet-100 selection:text-violet-900 min-h-screen", - ) diff --git a/pcweb/pages/use_cases/finance_use_case.py b/pcweb/pages/use_cases/finance_use_case.py deleted file mode 100644 index 683b7cd085..0000000000 --- a/pcweb/pages/use_cases/finance_use_case.py +++ /dev/null @@ -1,7 +0,0 @@ -from pcweb.pages.use_cases.finance_landing import finance_landing_page -from pcweb.templates.webpage import webpage - - -@webpage(path="/use-cases/finance", title="Finance Use Case - Reflex") -def finance_use_case_page(): - return finance_landing_page() diff --git a/pcweb/pages/use_cases/use_cases.md b/pcweb/pages/use_cases/use_cases.md index 40d7bc0a6e..45f9d72963 100644 --- a/pcweb/pages/use_cases/use_cases.md +++ b/pcweb/pages/use_cases/use_cases.md @@ -7,7 +7,7 @@ Organizations across industries use **Reflex** to build internal tools, dashboar ```python exec import reflex as rx from reflex_image_zoom import image_zoom -from pcweb.pages.use_cases.finance_use_case import finance_use_case_page +from pcweb.pages.use_cases.finance import finance_use_case_page ``` ```python eval From c36d8c9b8b27c94a7a98fc3b24519c5f70ca2f41 Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 15 Dec 2025 17:15:19 +0100 Subject: [PATCH 02/10] common views --- pcweb/pages/use_cases/common/features_1.py | 15 +++ pcweb/pages/use_cases/common/features_2.py | 19 ++++ pcweb/pages/use_cases/common/final_section.py | 52 +++++++++++ pcweb/pages/use_cases/common/hero.py | 82 ++++++++++++++++ pcweb/pages/use_cases/common/quote.py | 32 +++++++ pcweb/pages/use_cases/common/social_proof.py | 37 ++++++++ pcweb/pages/use_cases/common/stats.py | 16 ++++ pcweb/pages/use_cases/common/text_section.py | 28 ++++++ .../use_cases/finance/views/features_1.py | 14 +-- .../use_cases/finance/views/features_2.py | 18 +--- .../use_cases/finance/views/final_section.py | 61 ++---------- pcweb/pages/use_cases/finance/views/hero.py | 93 ++++--------------- pcweb/pages/use_cases/finance/views/quotes.py | 37 +------- .../use_cases/finance/views/social_proof.py | 30 +----- pcweb/pages/use_cases/finance/views/stats.py | 15 +-- .../use_cases/finance/views/text_section_1.py | 24 +---- .../use_cases/finance/views/text_section_2.py | 24 +---- .../use_cases/finance/views/text_section_3.py | 20 +--- .../use_cases/finance/views/text_section_4.py | 20 +--- 19 files changed, 335 insertions(+), 302 deletions(-) create mode 100644 pcweb/pages/use_cases/common/features_1.py create mode 100644 pcweb/pages/use_cases/common/features_2.py create mode 100644 pcweb/pages/use_cases/common/final_section.py create mode 100644 pcweb/pages/use_cases/common/hero.py create mode 100644 pcweb/pages/use_cases/common/quote.py create mode 100644 pcweb/pages/use_cases/common/social_proof.py create mode 100644 pcweb/pages/use_cases/common/stats.py create mode 100644 pcweb/pages/use_cases/common/text_section.py diff --git a/pcweb/pages/use_cases/common/features_1.py b/pcweb/pages/use_cases/common/features_1.py new file mode 100644 index 0000000000..6a3e4fd9b9 --- /dev/null +++ b/pcweb/pages/use_cases/common/features_1.py @@ -0,0 +1,15 @@ +import reflex as rx + +from pcweb.components.icons import get_icon + + +def feature_card(icon: str, title: str, description: str) -> rx.Component: + return rx.el.div( + get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), + rx.el.span(title, class_name="font-semibold text-slate-12 text-lg mt-2"), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + class_name="flex flex-col items-start gap-2 p-10 lg:border-r border-b border-slate-3", + ) diff --git a/pcweb/pages/use_cases/common/features_2.py b/pcweb/pages/use_cases/common/features_2.py new file mode 100644 index 0000000000..6f2b411528 --- /dev/null +++ b/pcweb/pages/use_cases/common/features_2.py @@ -0,0 +1,19 @@ +import reflex as rx + +from pcweb.components.icons import get_icon + + +def feature_card(icon: str, stat: str, title: str, description: str) -> rx.Component: + return rx.el.div( + get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), + rx.el.span( + stat, + class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-sm mt-4", + ), + rx.el.span(title, class_name="font-semibold text-slate-12 text-lg mt-4"), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium mt-2", + ), + class_name="flex flex-col items-start p-10", + ) diff --git a/pcweb/pages/use_cases/common/final_section.py b/pcweb/pages/use_cases/common/final_section.py new file mode 100644 index 0000000000..47cc83f2f7 --- /dev/null +++ b/pcweb/pages/use_cases/common/final_section.py @@ -0,0 +1,52 @@ +import reflex as rx +import reflex_ui as ui +from reflex_ui.blocks.calcom import get_cal_attrs + +from pcweb.constants import REFLEX_BUILD_URL +from pcweb.pages.pricing.plan_cards import radial_circle + + +def right_content(h1: str, description: str) -> rx.Component: + return rx.el.div( + rx.el.h2( + h1, + class_name="text-slate-12 text-2xl font-semibold", + ), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium mt-2", + ), + ui.link( + render_=ui.button( + "Go to the builder", + size="lg", + variant="outline", + class_name="w-fit font-semibold lg:mt-auto mt-8 text-m-slate-11 dark:text-m-slate-9 border-m-slate-5 dark:border-m-slate-12", + ), + to=REFLEX_BUILD_URL, + target="_blank", + ), + class_name="flex flex-col lg:p-20 p-8 h-full", + ) + + +def left_content(h1: str, description: str) -> rx.Component: + return rx.el.div( + radial_circle(class_name="dark:opacity-50"), + rx.el.h2( + h1, + class_name="text-slate-12 lg:text-3xl text-2xl font-semibold", + ), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + ui.button( + ui.icon("Calendar04Icon"), + "Schedule a demo", + size="lg", + custom_attrs=get_cal_attrs(), + class_name="w-fit font-semibold mt-4", + ), + class_name="flex flex-col gap-4 items-start justify-center lg:py-20 py-8 lg:pl-20 pl-8 lg:pr-[7.5rem] pr-8 relative overflow-hidden min-h-fit", + ) diff --git a/pcweb/pages/use_cases/common/hero.py b/pcweb/pages/use_cases/common/hero.py new file mode 100644 index 0000000000..1eae0cca36 --- /dev/null +++ b/pcweb/pages/use_cases/common/hero.py @@ -0,0 +1,82 @@ +import reflex as rx +import reflex_ui as ui +from reflex_ui.blocks.calcom import get_cal_attrs + +from pcweb.components.numbers_pattern import numbers_pattern + + +def left_content( + h1: str, h1_accent: str, h2: str, button_1: str, button_2: str +) -> rx.Component: + return rx.el.div( + rx.el.h1( + h1, + rx.el.span( + h1_accent, + class_name="text-m-violet-11", + ), + class_name="text-slate-12 lg:text-5xl text-3xl font-semibold", + ), + rx.el.h2( + h2, + class_name="text-m-slate-11 dark:text-slate-9 text-base font-medium", + ), + rx.el.div( + ui.button( + button_1, + size="lg", + class_name="font-semibold", + custom_attrs=get_cal_attrs(), + ), + ui.button( + button_2, + size="lg", + variant="outline", + class_name="font-semibold text-m-slate-11 dark:text-slate-9 border-m-slate-5 dark:border-m-slate-12", + custom_attrs=get_cal_attrs(), + ), + class_name="flex lg:flex-row flex-col items-center max-lg:justify-center gap-4 mt-2", + ), + class_name="flex flex-col gap-6 max-lg:items-center max-lg:justify-center max-lg:text-center", + ) + + +def feature_row(icon: str, title: str) -> rx.Component: + return rx.el.div( + ui.icon( + icon, + class_name="size-5 text-m-violet-11 dark:text-m-violet-10 shrink-0", + stroke_width=1.5, + ), + rx.el.span(title, class_name="font-medium text-slate-12 text-sm"), + class_name="flex flex-row items-start gap-2.5", + ) + + +def right_content(features: list[tuple[str, str]]) -> rx.Component: + return rx.el.div( + rx.el.span( + "Why Reflex?", + class_name="font-semibold text-slate-12 text-base", + ), + rx.el.div( + *[feature_row(icon, title) for icon, title in features], + class_name="flex flex-col gap-4", + ), + class_name="shadow-large rounded-xl border-m-slate-4 border p-8 bg-white-1 dark:bg-m-slate-14 dark:border-m-slate-12 flex flex-col gap-6 max-w-[24.25rem] w-full shrink-0", + ) + + +def hero() -> rx.Component: + return rx.el.section( + numbers_pattern( + side="right", + class_name="lg:top-[65px] top-[45px] lg:h-[calc(100%-65px)] h-[calc(100%-45px)] max-lg:hidden", + ), + rx.el.div( + left_content(), + right_content(), + class_name="flex lg:flex-row flex-col lg:gap-20 gap-10 max-lg:items-center max-lg:justify-center max-lg:text-center", + ), + class_name="flex flex-col justify-center items-center gap-4 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 pb-[3rem] pt-32 lg:pt-[11.5rem] lg:pb-[7.5rem] relative lg:overflow-hidden overflow-hidden z-[1] lg:px-10", + ) diff --git a/pcweb/pages/use_cases/common/quote.py b/pcweb/pages/use_cases/common/quote.py new file mode 100644 index 0000000000..a8209d3448 --- /dev/null +++ b/pcweb/pages/use_cases/common/quote.py @@ -0,0 +1,32 @@ +import reflex as rx + + +def quote_card( + h1: str, h2: str, description: str, quote: str, name: str +) -> rx.Component: + return rx.el.div( + rx.el.div( + rx.el.div( + rx.el.h1(h1, class_name="text-slate-12 text-2xl font-semibold"), + rx.el.h2( + h2, + class_name="text-m-violet-11 dark:text-m-violet-10 text-2xl font-semibold", + ), + class_name="flex flex-col", + ), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + class_name="flex flex-col gap-6 border-b border-m-slate-4 dark:border-m-slate-12 p-10", + ), + rx.el.div( + rx.el.p(quote, class_name="text-slate-12 text-lg font-semibold"), + rx.el.p( + name, + class_name="text-m-slate-11 dark:text-m-slate-9 text-base font-medium", + ), + class_name="flex flex-col gap-2 p-10", + ), + class_name="flex flex-col border border-m-slate-4 dark:border-m-slate-12 shadow-small rounded-[1.125rem] bg-white-1 dark:bg-m-slate-14", + ) diff --git a/pcweb/pages/use_cases/common/social_proof.py b/pcweb/pages/use_cases/common/social_proof.py new file mode 100644 index 0000000000..c84758b45b --- /dev/null +++ b/pcweb/pages/use_cases/common/social_proof.py @@ -0,0 +1,37 @@ +import reflex as rx +import reflex_ui as ui + + +def first_card(title: str) -> rx.Component: + return rx.el.div( + ui.icon( + "CheckmarkBadge02Icon", + class_name="text-m-slate-11 dark:text-m-slate-9 shrink-0", + ), + rx.el.span( + title, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium text-nowrap", + ), + class_name="flex flex-row gap-2.5 items-center max-lg:justify-center lg:col-span-2 px-10 h-full max-lg:h-[10.75rem] max-lg:w-full", + ) + + +def social_proof_card(image: str) -> rx.Component: + return rx.el.div( + rx.image( + src=rx.color_mode_cond( + f"/companies/light/{image}.svg", f"/companies/dark/{image}.svg" + ), + loading="lazy", + alt=f"{image} logo", + ), + class_name="flex justify-center items-center lg:size-[10.75rem] max-lg:h-[10.75rem] max-lg:w-full", + ) + + +def social_proof(title: str, images: list[str]) -> rx.Component: + return rx.el.div( + first_card(title), + *[social_proof_card(image) for image in images], + class_name="grid lg:grid-cols-6 grid-cols-1 justify-center items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 lg:divide-x divide-slate-3 lg:border-t max-lg:divide-y", + ) diff --git a/pcweb/pages/use_cases/common/stats.py b/pcweb/pages/use_cases/common/stats.py new file mode 100644 index 0000000000..ed3d8ab3a4 --- /dev/null +++ b/pcweb/pages/use_cases/common/stats.py @@ -0,0 +1,16 @@ +import reflex as rx + + +def stat_card(stat: str, title: str, description: str) -> rx.Component: + return rx.el.div( + rx.el.span( + stat, + class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-3xl", + ), + rx.el.span(title, class_name="font-semibold text-slate-12 text-sm"), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", + ), + class_name="flex flex-col items-start p-10 gap-2", + ) diff --git a/pcweb/pages/use_cases/common/text_section.py b/pcweb/pages/use_cases/common/text_section.py new file mode 100644 index 0000000000..4e81221d90 --- /dev/null +++ b/pcweb/pages/use_cases/common/text_section.py @@ -0,0 +1,28 @@ +import reflex as rx + +from pcweb.components.numbers_pattern import numbers_pattern + + +def content(header: str, description: str | None = None) -> rx.Component: + return rx.el.div( + rx.el.h2( + header, + class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", + ), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-slate-9 text-sm font-medium text-center", + ) + if description + else None, + class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", + ) + + +def text_section(header: str, description: str) -> rx.Component: + return rx.el.section( + numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), + numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), + content(header, description), + class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20 border-t", + ) diff --git a/pcweb/pages/use_cases/finance/views/features_1.py b/pcweb/pages/use_cases/finance/views/features_1.py index d6b354299c..0ce07962e7 100644 --- a/pcweb/pages/use_cases/finance/views/features_1.py +++ b/pcweb/pages/use_cases/finance/views/features_1.py @@ -1,18 +1,6 @@ import reflex as rx -from pcweb.components.icons import get_icon - - -def feature_card(icon: str, title: str, description: str) -> rx.Component: - return rx.el.div( - get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), - rx.el.span(title, class_name="font-semibold text-slate-12 text-lg mt-2"), - rx.el.p( - description, - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", - ), - class_name="flex flex-col items-start gap-2 p-10 lg:border-r border-b border-slate-3", - ) +from pcweb.pages.use_cases.common.features_1 import feature_card def features_1() -> rx.Component: diff --git a/pcweb/pages/use_cases/finance/views/features_2.py b/pcweb/pages/use_cases/finance/views/features_2.py index 4020348ae2..5cb6a09533 100644 --- a/pcweb/pages/use_cases/finance/views/features_2.py +++ b/pcweb/pages/use_cases/finance/views/features_2.py @@ -1,22 +1,6 @@ import reflex as rx -from pcweb.components.icons import get_icon - - -def feature_card(icon: str, stat: str, title: str, description: str) -> rx.Component: - return rx.el.div( - get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), - rx.el.span( - stat, - class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-sm mt-4", - ), - rx.el.span(title, class_name="font-semibold text-slate-12 text-lg mt-4"), - rx.el.p( - description, - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium mt-2", - ), - class_name="flex flex-col items-start p-10", - ) +from pcweb.pages.use_cases.common.features_2 import feature_card def features_2() -> rx.Component: diff --git a/pcweb/pages/use_cases/finance/views/final_section.py b/pcweb/pages/use_cases/finance/views/final_section.py index b50eb6bed1..4703586da8 100644 --- a/pcweb/pages/use_cases/finance/views/final_section.py +++ b/pcweb/pages/use_cases/finance/views/final_section.py @@ -1,62 +1,19 @@ import reflex as rx -import reflex_ui as ui -from reflex_ui.blocks.calcom import get_cal_attrs -from pcweb.constants import REFLEX_BUILD_URL -from pcweb.pages.pricing.plan_cards import radial_circle - - -def right_content() -> rx.Component: - return rx.el.div( - rx.el.h2( - "Spin Up Your First Finance App", - class_name="text-slate-12 text-2xl font-semibold", - ), - rx.el.p( - "Connect your data source, and ship a working internal tool in an afternoon—no JavaScript required.", - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium mt-2", - ), - ui.link( - render_=ui.button( - "Go to the builder", - size="lg", - variant="outline", - class_name="w-fit font-semibold lg:mt-auto mt-8 text-m-slate-11 dark:text-m-slate-9 border-m-slate-5 dark:border-m-slate-12", - ), - to=REFLEX_BUILD_URL, - target="_blank", - ), - class_name="flex flex-col lg:p-20 p-8 h-full", - ) - - -def text() -> rx.Component: - return rx.el.div( - radial_circle(class_name="dark:opacity-50"), - rx.el.h2( - "Make Your Toughest Internal Tool Real With Reflex", - class_name="text-slate-12 lg:text-3xl text-2xl font-semibold", - ), - rx.el.p( - "Have a spreadsheet-driven workflow, a fragile Streamlit app, or a dashboard that never quite got to production? We’ll show you what it looks like as a Reflex app in pure Python.", - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", - ), - ui.button( - ui.icon("Calendar04Icon"), - "Schedule a demo", - size="lg", - custom_attrs=get_cal_attrs(), - class_name="w-fit font-semibold mt-4", - ), - class_name="flex flex-col gap-4 items-start justify-center lg:py-20 py-8 lg:pl-20 pl-8 lg:pr-[7.5rem] pr-8 relative overflow-hidden min-h-fit", - ) +from pcweb.pages.use_cases.common.final_section import left_content, right_content def final_section() -> rx.Component: return rx.el.section( rx.el.div( - text(), - right_content(), + left_content( + "Make Your Toughest Internal Tool Real With Reflex", + "Have a spreadsheet-driven workflow, a fragile Streamlit app, or a dashboard that never quite got to production? We’ll show you what it looks like as a Reflex app in pure Python.", + ), + right_content( + "Spin Up Your First Finance App", + "Connect your data source, and ship a working internal tool in an afternoon—no JavaScript required.", + ), class_name="flex lg:flex-row flex-col w-full rounded-2xl border border-m-slate-4 dark:border-m-slate-12 bg-white-1 dark:bg-m-slate-14 z-5 lg:divide-x divide-slate-3 max-lg:divide-y", ), class_name="mx-auto w-full max-w-[71.125rem] relative rounded-4xl border border-slate-4 backdrop-blur-[6px] bg-slate-2/48 p-4 flex z-1 max-lg:mb-6 -mb-px", diff --git a/pcweb/pages/use_cases/finance/views/hero.py b/pcweb/pages/use_cases/finance/views/hero.py index c0ef1c5b75..68f9be9ee8 100644 --- a/pcweb/pages/use_cases/finance/views/hero.py +++ b/pcweb/pages/use_cases/finance/views/hero.py @@ -1,78 +1,7 @@ import reflex as rx -import reflex_ui as ui -from reflex_ui.blocks.calcom import get_cal_attrs from pcweb.components.numbers_pattern import numbers_pattern - - -def left_content() -> rx.Component: - return rx.el.div( - rx.el.h1( - "The Future Of Finance Is", - rx.el.span( - " Python, Data, and AI", - class_name="text-m-violet-11", - ), - class_name="text-slate-12 lg:text-5xl text-3xl font-semibold", - ), - rx.el.h2( - "Give quants, risk teams, and operations the power to build production-grade dashboards and AI tools in pure Python—without waiting on front-end teams.", - class_name="text-m-slate-11 dark:text-slate-9 text-base font-medium", - ), - rx.el.div( - ui.button( - "Talk to a solutions engineer", - size="lg", - class_name="font-semibold", - custom_attrs=get_cal_attrs(), - ), - ui.button( - "Book a financial services demo", - size="lg", - variant="outline", - class_name="font-semibold text-m-slate-11 dark:text-slate-9 border-m-slate-5 dark:border-m-slate-12", - custom_attrs=get_cal_attrs(), - ), - class_name="flex lg:flex-row flex-col items-center max-lg:justify-center gap-4 mt-2", - ), - class_name="flex flex-col gap-6 max-lg:items-center max-lg:justify-center max-lg:text-center", - ) - - -def feature_row(icon: str, title: str) -> rx.Component: - return rx.el.div( - ui.icon( - icon, - class_name="size-5 text-m-violet-11 dark:text-m-violet-10 shrink-0", - stroke_width=1.5, - ), - rx.el.span(title, class_name="font-medium text-slate-12 text-sm"), - class_name="flex flex-row items-start gap-2.5", - ) - - -def right_content() -> rx.Component: - return rx.el.div( - rx.el.span( - "Why Reflex?", - class_name="font-semibold text-slate-12 text-base", - ), - rx.el.div( - feature_row( - "ShieldEnergyIcon", "Build secure internal tools and data apps" - ), - feature_row( - "DashboardSpeed01Icon", "Develop up to 10x faster in pure Python" - ), - feature_row("PythonIcon", "Go in Python from prototype to production"), - feature_row( - "BrowserIcon", - "From risk dashboards and model validation portals to AI-powered RAG chatbots", - ), - class_name="flex flex-col gap-4", - ), - class_name="shadow-large rounded-xl border-m-slate-4 border p-8 bg-white-1 dark:bg-m-slate-14 dark:border-m-slate-12 flex flex-col gap-6 max-w-[24.25rem] w-full shrink-0", - ) +from pcweb.pages.use_cases.common.hero import left_content, right_content def hero() -> rx.Component: @@ -82,8 +11,24 @@ def hero() -> rx.Component: class_name="lg:top-[65px] top-[45px] lg:h-[calc(100%-65px)] h-[calc(100%-45px)] max-lg:hidden", ), rx.el.div( - left_content(), - right_content(), + left_content( + "The Future Of Finance Is", + " Python, Data, and AI", + "Give quants, risk teams, and operations the power to build production-grade dashboards and AI tools in pure Python—without waiting on front-end teams.", + "Talk to a solutions engineer", + "Book a financial services demo", + ), + right_content( + [ + ("ShieldEnergyIcon", "Build secure internal tools and data apps"), + ("DashboardSpeed01Icon", "Develop up to 10x faster in pure Python"), + ("PythonIcon", "Go in Python from prototype to production"), + ( + "BrowserIcon", + "From risk dashboards and model validation portals to AI-powered RAG chatbots", + ), + ], + ), class_name="flex lg:flex-row flex-col lg:gap-20 gap-10 max-lg:items-center max-lg:justify-center max-lg:text-center", ), class_name="flex flex-col justify-center items-center gap-4 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 pb-[3rem] pt-32 lg:pt-[11.5rem] lg:pb-[7.5rem] relative lg:overflow-hidden overflow-hidden z-[1] lg:px-10", diff --git a/pcweb/pages/use_cases/finance/views/quotes.py b/pcweb/pages/use_cases/finance/views/quotes.py index bbe782b212..0f0a2f31b5 100644 --- a/pcweb/pages/use_cases/finance/views/quotes.py +++ b/pcweb/pages/use_cases/finance/views/quotes.py @@ -1,59 +1,32 @@ import reflex as rx - -def card(h1: str, h2: str, description: str, quote: str, name: str) -> rx.Component: - return rx.el.div( - rx.el.div( - rx.el.div( - rx.el.h1(h1, class_name="text-slate-12 text-2xl font-semibold"), - rx.el.h2( - h2, - class_name="text-m-violet-11 dark:text-m-violet-10 text-2xl font-semibold", - ), - class_name="flex flex-col", - ), - rx.el.p( - description, - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", - ), - class_name="flex flex-col gap-6 border-b border-m-slate-4 dark:border-m-slate-12 p-10", - ), - rx.el.div( - rx.el.p(quote, class_name="text-slate-12 text-lg font-semibold"), - rx.el.p( - name, - class_name="text-m-slate-11 dark:text-m-slate-9 text-base font-medium", - ), - class_name="flex flex-col gap-2 p-10", - ), - class_name="flex flex-col border border-m-slate-4 dark:border-m-slate-12 shadow-small rounded-[1.125rem] bg-white-1 dark:bg-m-slate-14", - ) +from pcweb.pages.use_cases.common.quote import quote_card def quotes() -> rx.Component: return rx.el.section( - card( + quote_card( "Automate Analytics for Internal AI Tools.", "Deploy Bank-Grade Internal Dashboards in Days, Not Months", "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', "FirstName LastName, Crédit Agricole CIB", ), - card( + quote_card( "Automate Analytics for Internal AI Tools.", "Deploy Bank-Grade Internal Dashboards in Days, Not Months", "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', "FirstName LastName, Crédit Agricole CIB", ), - card( + quote_card( "Automate Analytics for Internal AI Tools.", "Deploy Bank-Grade Internal Dashboards in Days, Not Months", "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', "FirstName LastName, Crédit Agricole CIB", ), - card( + quote_card( "Automate Analytics for Internal AI Tools.", "Deploy Bank-Grade Internal Dashboards in Days, Not Months", "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", diff --git a/pcweb/pages/use_cases/finance/views/social_proof.py b/pcweb/pages/use_cases/finance/views/social_proof.py index e2236bea1b..f839e20722 100644 --- a/pcweb/pages/use_cases/finance/views/social_proof.py +++ b/pcweb/pages/use_cases/finance/views/social_proof.py @@ -1,37 +1,11 @@ import reflex as rx -import reflex_ui as ui - -def first_card() -> rx.Component: - return rx.el.div( - ui.icon( - "CheckmarkBadge02Icon", - class_name="text-m-slate-11 dark:text-m-slate-9 shrink-0", - ), - rx.el.span( - "Trusted by innovative finance teams", - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium text-nowrap", - ), - class_name="flex flex-row gap-2.5 items-center max-lg:justify-center lg:col-span-2 px-10 h-full max-lg:h-[10.75rem] max-lg:w-full", - ) - - -def social_proof_card(image: str) -> rx.Component: - return rx.el.div( - rx.image( - src=rx.color_mode_cond( - f"/companies/light/{image}.svg", f"/companies/dark/{image}.svg" - ), - loading="lazy", - alt=f"{image} logo", - ), - class_name="flex justify-center items-center lg:size-[10.75rem] max-lg:h-[10.75rem] max-lg:w-full", - ) +from pcweb.pages.use_cases.common.social_proof import first_card, social_proof_card def social_proof() -> rx.Component: return rx.el.div( - first_card(), + first_card("Trusted by innovative finance teams"), social_proof_card("man_group"), social_proof_card("world_bank"), social_proof_card("credit_agricole"), diff --git a/pcweb/pages/use_cases/finance/views/stats.py b/pcweb/pages/use_cases/finance/views/stats.py index 0a46a3e622..0b206743af 100644 --- a/pcweb/pages/use_cases/finance/views/stats.py +++ b/pcweb/pages/use_cases/finance/views/stats.py @@ -1,19 +1,6 @@ import reflex as rx - -def stat_card(stat: str, title: str, description: str) -> rx.Component: - return rx.el.div( - rx.el.span( - stat, - class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-3xl", - ), - rx.el.span(title, class_name="font-semibold text-slate-12 text-sm"), - rx.el.p( - description, - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", - ), - class_name="flex flex-col items-start p-10 gap-2", - ) +from pcweb.pages.use_cases.common.stats import stat_card def stats() -> rx.Component: diff --git a/pcweb/pages/use_cases/finance/views/text_section_1.py b/pcweb/pages/use_cases/finance/views/text_section_1.py index edd2a28ca8..6786ac9d1d 100644 --- a/pcweb/pages/use_cases/finance/views/text_section_1.py +++ b/pcweb/pages/use_cases/finance/views/text_section_1.py @@ -1,26 +1,10 @@ import reflex as rx -from pcweb.components.numbers_pattern import numbers_pattern - - -def header() -> rx.Component: - return rx.el.div( - rx.el.h2( - "Balance Resilience and Innovation", - class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", - ), - rx.el.p( - "Financial organizations are under pressure from every side: volatile markets, new regulations, GenAI, and rising expectations. Most internal tools haven't kept up.", - class_name="text-m-slate-11 dark:text-slate-9 text-sm font-medium text-center", - ), - class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", - ) +from pcweb.pages.use_cases.common.text_section import text_section def text_section_1() -> rx.Component: - return rx.el.section( - numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), - numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), - header(), - class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20 border-t", + return text_section( + header="Balance Resilience and Innovation", + description="Financial organizations are under pressure from every side: volatile markets, new regulations, GenAI, and rising expectations. Most internal tools haven't kept up.", ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_2.py b/pcweb/pages/use_cases/finance/views/text_section_2.py index 9ebf2788e6..bbc3975b1c 100644 --- a/pcweb/pages/use_cases/finance/views/text_section_2.py +++ b/pcweb/pages/use_cases/finance/views/text_section_2.py @@ -1,26 +1,10 @@ import reflex as rx -from pcweb.components.numbers_pattern import numbers_pattern - - -def header() -> rx.Component: - return rx.el.div( - rx.el.h2( - "Proven at the World's Leading Institutions", - class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", - ), - rx.el.p( - "From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", - class_name="text-m-slate-11 dark:text-slate-9 text-sm font-medium text-center", - ), - class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", - ) +from pcweb.pages.use_cases.common.text_section import text_section def text_section_2() -> rx.Component: - return rx.el.section( - numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), - numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), - header(), - class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + return text_section( + header="Proven at the World's Leading Institutions", + description="From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_3.py b/pcweb/pages/use_cases/finance/views/text_section_3.py index 8a75abb131..0fe3392aa8 100644 --- a/pcweb/pages/use_cases/finance/views/text_section_3.py +++ b/pcweb/pages/use_cases/finance/views/text_section_3.py @@ -1,22 +1,10 @@ import reflex as rx -from pcweb.components.numbers_pattern import numbers_pattern - - -def header() -> rx.Component: - return rx.el.div( - rx.el.h2( - "Why Financial Organizations Choose Reflex", - class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", - ), - class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", - ) +from pcweb.pages.use_cases.common.text_section import text_section def text_section_3() -> rx.Component: - return rx.el.section( - numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), - numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), - header(), - class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + return text_section( + header="Why Financial Organizations Choose Reflex", + description="From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_4.py b/pcweb/pages/use_cases/finance/views/text_section_4.py index db37a25f96..3658522ca3 100644 --- a/pcweb/pages/use_cases/finance/views/text_section_4.py +++ b/pcweb/pages/use_cases/finance/views/text_section_4.py @@ -1,22 +1,10 @@ import reflex as rx -from pcweb.components.numbers_pattern import numbers_pattern - - -def header() -> rx.Component: - return rx.el.div( - rx.el.h2( - "Reflex as a Strategic Platform for Finance Teams", - class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", - ), - class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", - ) +from pcweb.pages.use_cases.common.text_section import text_section def text_section_4() -> rx.Component: - return rx.el.section( - numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), - numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), - header(), - class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + return text_section( + header="Reflex as a Strategic Platform for Finance Teams", + description="From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", ) From cefe38e008d43694b572e2cc1621e5c894e67c8b Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 15 Dec 2025 17:35:11 +0100 Subject: [PATCH 03/10] tests --- tests/test_background_events.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_background_events.py b/tests/test_background_events.py index 20fe021adb..e5bc09c9eb 100644 --- a/tests/test_background_events.py +++ b/tests/test_background_events.py @@ -37,5 +37,4 @@ def test_background_events( expect(heading).to_have_text(re.compile(r"[4-7] /")) reset_button.click() - expect(heading).to_have_text("0 /") expect(heading).to_have_text("10 /", timeout=12000) From b790f774f59393d3cd681daa12469192de9407a2 Mon Sep 17 00:00:00 2001 From: carlosabadia Date: Mon, 15 Dec 2025 18:58:22 +0100 Subject: [PATCH 04/10] fix safari thing --- pcweb/pages/use_cases/common/final_section.py | 4 ++-- pcweb/pages/use_cases/finance/views/final_section.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pcweb/pages/use_cases/common/final_section.py b/pcweb/pages/use_cases/common/final_section.py index 47cc83f2f7..4732a7d795 100644 --- a/pcweb/pages/use_cases/common/final_section.py +++ b/pcweb/pages/use_cases/common/final_section.py @@ -26,7 +26,7 @@ def right_content(h1: str, description: str) -> rx.Component: to=REFLEX_BUILD_URL, target="_blank", ), - class_name="flex flex-col lg:p-20 p-8 h-full", + class_name="flex flex-col lg:p-20 p-8 h-full shrink-0", ) @@ -48,5 +48,5 @@ def left_content(h1: str, description: str) -> rx.Component: custom_attrs=get_cal_attrs(), class_name="w-fit font-semibold mt-4", ), - class_name="flex flex-col gap-4 items-start justify-center lg:py-20 py-8 lg:pl-20 pl-8 lg:pr-[7.5rem] pr-8 relative overflow-hidden min-h-fit", + class_name="flex flex-col gap-4 items-start justify-center lg:py-20 py-8 lg:pl-20 pl-8 lg:pr-[7.5rem] pr-8 relative overflow-hidden min-h-fit shrink-0", ) diff --git a/pcweb/pages/use_cases/finance/views/final_section.py b/pcweb/pages/use_cases/finance/views/final_section.py index 4703586da8..0fc5cb6391 100644 --- a/pcweb/pages/use_cases/finance/views/final_section.py +++ b/pcweb/pages/use_cases/finance/views/final_section.py @@ -14,7 +14,7 @@ def final_section() -> rx.Component: "Spin Up Your First Finance App", "Connect your data source, and ship a working internal tool in an afternoon—no JavaScript required.", ), - class_name="flex lg:flex-row flex-col w-full rounded-2xl border border-m-slate-4 dark:border-m-slate-12 bg-white-1 dark:bg-m-slate-14 z-5 lg:divide-x divide-slate-3 max-lg:divide-y", + class_name="flex xl:flex-row flex-col w-full rounded-2xl border border-m-slate-4 dark:border-m-slate-12 bg-white-1 dark:bg-m-slate-14 z-5 lg:divide-x divide-slate-3 max-lg:divide-y", ), class_name="mx-auto w-full max-w-[71.125rem] relative rounded-4xl border border-slate-4 backdrop-blur-[6px] bg-slate-2/48 p-4 flex z-1 max-lg:mb-6 -mb-px", ) From 91b2c6a8b0c68fdaba4522365c0e50357400424b Mon Sep 17 00:00:00 2001 From: carlosabadia Date: Mon, 15 Dec 2025 19:43:55 +0100 Subject: [PATCH 05/10] updates --- pcweb/pages/use_cases/common/final_section.py | 4 ++-- pcweb/pages/use_cases/common/text_section.py | 8 ++++++-- pcweb/pages/use_cases/finance/views/final_section.py | 2 +- pcweb/pages/use_cases/finance/views/text_section_2.py | 1 + pcweb/pages/use_cases/finance/views/text_section_3.py | 1 + 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pcweb/pages/use_cases/common/final_section.py b/pcweb/pages/use_cases/common/final_section.py index 4732a7d795..1eb40bbf24 100644 --- a/pcweb/pages/use_cases/common/final_section.py +++ b/pcweb/pages/use_cases/common/final_section.py @@ -26,7 +26,7 @@ def right_content(h1: str, description: str) -> rx.Component: to=REFLEX_BUILD_URL, target="_blank", ), - class_name="flex flex-col lg:p-20 p-8 h-full shrink-0", + class_name="flex flex-col lg:p-20 p-8 h-auto", ) @@ -48,5 +48,5 @@ def left_content(h1: str, description: str) -> rx.Component: custom_attrs=get_cal_attrs(), class_name="w-fit font-semibold mt-4", ), - class_name="flex flex-col gap-4 items-start justify-center lg:py-20 py-8 lg:pl-20 pl-8 lg:pr-[7.5rem] pr-8 relative overflow-hidden min-h-fit shrink-0", + class_name="flex flex-col gap-4 items-start justify-center lg:py-20 py-8 lg:pl-20 pl-8 lg:pr-[7.5rem] pr-8 relative overflow-hidden min-h-fit", ) diff --git a/pcweb/pages/use_cases/common/text_section.py b/pcweb/pages/use_cases/common/text_section.py index 4e81221d90..df6e42921d 100644 --- a/pcweb/pages/use_cases/common/text_section.py +++ b/pcweb/pages/use_cases/common/text_section.py @@ -1,4 +1,5 @@ import reflex as rx +import reflex_ui as ui from pcweb.components.numbers_pattern import numbers_pattern @@ -19,10 +20,13 @@ def content(header: str, description: str | None = None) -> rx.Component: ) -def text_section(header: str, description: str) -> rx.Component: +def text_section(header: str, description: str, class_name: str = "") -> rx.Component: return rx.el.section( numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), content(header, description), - class_name="flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20 border-t", + class_name=ui.cn( + "flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20 border-t", + class_name, + ), ) diff --git a/pcweb/pages/use_cases/finance/views/final_section.py b/pcweb/pages/use_cases/finance/views/final_section.py index 0fc5cb6391..a492f0ed33 100644 --- a/pcweb/pages/use_cases/finance/views/final_section.py +++ b/pcweb/pages/use_cases/finance/views/final_section.py @@ -14,7 +14,7 @@ def final_section() -> rx.Component: "Spin Up Your First Finance App", "Connect your data source, and ship a working internal tool in an afternoon—no JavaScript required.", ), - class_name="flex xl:flex-row flex-col w-full rounded-2xl border border-m-slate-4 dark:border-m-slate-12 bg-white-1 dark:bg-m-slate-14 z-5 lg:divide-x divide-slate-3 max-lg:divide-y", + class_name="flex xl:flex-row flex-col w-full rounded-2xl border border-m-slate-4 dark:border-m-slate-12 bg-white-1 dark:bg-m-slate-14 z-5 xl:divide-x divide-slate-3 max-xl:divide-y", ), class_name="mx-auto w-full max-w-[71.125rem] relative rounded-4xl border border-slate-4 backdrop-blur-[6px] bg-slate-2/48 p-4 flex z-1 max-lg:mb-6 -mb-px", ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_2.py b/pcweb/pages/use_cases/finance/views/text_section_2.py index bbc3975b1c..1b4a1fc210 100644 --- a/pcweb/pages/use_cases/finance/views/text_section_2.py +++ b/pcweb/pages/use_cases/finance/views/text_section_2.py @@ -7,4 +7,5 @@ def text_section_2() -> rx.Component: return text_section( header="Proven at the World's Leading Institutions", description="From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", + class_name="border-t-0", ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_3.py b/pcweb/pages/use_cases/finance/views/text_section_3.py index 0fe3392aa8..d73fe3337b 100644 --- a/pcweb/pages/use_cases/finance/views/text_section_3.py +++ b/pcweb/pages/use_cases/finance/views/text_section_3.py @@ -7,4 +7,5 @@ def text_section_3() -> rx.Component: return text_section( header="Why Financial Organizations Choose Reflex", description="From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", + class_name="border-t-0", ) From b67594b2b174c9cd32a93a1ea2a5e4c9ca6913ea Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 15 Dec 2025 20:39:50 +0100 Subject: [PATCH 06/10] navbar --- pcweb/components/docpage/navbar/navbar.py | 296 ++++++++++++++++++---- 1 file changed, 243 insertions(+), 53 deletions(-) diff --git a/pcweb/components/docpage/navbar/navbar.py b/pcweb/components/docpage/navbar/navbar.py index 2a5823b4db..d239101147 100644 --- a/pcweb/components/docpage/navbar/navbar.py +++ b/pcweb/components/docpage/navbar/navbar.py @@ -11,6 +11,7 @@ from pcweb.pages.faq import faq from pcweb.pages.framework.framework import framework from pcweb.pages.hosting.hosting import hosting_landing +from pcweb.pages.use_cases.finance import finance_use_case_page from pcweb.pages.use_cases.use_cases import use_cases_page from ...link_button import resources_button @@ -64,6 +65,19 @@ def link_item(name: str, url: str, active_str: str = ""): elif active_str == "hosting" or active_str == "cloud": active = router_path.contains("cloud") | router_path.contains("hosting") + elif active_str == "products": + is_docs = router_path.contains("docs") + is_open_source_page = router_path.contains("open-source") + not_cloud = ~(router_path.contains("cloud") | router_path.contains("hosting")) + not_ai_builder = ~router_path.contains("ai-builder") + is_framework = (is_docs & not_cloud & not_ai_builder) | is_open_source_page + active = ( + router_path.contains("ai-builder") + | router_path.contains("cloud") + | router_path.contains("hosting") + | is_framework + ) + elif active_str == "pricing": active = router_path.contains("pricing") @@ -344,23 +358,160 @@ def _resource_section_column( ) +def solutions_section(): + _app_types_items = [ + { + "label": "Internal Tools", + "url": use_cases_page.path, + "icon": "Settings01Icon", + }, + { + "label": "Data & AI", + "url": use_cases_page.path, + "icon": "Database02Icon", + }, + { + "label": "External Apps", + "url": use_cases_page.path, + "icon": "UserGroupIcon", + }, + ] + + _industries_items = [ + { + "label": "Finance", + "url": finance_use_case_page.path, + "icon": "CreditCardPosIcon", + }, + { + "label": "Healthcare", + "url": use_cases_page.path, + "icon": "HealthIcon", + }, + { + "label": "Consulting", + "url": use_cases_page.path, + "icon": "MentoringIcon", + }, + { + "label": "Enterprise", + "url": use_cases_page.path, + "icon": "Building03Icon", + }, + ] + + def _link_button(label: str, url: str, icon: str) -> rx.Component: + return rx.el.a( + resources_button( + ui.icon(icon, size=16, class_name="flex-shrink-0"), + label, + size="md", + variant="transparent", + class_name="justify-start w-full items-center gap-3", + ), + to=url, + class_name="w-full", + ) + + def _solutions_section_column( + section_title: str, solution_item: list[dict[str, str]] + ): + return rx.box( + rx.box( + rx.text( + section_title, + class_name="text-sm text-slate-12 font-semibold px-2.5 py-1 pb-2", + ), + *[ + _link_button(item["label"], item["url"], item["icon"]) + for item in solution_item + ], + class_name="flex flex-col w-full p-2", + ), + class_name="flex flex-col w-full max-w-[9.1875rem]", + ) + + return ui.navigation_menu.content( + _solutions_section_column("App Types", _app_types_items), + _solutions_section_column("Industries", _industries_items), + # Grid card + rx.box( + rx.el.a( + rx.box( + rx.text( + "Get a personalized demo for your company", + class_name="text-slate-12 text-base font-semibold break-words leading-tight flex-1 min-w-0", + ), + rx.el.button( + rx.icon("chevron-right", class_name="text-secondary-11 size-4"), + class_name="size-6 group-hover:bg-secondary-3 transition-colors rounded-md flex items-center justify-center flex-shrink-0 mt-0.5", + ), + class_name="flex flex-row items-start gap-2 justify-between mb-1 w-full", + ), + rx.text( + "See how Reflex can help your team build apps.", + class_name="text-secondary-11 text-sm font-medium break-words leading-relaxed w-full", + ), + to="/pricing", + class_name="w-[16.5rem] h-full rounded-md shadow-small bg-white-1 dark:bg-m-slate-14 border border-slate-4 dark:border-m-slate-12 flex flex-col gap-2.5 pt-6 pb-6 pl-5 pr-6 relative border-solid group overflow-hidden", + ), + class_name="flex flex-col pt-4 pb-2 pl-3 pr-6 flex-shrink-0 overflow-hidden h-full", + ), + unstyled=True, + class_name=ui.cn( + ui.navigation_menu.class_names.CONTENT, + "flex flex-row gap-4 rounded-xl w-[37rem] font-sans overflow-hidden pt-1.5 pb-1.5 pl-1.5 pr-3", + ), + ) + + def new_menu_trigger( title: str, url: str | None = None, active_str: str = "" ) -> rx.Component: if url: return ui.navigation_menu.trigger(link_item(title, url, active_str)) + + router_path = rx.State.router.page.path + active = False + + if active_str == "products": + is_docs = router_path.contains("docs") + is_open_source_page = router_path.contains("open-source") + not_cloud = ~(router_path.contains("cloud") | router_path.contains("hosting")) + not_ai_builder = ~router_path.contains("ai-builder") + is_framework = (is_docs & not_cloud & not_ai_builder) | is_open_source_page + active = ( + router_path.contains("ai-builder") + | router_path.contains("cloud") + | router_path.contains("hosting") + | is_framework + ) + elif active_str: + active = router_path.contains(active_str) + + common_cn = "p-[1.406rem_0px] font-medium text-sm transition-colors" + active_cn = "shadow-[inset_0_-0.5px_0_0_var(--c-violet-9)] text-violet-9 group-hover:text-violet-9" + unactive_cn = "shadow-none text-secondary-11 group-hover:text-secondary-12" + return ui.navigation_menu.trigger( rx.box( rx.text( title, - class_name="p-[1.406rem_0px] font-medium text-sm text-secondary-11 group-hover:text-secondary-12 transition-colors", + class_name=common_cn + " " + rx.cond(active, active_cn, unactive_cn), ), rx.icon( "chevron-down", - class_name="chevron size-5 !text-secondary-11 group-hover:!text-secondary-12 py-1 mr-0 transition-all ease-out", + class_name=rx.cond( + active, + "chevron size-5 !text-violet-9 group-hover:!text-violet-9 py-1 mr-0 transition-all ease-out", + "chevron size-5 !text-secondary-11 group-hover:!text-secondary-12 py-1 mr-0 transition-all ease-out", + ), aria_hidden="true", ), - class_name="flex-row items-center gap-x-1 group user-select-none cursor-pointer xl:flex hidden", + class_name=ui.cn( + "flex-row items-center gap-x-1 group user-select-none cursor-pointer xl:flex hidden", + common_cn, + ), on_click=rx.stop_propagation, ), style={ @@ -419,10 +570,85 @@ def doc_section(): ) -def new_component_section() -> rx.Component: +def products_section(): from pcweb.pages.docs import ai_builder as ai_builder_pages from pcweb.pages.docs import hosting as hosting_page + return rx.cond( + rx.State.router.page.path.contains("docs") + | rx.State.router.page.path.contains("ai-builder") + | rx.State.router.page.path.contains("cloud"), + ui.navigation_menu.content( + resource_item( + "AI Builder", + ai_builder_pages.overview.best_practices.path, + "MagicWand01Icon", + 0, + ), + resource_item( + "Open Source", + getting_started.introduction.path, + "SourceCodeCircleIcon", + 0, + ), + resource_item( + "Cloud", + hosting_page.deploy_quick_start.path, + "CloudServerIcon", + 0, + ), + unstyled=True, + class_name=ui.cn( + ui.navigation_menu.class_names.CONTENT, + "flex flex-col gap-1.5 m-0 p-1.5 w-[280px] min-w-max h-auto", + ), + ), + ui.navigation_menu.content( + rx.el.a( + rx.box( + ui.icon( + "MagicWand01Icon", + size=16, + class_name="flex-shrink-0 text-secondary-11", + ), + rx.text( + "AI Builder", + class_name="font-small text-secondary-11 truncate text-start w-[150px]", + ), + rx.icon( + tag="chevron_right", + size=14, + stroke_width=2, + class_name="flex-shrink-0 text-slate-8 ml-auto", + ), + class_name="flex flex-row flex-nowrap items-center gap-4 hover:bg-secondary-3 px-[1.125rem] py-2 rounded-md w-full transition-colors", + ), + class_name="w-full text-secondary-11 hover:text-secondary-11", + href=REFLEX_BUILD_URL, + is_external=True, + ), + resource_item( + "Open Source", + framework.path, + "SourceCodeCircleIcon", + 0, + ), + resource_item( + "Cloud", + hosting_landing.path, + "CloudServerIcon", + 0, + ), + unstyled=True, + class_name=ui.cn( + ui.navigation_menu.class_names.CONTENT, + "flex flex-col gap-1.5 m-0 p-1.5 w-[280px] min-w-max h-auto", + ), + ), + ) + + +def new_component_section() -> rx.Component: return ui.navigation_menu.root( ui.navigation_menu.list( ui.navigation_menu.item( @@ -446,56 +672,14 @@ def new_component_section() -> rx.Component: unstyled=True, ), ), - rx.cond( - rx.State.router.page.path.contains("docs") - | rx.State.router.page.path.contains("ai-builder") - | rx.State.router.page.path.contains("cloud"), - ui.navigation_menu.list( - ui.navigation_menu.item( - render_=link_item( - "AI Builder", - ai_builder_pages.overview.best_practices.path, - "builder", - ), - unstyled=True, - ), - ui.navigation_menu.item( - render_=link_item( - "Open Source", - getting_started.introduction.path, - "framework", - ), - unstyled=True, - class_name="whitespace-nowrap", - ), - ui.navigation_menu.item( - render_=link_item( - "Cloud", hosting_page.deploy_quick_start.path, "hosting" - ), - unstyled=True, - ), - class_name="xl:flex hidden flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none", - ), - ui.navigation_menu.list( - ui.navigation_menu.item( - render_=link_item( - "AI Builder", - REFLEX_BUILD_URL, - "builder", - ), - unstyled=True, - ), - ui.navigation_menu.item( - render_=link_item("Open Source", framework.path, "framework"), - class_name="whitespace-nowrap", - unstyled=True, - ), - ui.navigation_menu.item( - render_=link_item("Cloud", hosting_landing.path, "hosting"), - unstyled=True, - ), - class_name="xl:flex hidden flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none", + ui.navigation_menu.list( + ui.navigation_menu.item( + new_menu_trigger("Product", active_str="products"), + products_section(), + class_name="cursor-pointer", + unstyled=True, ), + class_name="xl:flex hidden flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none", ), ui.navigation_menu.item( new_menu_trigger("Docs"), @@ -516,6 +700,12 @@ def new_component_section() -> rx.Component: class_name="cursor-pointer", unstyled=True, ), + ui.navigation_menu.item( + new_menu_trigger("Solutions", active_str="use-cases"), + solutions_section(), + class_name="cursor-pointer", + unstyled=True, + ), ui.navigation_menu.item( ui.navigation_menu.item( render_=link_item( From 504868c25cd1067052dfacea9f1dcc03ecc3a04c Mon Sep 17 00:00:00 2001 From: Carlos Date: Tue, 16 Dec 2025 14:16:15 +0100 Subject: [PATCH 07/10] healthcare page --- assets/companies/light/dana_farber.svg | 1 + assets/companies/light/drager.svg | 3 + assets/companies/light/ggdzl.svg | 1 + assets/companies/light/mercy.svg | 1 + .../companies/light/united_health_group.svg | 1 + assets/companies/light/wvu_medicine.svg | 76 +++++++++++++++++++ pcweb/components/docpage/navbar/navbar.py | 3 +- pcweb/pages/__init__.py | 1 + pcweb/pages/pricing/faq.py | 2 +- pcweb/pages/use_cases/common/faq.py | 40 ++++++++++ pcweb/pages/use_cases/common/features_1.py | 27 +++++-- pcweb/pages/use_cases/common/features_2.py | 7 +- .../pages/use_cases/common/logos_carousel.py | 25 ++++++ pcweb/pages/use_cases/common/social_proof.py | 6 +- pcweb/pages/use_cases/common/stats.py | 15 +++- .../use_cases/finance/views/features_1.py | 8 +- .../use_cases/finance/views/features_2.py | 8 +- pcweb/pages/use_cases/finance/views/stats.py | 8 +- .../use_cases/finance/views/text_section_1.py | 1 + pcweb/pages/use_cases/healthcare/__init__.py | 33 ++++++++ pcweb/pages/use_cases/healthcare/views/faq.py | 30 ++++++++ .../use_cases/healthcare/views/features_1.py | 69 +++++++++++++++++ .../use_cases/healthcare/views/features_2.py | 33 ++++++++ .../healthcare/views/final_section.py | 20 +++++ .../pages/use_cases/healthcare/views/hero.py | 38 ++++++++++ .../healthcare/views/social_proof.py | 37 +++++++++ .../pages/use_cases/healthcare/views/stats.py | 39 ++++++++++ .../healthcare/views/text_section_1.py | 10 +++ .../healthcare/views/text_section_2.py | 11 +++ .../healthcare/views/text_section_3.py | 11 +++ .../healthcare/views/text_section_4.py | 11 +++ 31 files changed, 548 insertions(+), 28 deletions(-) create mode 100644 assets/companies/light/dana_farber.svg create mode 100644 assets/companies/light/drager.svg create mode 100644 assets/companies/light/ggdzl.svg create mode 100644 assets/companies/light/mercy.svg create mode 100644 assets/companies/light/united_health_group.svg create mode 100644 assets/companies/light/wvu_medicine.svg create mode 100644 pcweb/pages/use_cases/common/faq.py create mode 100644 pcweb/pages/use_cases/common/logos_carousel.py create mode 100644 pcweb/pages/use_cases/healthcare/__init__.py create mode 100644 pcweb/pages/use_cases/healthcare/views/faq.py create mode 100644 pcweb/pages/use_cases/healthcare/views/features_1.py create mode 100644 pcweb/pages/use_cases/healthcare/views/features_2.py create mode 100644 pcweb/pages/use_cases/healthcare/views/final_section.py create mode 100644 pcweb/pages/use_cases/healthcare/views/hero.py create mode 100644 pcweb/pages/use_cases/healthcare/views/social_proof.py create mode 100644 pcweb/pages/use_cases/healthcare/views/stats.py create mode 100644 pcweb/pages/use_cases/healthcare/views/text_section_1.py create mode 100644 pcweb/pages/use_cases/healthcare/views/text_section_2.py create mode 100644 pcweb/pages/use_cases/healthcare/views/text_section_3.py create mode 100644 pcweb/pages/use_cases/healthcare/views/text_section_4.py diff --git a/assets/companies/light/dana_farber.svg b/assets/companies/light/dana_farber.svg new file mode 100644 index 0000000000..18e66a0524 --- /dev/null +++ b/assets/companies/light/dana_farber.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/light/drager.svg b/assets/companies/light/drager.svg new file mode 100644 index 0000000000..9b53113ca1 --- /dev/null +++ b/assets/companies/light/drager.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/assets/companies/light/ggdzl.svg b/assets/companies/light/ggdzl.svg new file mode 100644 index 0000000000..ab77cf7a09 --- /dev/null +++ b/assets/companies/light/ggdzl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/light/mercy.svg b/assets/companies/light/mercy.svg new file mode 100644 index 0000000000..78768e3afb --- /dev/null +++ b/assets/companies/light/mercy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/companies/light/united_health_group.svg b/assets/companies/light/united_health_group.svg new file mode 100644 index 0000000000..fe4089d761 --- /dev/null +++ b/assets/companies/light/united_health_group.svg @@ -0,0 +1 @@ +United Health Group Logo \ No newline at end of file diff --git a/assets/companies/light/wvu_medicine.svg b/assets/companies/light/wvu_medicine.svg new file mode 100644 index 0000000000..356cf69f84 --- /dev/null +++ b/assets/companies/light/wvu_medicine.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcweb/components/docpage/navbar/navbar.py b/pcweb/components/docpage/navbar/navbar.py index d239101147..44015e63fa 100644 --- a/pcweb/components/docpage/navbar/navbar.py +++ b/pcweb/components/docpage/navbar/navbar.py @@ -12,6 +12,7 @@ from pcweb.pages.framework.framework import framework from pcweb.pages.hosting.hosting import hosting_landing from pcweb.pages.use_cases.finance import finance_use_case_page +from pcweb.pages.use_cases.healthcare import healthcare_use_case_page from pcweb.pages.use_cases.use_cases import use_cases_page from ...link_button import resources_button @@ -385,7 +386,7 @@ def solutions_section(): }, { "label": "Healthcare", - "url": use_cases_page.path, + "url": healthcare_use_case_page.path, "icon": "HealthIcon", }, { diff --git a/pcweb/pages/__init__.py b/pcweb/pages/__init__.py index 136a17d8f2..77429d7388 100644 --- a/pcweb/pages/__init__.py +++ b/pcweb/pages/__init__.py @@ -21,6 +21,7 @@ from .security.security import security_page as security_page from .to_be_booked import to_be_booked as to_be_booked from .use_cases.finance import finance_use_case_page as finance_use_case_page +from .use_cases.healthcare import healthcare_use_case_page as healthcare_use_case_page from .use_cases.use_cases import use_cases_page as use_cases_page routes = [ diff --git a/pcweb/pages/pricing/faq.py b/pcweb/pages/pricing/faq.py index db57d6f08d..5ae0448a44 100644 --- a/pcweb/pages/pricing/faq.py +++ b/pcweb/pages/pricing/faq.py @@ -61,7 +61,7 @@ def accordion(title: str, content: rx.Component) -> rx.Component: size=16, class_name="!text-slate-9 group-data-[state=open]:rotate-45 transition-transform", ), - class_name="hover:!bg-transparent !p-[0.5rem_0rem] !justify-between gap-4 group", + class_name="hover:!bg-transparent !bg-transparent !p-[0.5rem_0rem] !justify-between gap-4 group", ), rx.accordion.content( content, diff --git a/pcweb/pages/use_cases/common/faq.py b/pcweb/pages/use_cases/common/faq.py new file mode 100644 index 0000000000..9101c1e810 --- /dev/null +++ b/pcweb/pages/use_cases/common/faq.py @@ -0,0 +1,40 @@ +import reflex as rx +import reflex_ui as ui + +from pcweb.components.numbers_pattern import numbers_pattern +from pcweb.pages.pricing.faq import accordion, accordion_text + + +def content(header: str, description: str | None = None) -> rx.Component: + return rx.el.div( + rx.el.h2( + header, + class_name="max-w-full w-full lg:text-3xl text-2xl text-center text-slate-12 font-semibold", + ), + rx.el.p( + description, + class_name="text-m-slate-11 dark:text-slate-9 text-sm font-medium text-center", + ) + if description + else None, + class_name="flex flex-col gap-4 items-center mx-auto w-full relative overflow-hidden max-w-[26.5rem] text-center", + ) + + +def faq_section(faq_items: list[tuple[str, str]], class_name: str = "") -> rx.Component: + return rx.el.section( + numbers_pattern(side="left", reverse=True, class_name="left-0 top-0"), + numbers_pattern(side="right", reverse=True, class_name="right-0 top-0"), + content("Frequently Asked Questions"), + rx.el.div( + *[ + accordion(title, accordion_text(content)) + for title, content in faq_items + ], + class_name="max-w-[35rem] flex justify-center items-center flex-col mx-auto w-full gap-2 mt-[2rem]", + ), + class_name=ui.cn( + "flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + class_name, + ), + ) diff --git a/pcweb/pages/use_cases/common/features_1.py b/pcweb/pages/use_cases/common/features_1.py index 6a3e4fd9b9..9be1b71c3b 100644 --- a/pcweb/pages/use_cases/common/features_1.py +++ b/pcweb/pages/use_cases/common/features_1.py @@ -1,15 +1,32 @@ import reflex as rx +import reflex_ui as ui -from pcweb.components.icons import get_icon - -def feature_card(icon: str, title: str, description: str) -> rx.Component: +def feature_card( + icon: str, title: str, description: str = "", items: list[str] | None = None +) -> rx.Component: return rx.el.div( - get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), + ui.icon( + icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0 size-7" + ), rx.el.span(title, class_name="font-semibold text-slate-12 text-lg mt-2"), rx.el.p( description, class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", - ), + ) + if description + else None, + rx.el.ul( + *[ + rx.el.li( + item, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium mt-1", + ) + for item in items + ], + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium list-disc list-inside", + ) + if items + else None, class_name="flex flex-col items-start gap-2 p-10 lg:border-r border-b border-slate-3", ) diff --git a/pcweb/pages/use_cases/common/features_2.py b/pcweb/pages/use_cases/common/features_2.py index 6f2b411528..8e4295b82c 100644 --- a/pcweb/pages/use_cases/common/features_2.py +++ b/pcweb/pages/use_cases/common/features_2.py @@ -1,11 +1,12 @@ import reflex as rx - -from pcweb.components.icons import get_icon +import reflex_ui as ui def feature_card(icon: str, stat: str, title: str, description: str) -> rx.Component: return rx.el.div( - get_icon(icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0"), + ui.icon( + icon, class_name="text-m-violet-9 dark:text-m-violet-10 shrink-0 size-5" + ), rx.el.span( stat, class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-sm mt-4", diff --git a/pcweb/pages/use_cases/common/logos_carousel.py b/pcweb/pages/use_cases/common/logos_carousel.py new file mode 100644 index 0000000000..bda3aebb75 --- /dev/null +++ b/pcweb/pages/use_cases/common/logos_carousel.py @@ -0,0 +1,25 @@ +import reflex as rx + +from pcweb.components.marquee import marquee + + +def social_proof_card(image: str) -> rx.Component: + return rx.el.div( + rx.image( + f"/companies/light/{image}.svg", + loading="lazy", + alt=f"{image} logo", + class_name="grayscale-100 max-h-[2.5rem] opacity-90 dark:opacity-100", + ), + class_name="flex justify-center items-center h-[10.75rem] min-w-[10.75rem] px-4 w-auto relative overflow-hidden lg:border-r border-slate-3", + ) + + +def logos_carousel(logos: list[str]) -> rx.Component: + return marquee( + *[social_proof_card(logo) for logo in logos], + direction="left", + class_name="h-[10.75rem] w-full overflow-hidden", + gradient_width=0, + speed=50, + ) diff --git a/pcweb/pages/use_cases/common/social_proof.py b/pcweb/pages/use_cases/common/social_proof.py index c84758b45b..23e6f82954 100644 --- a/pcweb/pages/use_cases/common/social_proof.py +++ b/pcweb/pages/use_cases/common/social_proof.py @@ -10,9 +10,9 @@ def first_card(title: str) -> rx.Component: ), rx.el.span( title, - class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium text-nowrap", + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium text-wrap", ), - class_name="flex flex-row gap-2.5 items-center max-lg:justify-center lg:col-span-2 px-10 h-full max-lg:h-[10.75rem] max-lg:w-full", + class_name="flex flex-row gap-2.5 items-center max-lg:justify-center lg:col-span-2 px-10 h-full max-lg:h-[10.75rem] max-lg:w-full lg:border-r border-b w-full", ) @@ -25,7 +25,7 @@ def social_proof_card(image: str) -> rx.Component: loading="lazy", alt=f"{image} logo", ), - class_name="flex justify-center items-center lg:size-[10.75rem] max-lg:h-[10.75rem] max-lg:w-full", + class_name="flex justify-center items-center lg:size-[10.75rem] max-lg:h-[10.75rem] max-lg:w-full lg:border-r border-b", ) diff --git a/pcweb/pages/use_cases/common/stats.py b/pcweb/pages/use_cases/common/stats.py index ed3d8ab3a4..224fe2f863 100644 --- a/pcweb/pages/use_cases/common/stats.py +++ b/pcweb/pages/use_cases/common/stats.py @@ -1,16 +1,25 @@ import reflex as rx -def stat_card(stat: str, title: str, description: str) -> rx.Component: +def stat_card( + title: str, description: str, stat: str = "", accent: bool = False +) -> rx.Component: return rx.el.div( rx.el.span( stat, class_name="font-semibold text-m-violet-9 dark:text-m-violet-10 text-3xl", + ) + if stat + else None, + rx.el.span( + title, + class_name="font-semibold text-slate-12 text-sm" + if not accent + else "text-sm font-semibold text-m-violet-9 dark:text-m-violet-10", ), - rx.el.span(title, class_name="font-semibold text-slate-12 text-sm"), rx.el.p( description, class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium", ), - class_name="flex flex-col items-start p-10 gap-2", + class_name="flex flex-col items-start p-10 gap-2 border-slate-3 lg:border-b lg:border-r", ) diff --git a/pcweb/pages/use_cases/finance/views/features_1.py b/pcweb/pages/use_cases/finance/views/features_1.py index 0ce07962e7..1a09c01658 100644 --- a/pcweb/pages/use_cases/finance/views/features_1.py +++ b/pcweb/pages/use_cases/finance/views/features_1.py @@ -6,22 +6,22 @@ def features_1() -> rx.Component: return rx.el.section( feature_card( - "ai-04", + "ArtificialIntelligence04Icon", "Ship AI-Powered Tools Securely", "Build chat-based assistants and RAG apps in Python, deployed inside your own cloud or on-prem, with full control over where data lives.", ), feature_card( - "refresh-dot", + "RepeatIcon", "Modernize Legacy Internal Apps", "Replace fragile in-house dashboards with maintainable Python apps that plug into your existing data stack.", ), feature_card( - "flow-connection", + "FlowConnectionIcon", "Automate Workflows, Not Just Reports", "Turn manual compliance checks, KYC workflows, and operations processes into interactive apps—tied to your systems, not screenshots.", ), feature_card( - "layers-01", + "Layers01Icon", "Orchestrate End-to-End Lifecycles", "Let researchers, analysts, and quants move from 'run a script in a Jupyter notebook' to 'share a full app' using the same language they already know.", ), diff --git a/pcweb/pages/use_cases/finance/views/features_2.py b/pcweb/pages/use_cases/finance/views/features_2.py index 5cb6a09533..415f98c7a0 100644 --- a/pcweb/pages/use_cases/finance/views/features_2.py +++ b/pcweb/pages/use_cases/finance/views/features_2.py @@ -6,25 +6,25 @@ def features_2() -> rx.Component: return rx.el.section( feature_card( - "zap-01", + "ZapIcon", "Speed to Production", "Ship Internal Tools 10x Faster", "Reflex lets Python teams build production-grade apps without leaving their language. Crédit Agricole’s R&D team built a full chatbot analytics dashboard in two days and is rolling it out to 100+ users, without adding a single React engineer.", ), feature_card( - "python-01", + "PythonIcon", "Python-first Flexibility", "Let Experts Build, Not Just Consume", "At Man Group, 50+ researchers write Python, not JavaScript. Reflex gives them a full-Python framework to create dashboards and model views without touching javascript front-end code, while the platform team wraps their internal design system.", ), feature_card( - "shield-key", + "ShieldKeyIcon", "Full Control & Enterprise Deployment", "Run in Your Cloud, Offline if Needed", "Reflex Enterprise runs fully on-prem or in your own cloud. Man Group deploys Reflex apps in air-gapped environments; CACIB and the World Bank run Reflex inside internal AWS and Azure environments with their own SSO, logging, and infra.", ), feature_card( - "chart-up", + "ChartUpIcon", "Agility & Cost Efficiency", "Do More With Your Python Team", "Bayesline avoided hiring a front-end engineer and shipped a fintech SaaS app entirely in Python; One engineer can do the work of two by collapsing front- and back-end into a single Reflex codebase.", diff --git a/pcweb/pages/use_cases/finance/views/stats.py b/pcweb/pages/use_cases/finance/views/stats.py index 0b206743af..788669deb7 100644 --- a/pcweb/pages/use_cases/finance/views/stats.py +++ b/pcweb/pages/use_cases/finance/views/stats.py @@ -6,24 +6,24 @@ def stats() -> rx.Component: return rx.el.section( stat_card( - "10x", "Faster Development", "Vs. legacy front-end stacks (Crédit Agricole CIB)", + "10x", ), stat_card( - "50+", "Quant Researchers", "Building dashboards in Python (Man Group)", + "50+", ), stat_card( - "100+", "Legal Professionals", "Using AI tools replacing Tableau (World Bank)", + "100+", ), stat_card( - "4x", "Faster & 50% Less Code", "Vs. Dash/React for fintech analytics (Bayesline)", + "4x", ), class_name="grid lg:grid-cols-4 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden border-t lg:divide-x divide-slate-3 max-lg:divide-y", ) diff --git a/pcweb/pages/use_cases/finance/views/text_section_1.py b/pcweb/pages/use_cases/finance/views/text_section_1.py index 6786ac9d1d..fc0e775b68 100644 --- a/pcweb/pages/use_cases/finance/views/text_section_1.py +++ b/pcweb/pages/use_cases/finance/views/text_section_1.py @@ -7,4 +7,5 @@ def text_section_1() -> rx.Component: return text_section( header="Balance Resilience and Innovation", description="Financial organizations are under pressure from every side: volatile markets, new regulations, GenAI, and rising expectations. Most internal tools haven't kept up.", + class_name="border-t-0", ) diff --git a/pcweb/pages/use_cases/healthcare/__init__.py b/pcweb/pages/use_cases/healthcare/__init__.py new file mode 100644 index 0000000000..8aca31b539 --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/__init__.py @@ -0,0 +1,33 @@ +import reflex as rx + +from pcweb.meta.meta import meta_tags +from pcweb.pages.use_cases.healthcare.views.faq import faq +from pcweb.pages.use_cases.healthcare.views.features_1 import features_1 +from pcweb.pages.use_cases.healthcare.views.features_2 import features_2 +from pcweb.pages.use_cases.healthcare.views.final_section import final_section +from pcweb.pages.use_cases.healthcare.views.hero import hero +from pcweb.pages.use_cases.healthcare.views.social_proof import social_proof +from pcweb.pages.use_cases.healthcare.views.stats import stats +from pcweb.pages.use_cases.healthcare.views.text_section_1 import text_section_1 +from pcweb.pages.use_cases.healthcare.views.text_section_3 import text_section_3 +from pcweb.pages.use_cases.healthcare.views.text_section_4 import text_section_4 +from pcweb.templates.mainpage import mainpage + + +@mainpage( + path="/use-cases/healthcare", title="Healthcare Use Case - Reflex", meta=meta_tags +) +def healthcare_use_case_page() -> rx.Component: + return rx.el.div( + hero(), + social_proof(), + text_section_3(), + features_2(), + text_section_1(), + features_1(), + text_section_4(), + stats(), + faq(), + final_section(), + class_name="flex flex-col size-full justify-center items-center max-w-[calc(100vw-2rem)] mx-auto", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/faq.py b/pcweb/pages/use_cases/healthcare/views/faq.py new file mode 100644 index 0000000000..eb532730c1 --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/faq.py @@ -0,0 +1,30 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.faq import faq_section + + +def faq() -> rx.Component: + return faq_section( + faq_items=[ + ( + "Is Reflex HIPAA-compliant?", + "Yes, Reflex apps can be deployed in fully self-hosted, HIPAA-compliant environments with PHI remaining entirely under your control.", + ), + ( + "Do I need frontend experience?", + "No. Reflex handles frontend automatically. You type Prompts or write Python; Reflex generates the UI.", + ), + ( + "Can non-developers use the AI builder?", + "Yes, the AI builder allows clinicians, analysts, and operations teams to generate apps from natural-language prompts.", + ), + ( + "Can Reflex replace spreadsheets?", + "Absolutely, many healthcare teams use Reflex to create secure, auditable, workflow-specific replacements.", + ), + ( + "Can I integrate with (Epic / Cerner / Athena / HL7 / FHIR)?", + "Yes, Reflex runs in Python, so integrations are straightforward using Premium built-in integrations or using available SDKs or APIs.", + ), + ], + ) diff --git a/pcweb/pages/use_cases/healthcare/views/features_1.py b/pcweb/pages/use_cases/healthcare/views/features_1.py new file mode 100644 index 0000000000..a6497e5b63 --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/features_1.py @@ -0,0 +1,69 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.features_1 import feature_card + + +def features_1() -> rx.Component: + return rx.el.section( + feature_card( + "Hospital02Icon", + "Electronic Medical Record (EMR) & Patient Tools", + items=[ + "Internal EMR viewers", + "Patient intake dashboards", + "Referral and triage portals", + "Physician scheduling tools", + ], + ), + feature_card( + "TestTube02Icon", + "Lab, Research & Clinical Ops Tools", + items=[ + "Lab workflow management", + "Clinical trials data dashboards", + "Sample tracking and chain of custody", + "Adverse event reporting systems", + ], + ), + feature_card( + "Analytics01Icon", + "Healthcare Analytics & BI Dashboards", + items=[ + "Outcomes tracking", + "Operational KPIs", + "Financial & claims analytics", + "Provider performance dashboards", + ], + ), + feature_card( + "ArtificialIntelligence04Icon", + "AI-Driven Assistants and RAG Chatbots", + items=[ + "PHI-safe medical documentation assistants", + "Staff support tools", + "AI routing and triage helpers", + "Knowledge base Q&A over internal documents", + ], + ), + feature_card( + "ShieldUserIcon", + "Administrative & Compliance Automation", + items=[ + "HIPAA training dashboards", + "Staff credentialing systems", + "Equipment & inventory management", + "Audit reporting automation", + ], + ), + feature_card( + "UserMultipleIcon", + "Patient & Staff Portals", + items=[ + "Secure messaging", + "Case management", + "Payment flows", + "Appointment scheduling", + ], + ), + class_name="grid lg:grid-cols-2 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-l border-slate-3 relative overflow-hidden border-t", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/features_2.py b/pcweb/pages/use_cases/healthcare/views/features_2.py new file mode 100644 index 0000000000..071f8b7355 --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/features_2.py @@ -0,0 +1,33 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.features_2 import feature_card + + +def features_2() -> rx.Component: + return rx.el.section( + feature_card( + "ArtificialIntelligence04Icon", + "AI App Builder for Healthcare", + "Build complete healthcare applications from a prompt", + "Reflex AI generates Python code, UI components, and data connections — all editable and production-ready. Hear from Matt, CEO of Playspace: 'I just built an app and beyond impressed by the output. I asked claude to create a PRD from a URL/app that i wanted to copy. I uploaded the PDF to reflex and just said build this and it did, including some advanced capabilities like image and video generation within the app.'", + ), + feature_card( + "ShieldKeyIcon", + "HIPAA-Compliant by Design", + "Self-host on your infrastructure with full control", + "Self-host Reflex apps on your own infrastructure, VPC, or air-gapped environment with fully encrypted data and no external internet required. Perfect for PHI, clinical workflows, and sensitive analytics. Built for enterprise IT & compliance teams with full auditability, identity control and role-based access.", + ), + feature_card( + "ZapIcon", + "10x Faster Than Traditional Development", + "Move from idea to deployed app in hours, not months", + "Reflex handles frontend, backend, state management, and deployment so your team can focus on patient outcomes and operational efficiency. Build production-grade healthcare apps without leaving Python or waiting on front-end teams.", + ), + feature_card( + "PlugSocketIcon", + "Designed for Data-Intensive Healthcare Workflows", + "Native Python environment for all your integrations", + "Integrate EMR/EHR data, HL7 & FHIR APIs, claims & billing systems, research databases, Snowflake, Postgres, Databricks, BigQuery, and clinical analytics & ML models — all in pure Python without switching contexts or languages.", + ), + class_name="grid lg:grid-cols-4 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden border-t lg:divide-x divide-slate-3 max-lg:divide-y", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/final_section.py b/pcweb/pages/use_cases/healthcare/views/final_section.py new file mode 100644 index 0000000000..899dc33d3e --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/final_section.py @@ -0,0 +1,20 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.final_section import left_content, right_content + + +def final_section() -> rx.Component: + return rx.el.section( + rx.el.div( + left_content( + "Start Building Secure Healthcare Apps with Reflex", + "Turn your workflows into AI-powered applications — fast, compliant, and fully customizable.", + ), + right_content( + "Spin Up Your First Healthcare App", + "Connect your data source, and ship a working internal tool in an afternoon—no JavaScript required.", + ), + class_name="flex xl:flex-row flex-col w-full rounded-2xl border border-m-slate-4 dark:border-m-slate-12 bg-white-1 dark:bg-m-slate-14 z-5 xl:divide-x divide-slate-3 max-xl:divide-y", + ), + class_name="mx-auto w-full max-w-[71.125rem] relative rounded-4xl border border-slate-4 backdrop-blur-[6px] bg-slate-2/48 p-4 flex z-1 max-lg:mb-6 -mb-px", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/hero.py b/pcweb/pages/use_cases/healthcare/views/hero.py new file mode 100644 index 0000000000..a56f3e2b3e --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/hero.py @@ -0,0 +1,38 @@ +import reflex as rx + +from pcweb.components.numbers_pattern import numbers_pattern +from pcweb.pages.use_cases.common.hero import left_content, right_content + + +def hero() -> rx.Component: + return rx.el.section( + numbers_pattern( + side="right", + class_name="lg:top-[65px] top-[45px] lg:h-[calc(100%-65px)] h-[calc(100%-45px)] max-lg:hidden", + ), + rx.el.div( + left_content( + "Build HIPAA-Compliant Healthcare Apps —", + " 10x Faster with Reflex AI", + "The fastest way for healthcare teams to build secure internal tools, dashboards, and AI-powered workflows using only Python. Fully HIPAA-compliant, enterprise-ready, and deployable anywhere.", + "Talk to a solutions engineer", + "Book a healthcare demo", + ), + right_content( + [ + ( + "ShieldEnergyIcon", + "Build HIPAA-compliant internal tools and patient data apps", + ), + ("DashboardSpeed01Icon", "Develop up to 10x faster in pure Python"), + ("PythonIcon", "Go in Python from prototype to production"), + ( + "BrowserIcon", + "From patient dashboards and clinical workflows to AI-powered medical chatbots", + ), + ], + ), + class_name="flex lg:flex-row flex-col lg:gap-20 gap-10 max-lg:items-center max-lg:justify-center max-lg:text-center", + ), + class_name="flex flex-col justify-center items-center gap-4 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 pb-[3rem] pt-32 lg:pt-[11.5rem] lg:pb-[7.5rem] relative lg:overflow-hidden overflow-hidden z-[1] lg:px-10", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/social_proof.py b/pcweb/pages/use_cases/healthcare/views/social_proof.py new file mode 100644 index 0000000000..edbcb29935 --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/social_proof.py @@ -0,0 +1,37 @@ +import reflex as rx +import reflex_ui as ui + +from pcweb.pages.use_cases.common.logos_carousel import logos_carousel + +LOGOS = [ + "dana_farber", + "united_health_group", + "ggdzl", + "mercy", + "drager", + "wvu_medicine", +] + + +def first_card(title: str) -> rx.Component: + return rx.el.div( + ui.icon( + "CheckmarkBadge02Icon", + class_name="text-m-slate-11 dark:text-m-slate-9 shrink-0", + ), + rx.el.span( + title, + class_name="text-m-slate-11 dark:text-m-slate-9 text-sm font-medium text-wrap", + ), + class_name="flex flex-row gap-2.5 items-center max-lg:justify-center lg:col-span-2 px-10 h-full max-lg:h-[10.75rem] max-lg:w-full w-full lg:border-r", + ) + + +def social_proof() -> rx.Component: + return rx.el.div( + first_card( + "Reflex powers mission-critical internal apps used by thousands of employees worldwide." + ), + logos_carousel(LOGOS), + class_name="flex lg:flex-row flex-col justify-center items-center mx-auto w-full max-w-[64.19rem] lg:border border-slate-3 h-[10.75rem] z-1", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/stats.py b/pcweb/pages/use_cases/healthcare/views/stats.py new file mode 100644 index 0000000000..25fef9f0fa --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/stats.py @@ -0,0 +1,39 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.stats import stat_card + + +def stats() -> rx.Component: + return rx.el.section( + stat_card( + "Self-host anywhere", + "VPC, on-prem, or air-gapped environments", + accent=True, + ), + stat_card( + "Full control over PHI", + "Reflex never sees your data", + accent=True, + ), + stat_card( + "Encrypted data & secure architecture", + "Built for enterprise healthcare security", + accent=True, + ), + stat_card( + "Role-based access control", + "Audit trails and identity management", + accent=True, + ), + stat_card( + "HIPAA & SOC 2 compatible", + "Deploy in compliant environments", + accent=True, + ), + stat_card( + "No vendor lock-in", + "Own your code and infrastructure completely", + accent=True, + ), + class_name="grid lg:grid-cols-3 grid-cols-1 mx-auto w-full max-w-[64.19rem] border-slate-3 relative overflow-hidden border-t max-lg:divide-y lg:border-l", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/text_section_1.py b/pcweb/pages/use_cases/healthcare/views/text_section_1.py new file mode 100644 index 0000000000..62f2d3e6bd --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/text_section_1.py @@ -0,0 +1,10 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.text_section import text_section + + +def text_section_1() -> rx.Component: + return text_section( + header="What You Can Build with Reflex", + description="Healthcare organizations use Reflex to create fully custom applications using AI including:", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/text_section_2.py b/pcweb/pages/use_cases/healthcare/views/text_section_2.py new file mode 100644 index 0000000000..1b4a1fc210 --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/text_section_2.py @@ -0,0 +1,11 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.text_section import text_section + + +def text_section_2() -> rx.Component: + return text_section( + header="Proven at the World's Leading Institutions", + description="From global banks to agile fintechs, see how teams are transforming their internal tools with Reflex.", + class_name="border-t-0", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/text_section_3.py b/pcweb/pages/use_cases/healthcare/views/text_section_3.py new file mode 100644 index 0000000000..faf5769eea --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/text_section_3.py @@ -0,0 +1,11 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.text_section import text_section + + +def text_section_3() -> rx.Component: + return text_section( + header="Why Healthcare Teams Choose Reflex", + description="Reflex offers the speed of no-code with the power of full-code, ideal for healthcare. Healthcare organizations use Reflex to create fully custom applications using AI including:", + class_name="border-t-0", + ) diff --git a/pcweb/pages/use_cases/healthcare/views/text_section_4.py b/pcweb/pages/use_cases/healthcare/views/text_section_4.py new file mode 100644 index 0000000000..5d8a371191 --- /dev/null +++ b/pcweb/pages/use_cases/healthcare/views/text_section_4.py @@ -0,0 +1,11 @@ +import reflex as rx + +from pcweb.pages.use_cases.common.text_section import text_section + + +def text_section_4() -> rx.Component: + return text_section( + header="HIPAA Compliance & Security", + description="Reflex is purpose-built for regulated industries. Reflex does not transmit, store, or access PHI. Perfect for organizations needing complete security and observability.", + class_name="border-t-0", + ) From 73e4e0e92fe2e23e3b935a3fa9dd7ea7a7358c72 Mon Sep 17 00:00:00 2001 From: Carlos Date: Tue, 16 Dec 2025 14:16:53 +0100 Subject: [PATCH 08/10] health care page --- pcweb/pages/use_cases/common/faq.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pcweb/pages/use_cases/common/faq.py b/pcweb/pages/use_cases/common/faq.py index 9101c1e810..7180d70e9b 100644 --- a/pcweb/pages/use_cases/common/faq.py +++ b/pcweb/pages/use_cases/common/faq.py @@ -34,7 +34,7 @@ def faq_section(faq_items: list[tuple[str, str]], class_name: str = "") -> rx.Co class_name="max-w-[35rem] flex justify-center items-center flex-col mx-auto w-full gap-2 mt-[2rem]", ), class_name=ui.cn( - "flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20", + "flex flex-col items-center mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden py-20 max-lg:px-4", class_name, ), ) From 461746ebbae75a2d6d289d6a166011313c7a9582 Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 16 Dec 2025 14:29:30 -0800 Subject: [PATCH 09/10] fixes for removing man --- .../use_cases/finance/views/features_2.py | 2 +- pcweb/pages/use_cases/finance/views/quotes.py | 42 +++++++++---------- pcweb/pages/use_cases/finance/views/stats.py | 9 +--- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/pcweb/pages/use_cases/finance/views/features_2.py b/pcweb/pages/use_cases/finance/views/features_2.py index 415f98c7a0..812c7d0caa 100644 --- a/pcweb/pages/use_cases/finance/views/features_2.py +++ b/pcweb/pages/use_cases/finance/views/features_2.py @@ -15,7 +15,7 @@ def features_2() -> rx.Component: "PythonIcon", "Python-first Flexibility", "Let Experts Build, Not Just Consume", - "At Man Group, 50+ researchers write Python, not JavaScript. Reflex gives them a full-Python framework to create dashboards and model views without touching javascript front-end code, while the platform team wraps their internal design system.", + "Quants and researchers write Python, not JavaScript. Reflex gives them a full-Python framework to create dashboards and model views without touching javascript front-end code.", ), feature_card( "ShieldKeyIcon", diff --git a/pcweb/pages/use_cases/finance/views/quotes.py b/pcweb/pages/use_cases/finance/views/quotes.py index 0f0a2f31b5..219ff16541 100644 --- a/pcweb/pages/use_cases/finance/views/quotes.py +++ b/pcweb/pages/use_cases/finance/views/quotes.py @@ -6,32 +6,28 @@ def quotes() -> rx.Component: return rx.el.section( quote_card( - "Automate Analytics for Internal AI Tools.", - "Deploy Bank-Grade Internal Dashboards in Days, Not Months", - "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", - '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', - "FirstName LastName, Crédit Agricole CIB", + "Replace brittle Tableau/Streamlit prototypes with production apps.", + "Go straight from idea to production, without the “prototype then rebuild” cycle", + "At the World Bank, teams were stuck jumping between Tableau dashboards, Streamlit prototypes, and custom JavaScript apps. With Reflex, they’re building production-grade data platforms from day one, including a chat-driven data app with AG Grid tables and an AI-powered legal assistant that lets 100+ lawyers and investigators query internal documents securely within the Bank's Azure environment.", + '"You wouldn’t want to use Dash or Streamlit to build a real production-grade app… We have them go straight into Reflex."', + "Data Developer, World Bank", ), quote_card( - "Automate Analytics for Internal AI Tools.", - "Deploy Bank-Grade Internal Dashboards in Days, Not Months", - "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", - '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', - "FirstName LastName, Crédit Agricole CIB", + "Ship fintech-grade SaaS without a front-end team.", + "From YC prototype to fintech SaaS—with no React, Dash, or front-end hires", + "Bayesline’s founders built a full fintech risk analytics platform on Reflex—wrapping AG Grid, handling hundreds of thousands of instruments, and delivering a UI indistinguishable from a hand-coded React app. Reflex gave them ~4x faster development vs learning React and about 50% less code than their previous Dash implementation, while keeping everything in Python and avoiding the need to hire a dedicated front-end engineer.", + '"Using Reflex instead of Plotly Dash was like the difference between organized Legos and a plate of spaghetti."', + "Sebastian, Founder, Bayesline", ), - quote_card( - "Automate Analytics for Internal AI Tools.", - "Deploy Bank-Grade Internal Dashboards in Days, Not Months", - "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", - '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', - "FirstName LastName, Crédit Agricole CIB", - ), - quote_card( - "Automate Analytics for Internal AI Tools.", - "Deploy Bank-Grade Internal Dashboards in Days, Not Months", - "Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", - '"—It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', - "FirstName LastName, Crédit Agricole CIB", + rx.el.div( + quote_card( + "Automate Analytics for Internal AI Tools.", + "Deploy Bank-Grade Internal Dashboards in Days, Not Months", + "At Crédit Agricole CIB, Léo's R&D team turned a rough prototype into a production-grade dashboard tracking usage of a GPT-powered internal chatbot. What used to require weeks of front-end work now ships in a couple of days, inside their internal AWS environment.", + '"It\'s like comparing a bike to a supercar. (Comparing Dash to Reflex)"', + "Léo, Tech Lead, R&D, Crédit Agricole CIB", + ), + class_name="lg:col-span-2 lg:justify-self-center w-full lg:max-w-[42rem]", ), class_name="grid lg:grid-cols-2 grid-cols-1 gap-4 mx-auto w-full max-w-[84.5rem] relative overflow-hidden", ) diff --git a/pcweb/pages/use_cases/finance/views/stats.py b/pcweb/pages/use_cases/finance/views/stats.py index 788669deb7..dd2488113c 100644 --- a/pcweb/pages/use_cases/finance/views/stats.py +++ b/pcweb/pages/use_cases/finance/views/stats.py @@ -10,14 +10,9 @@ def stats() -> rx.Component: "Vs. legacy front-end stacks (Crédit Agricole CIB)", "10x", ), - stat_card( - "Quant Researchers", - "Building dashboards in Python (Man Group)", - "50+", - ), stat_card( "Legal Professionals", - "Using AI tools replacing Tableau (World Bank)", + "Using AI tools replacing Streamlit (World Bank)", "100+", ), stat_card( @@ -25,5 +20,5 @@ def stats() -> rx.Component: "Vs. Dash/React for fintech analytics (Bayesline)", "4x", ), - class_name="grid lg:grid-cols-4 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden border-t lg:divide-x divide-slate-3 max-lg:divide-y", + class_name="grid lg:grid-cols-3 grid-cols-1 mx-auto w-full max-w-[64.19rem] lg:border-x border-slate-3 relative overflow-hidden border-t lg:divide-x divide-slate-3 max-lg:divide-y", ) From 55cbe029dfa820aa8f900bf5f4877ebd6b6e557d Mon Sep 17 00:00:00 2001 From: Tom Gotsman Date: Tue, 16 Dec 2025 14:53:09 -0800 Subject: [PATCH 10/10] updates to healthcare pages --- pcweb/pages/use_cases/healthcare/views/faq.py | 4 ++-- pcweb/pages/use_cases/healthcare/views/features_2.py | 2 +- pcweb/pages/use_cases/healthcare/views/hero.py | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pcweb/pages/use_cases/healthcare/views/faq.py b/pcweb/pages/use_cases/healthcare/views/faq.py index eb532730c1..b77f8bb7cf 100644 --- a/pcweb/pages/use_cases/healthcare/views/faq.py +++ b/pcweb/pages/use_cases/healthcare/views/faq.py @@ -8,11 +8,11 @@ def faq() -> rx.Component: faq_items=[ ( "Is Reflex HIPAA-compliant?", - "Yes, Reflex apps can be deployed in fully self-hosted, HIPAA-compliant environments with PHI remaining entirely under your control.", + "Yes, both the Reflex Builder and the Reflex apps can be deployed in fully self-hosted, HIPAA-compliant environments with PHI remaining entirely under your control.", ), ( "Do I need frontend experience?", - "No. Reflex handles frontend automatically. You type Prompts or write Python; Reflex generates the UI.", + "No. Reflex handles frontend automatically. You type Prompts or write Python; Reflex generates the UI and the backend together.", ), ( "Can non-developers use the AI builder?", diff --git a/pcweb/pages/use_cases/healthcare/views/features_2.py b/pcweb/pages/use_cases/healthcare/views/features_2.py index 071f8b7355..e80f275d8a 100644 --- a/pcweb/pages/use_cases/healthcare/views/features_2.py +++ b/pcweb/pages/use_cases/healthcare/views/features_2.py @@ -20,7 +20,7 @@ def features_2() -> rx.Component: feature_card( "ZapIcon", "10x Faster Than Traditional Development", - "Move from idea to deployed app in hours, not months", + "Move from idea to deployed app in days, not months", "Reflex handles frontend, backend, state management, and deployment so your team can focus on patient outcomes and operational efficiency. Build production-grade healthcare apps without leaving Python or waiting on front-end teams.", ), feature_card( diff --git a/pcweb/pages/use_cases/healthcare/views/hero.py b/pcweb/pages/use_cases/healthcare/views/hero.py index a56f3e2b3e..1ecda5c395 100644 --- a/pcweb/pages/use_cases/healthcare/views/hero.py +++ b/pcweb/pages/use_cases/healthcare/views/hero.py @@ -24,7 +24,10 @@ def hero() -> rx.Component: "ShieldEnergyIcon", "Build HIPAA-compliant internal tools and patient data apps", ), - ("DashboardSpeed01Icon", "Develop up to 10x faster in pure Python"), + ( + "DashboardSpeed01Icon", + "Deliver production-ready tools in days, not months", + ), ("PythonIcon", "Go in Python from prototype to production"), ( "BrowserIcon",