Skip to content
This repository was archived by the owner on Apr 28, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion case-studies/ansa.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
company: Ansa
h1: "How Ansa Uses Reflex for AI-Powered Workflow Automation"
card_header: "How Ansa saved 100 hours of manual work a month with Reflex"
card_description: "See how Ansa automated their fintech workflows with Reflex, eliminating 100 hours of repetitive manual work per month and accelerating their operations."
description: "Why Ansa chose Reflex over no-code and low-code frameworks for their workflow automations. Full Python control for AI-powered business process automation."
domain: "https://www.ansa.co"
founded: "New York, 2021"
Expand Down Expand Up @@ -144,7 +146,8 @@ Finally, when their team has a short list of companies that fit within an invest
```md quote
- name: Ryan
- role: Investor and Head of Data
Let’s say we have 30 companies that we want to email. How can you efficiently send a custom note to each of these companies and track it properly? We launch a script, that runs through a Reflex background event, that'll go through each company, check the CRM ownership, fill out relevant fields and find the best person to reach out to. A lot of times, especially with early stage companies, data is missing or partially complete. So this workflow will leverage LLMs throughout the process to handle fuzzy matching and make contextual decisions, as well as proactively summarize company content, news, and relevant Ansa content to help support the email writing. Before we would do this all manually, now with this new workflow in Reflex, we've taken what was once 30+ clicks across 5 different apps and made it 5x faster with 2 clicks across 2 apps.
- variant: medium
Let’s say we have 30 companies that we want to email. How can you efficiently send a custom note to each of these companies and track it properly? We launch a script, that runs through a Reflex background event, that’ll go through each company, check the CRM ownership, fill out relevant fields and find the best person to reach out to. A lot of times, especially with early stage companies, data is missing or partially complete. So this workflow will leverage LLMs throughout the process to handle fuzzy matching and make contextual decisions, as well as proactively summarize company content, news, and relevant Ansa content to help support the email writing. Before we would do this all manually, now with this new workflow in Reflex, we’ve taken what was once 30+ clicks across 5 different apps and made it 5x faster with 2 clicks across 2 apps.
```

All these different workflows are now built into a single Reflex app. It makes it extremely easy for anyone on the team to run any of these workflows and leverage LLM-powered automation with a few clicks.
Expand Down
4 changes: 4 additions & 0 deletions case-studies/autodesk.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
company: Autodesk
card_header: "How Autodesk saved 25% of their development time"
card_description: "Learn how Autodesk leveraged Reflex to streamline their internal tools development, cutting build time by 25% while maintaining enterprise-grade reliability."
description: "Streamlining Complex Workflows: Why Autodesk Chose Reflex Over Streamlit for Scalable, Python-Based Solutions"
domain: "https://autodesk.com"
founded: "San Francisco, 1982"
Expand Down Expand Up @@ -130,6 +132,7 @@ The team was able to:
```md quote
- name: Paolo
- role: Principal Implementation Consultant
- variant: medium
I am able to wear all the caps at once: Solution Architecture, UI/UX, front-end and back-end.
```

Expand Down Expand Up @@ -183,5 +186,6 @@ Paolo and his team have now worked on three other projects for different custome
```md quote
- name: Paolo
- role: Principal Implementation Consultant
- variant: medium
Everything I was able to accomplish was because of the framework and unparalleled support and promptness of the Reflex team.
```
59 changes: 40 additions & 19 deletions case-studies/bayesline.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
company: Bayesline
card_header: "Why Bayesline chose Reflex over Plotly Dash"
card_description: "Discover how Bayesline built a robust Python web application aimed at creating scalable risk models and data visualizations."
description: "Why Bayesline chose Reflex over Plotly Dash for their production-grade Python web app. Learn how they built scalable risk models and data visualizations."
domain: "https://bayesline.com/"
founded: "New York, 2024"
Expand Down Expand Up @@ -70,25 +72,30 @@ Quantitative Analysts (Quants), like Sebastian, are usually proficient in data-o
Quants want to spend their time building models, proving out their ideas, and not worrying about the UI.

```md quote
- name: Sebastian
- role: Cofounder
- name: Sebastian Janisch
- role: Cofounder, Bayesline
- image: sebastian.webp
The UI is the necessary evil, that is not our bread and butter.
```

They used to build prototypes with Dash and eventually hand them to a fully-fledged engineering team.
It would take months before their app ideas could be used across an organization; with Reflex you can both build and share apps in a matter of hours (`reflex deploy`).

```md quote
- name: Sebastian
- role: Cofounder
- name: Sebastian Janisch
- role: Cofounder, Bayesline
- image: sebastian.webp
- variant: medium
You wouldn’t want to use Dash to build a production-grade application. It’s a prototyping tool. Usually, a UX and engineering team would re-implement everything from scratch. It will take six months for anyone to get hands on it, but we want this now.
```

When embarking on building Bayesline, Sebastian and his co-founder wanted an open-source framework that would enable them to build a fully-fledged web app in pure Python, the language and ecosystem they were already familiar with.

```md quote
- name: Sebastian
- role: Cofounder
- name: Sebastian Janisch
- role: Cofounder, Bayesline
- image: sebastian.webp
- variant: medium
So we basically need the tool that gets us to the finish line fastest without having to learn (a new framework) and without a super steep learning curve.
```

Expand All @@ -97,7 +104,9 @@ As their app grew, it eventually became slow and difficult to maintain.

```md quote
- name: Sebastian
- role: Cofounder
- role: Cofounder, Bayesline
- image: sebastian.webp
- variant: medium
The app was just getting painfully slow. Dash loads the entire application, the entire dom of every single page. As the application gets bigger, the performance will just go down.
```

Expand All @@ -106,16 +115,20 @@ The app was just getting painfully slow. Dash loads the entire application, the
Bayesline switched from Dash to Reflex because they could build both a production-grade and an aesthetically pleasing web app quickly–without JavaScript experience.

```md quote
- name: Sebastian
- role: Cofounder
- name: Sebastian Janisch
- role: Cofounder, Bayesline
- image: sebastian.webp
- variant: medium
We wanted to build a frontend that would be as indistinguishable as possible from one built by professional frontend developers.
```

Complicated Dash apps not only eventually hit performance limits but are also challenging to maintain since there isn’t first-class support for object-oriented programming (OOP) design patterns.

```md quote
- name: Sebastian
- role: Cofounder
- name: Sebastian Janisch
- role: Cofounder, Bayesline
- image: sebastian.webp
- variant: medium
When we started looking at the (Dash) code, it just got to this point where you’re scared of it because there is no object-oriented notion; the code just turns into an enormous mess because you just have this huge collection of functions.
```

Expand All @@ -128,8 +141,10 @@ Sebastian and the team originally started building with Reflex to create a minim
They quickly learned that Reflex was already ready to build production grade web apps.

```md quote
- name: Sebastian
- role: Cofounder
- name: Sebastian Janisch
- role: Cofounder, Bayesline
- image: sebastian.webp
- variant: medium
Turns out I don’t see right now, as it stands at least, reasons to migrate from Reflex to somewhere else.
```

Expand All @@ -143,23 +158,29 @@ Sebastian and his small team use Reflex to build a production-grade web app pure
* Learn frontend technologies: React (JavaScript), NodeJS, TailwindCSS

```md quote
- name: Misha and Sebastian
- role: Cofounders
- name: Misha Van Beek
- role: Cofounder, Bayesline
- image: misha.webp
- variant: big
Reflex definitely saved us from needing to hire a frontend engineer and sped us up by 4x relative to learning React
```

* Write boilerplate to stitch together their frontend and backend (including database management)

```md quote
- name: Sebastian
- role: Cofounder
- name: Sebastian Janisch
- role: Cofounder, Bayesline
- image: sebastian.webp
- variant: big
50% less code than the same Dash app and easier to read / write / maintain code compared to Dash
```

* Maintain expensive, fragile, and inevitably slow Dash apps

```md quote
- name: Misha
- role: Cofounder
- name: Misha Van Beek
- role: Cofounder, Bayesline
- image: misha.webp
- variant: big
Using Reflex instead of Plotly Dash was like the difference between organized Legos and a plate of spaghetti
```
4 changes: 4 additions & 0 deletions case-studies/sellerx.md
Comment thread
carlosabadia marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
company: SellerX
card_header: "Why SellerX chose Reflex over Streamlit"
card_description: "Find out why SellerX migrated from Streamlit to Reflex to power their e-commerce analytics platform with greater flexibility and performance."
description: "Why SellerX chose Reflex over Streamlit for their data processing pipeline. Building scalable e-commerce analytics and internal tools with Python."
domain: "https://sellerx.com"
founded: "Berlin, 2020"
Expand Down Expand Up @@ -141,6 +143,7 @@ The app that Mike and his team built with Reflex has been a huge success. It is
```md quote
- name: Mike
- role: Head of AI
- variant: medium
Comment thread
carlosabadia marked this conversation as resolved.
A team of 6 non-technical employees use the app to make decisions based on Amazon information. It is allowing this team to be significantly more efficient and structured in the way they work and they are very happy with the improvements in speed. This team is now able to review 5x more Amazon data than their previous approach.
```

Expand All @@ -156,6 +159,7 @@ We are moving significantly faster, which has been very very useful. To have a q
```md quote
- name: Mike
- role: Head of AI
- variant: medium
With Reflex it is ten times faster than developing with React and FastApi.
```

Expand Down
120 changes: 107 additions & 13 deletions pcweb/flexdown.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import flexdown
import reflex as rx
import reflex_ui as ui

from pcweb.constants import REFLEX_ASSETS_CDN
from pcweb.styles.colors import c_color
from pcweb.styles.fonts import base, code
from pcweb.templates.docpage import (
Expand Down Expand Up @@ -510,31 +512,123 @@ class QuoteBlock(flexdown.blocks.MarkdownBlock):

include_indicators = True

def render(self, env) -> rx.Component:
def _parse(self, env) -> dict[str, str]:
lines = self.get_lines(env)
quote_content = []
name = ""
role = ""
data = {
"name": "",
"role": "",
"image": "",
"variant": "small",
}

for line in lines[1:-1]: # Skip the first and last lines (indicators)
if line.startswith("- name:"):
name = line.split(":", 1)[1].strip()
data["name"] = line.split(":", 1)[1].strip()
elif line.startswith("- role:"):
role = line.split(":", 1)[1].strip()
data["role"] = line.split(":", 1)[1].strip()
elif line.startswith("- image:"):
data["image"] = line.split(":", 1)[1].strip()
elif line.startswith("- variant:"):
data["variant"] = line.split(":", 1)[1].strip().lower()
else:
quote_content.append(line)

quote_text = "\n".join(quote_content).strip()
data["quote_text"] = "\n".join(quote_content).strip()
return data

return rx.box(
rx.text(f'"{quote_text}"', class_name="text-slate-11 font-base italic"),
rx.box(
rx.text(name, class_name="text-slate-11 font-base"),
rx.text(role, class_name="text-slate-10 font-base"),
class_name="flex flex-col gap-0.5",
def _author(self, name: str, role: str, class_name: str = "") -> rx.Component:
return rx.el.div(
rx.el.span(
name,
class_name="text-xs font-mono uppercase font-[415] text-m-slate-12 dark:text-m-slate-3",
),
rx.el.span(
role,
class_name="text-xs font-mono font-[415] text-m-slate-7 dark:text-m-slate-6 uppercase",
),
class_name=ui.cn("flex flex-col gap-0.5", class_name),
)

def _avatar(
self, name: str, image: str, class_name: str = ""
) -> rx.Component | None:
if not image:
return None
avatar_class = ui.cn("rounded-full object-cover aspect-square", class_name)
return rx.image(
src=f"{REFLEX_ASSETS_CDN}case_studies/people/{image}",
alt=f"{name} profile picture",
class_name=avatar_class,
)

def _render_medium(self, data: dict[str, str]) -> rx.Component:
return rx.el.div(
rx.el.div(
self._avatar(data["name"], data["image"], class_name="size-6"),
class_name="p-4 shrink-0 lg:border-r border-m-slate-6 dark:border-m-slate-7 border-dashed max-lg:border-b",
),
rx.el.span(
f'"{data["quote_text"]}"',
class_name="text-m-slate-12 dark:text-m-slate-3 text-base font-[575] p-4 bg-white-1 dark:bg-m-slate-11",
),
class_name="flex lg:flex-row flex-col border border-dashed border-m-slate-6 dark:border-m-slate-7 mt-2 mb-6 rounded-lg overflow-hidden",
)

def _render_small(self, data: dict[str, str]) -> rx.Component:
return rx.el.div(
rx.el.span(
f'"{data["quote_text"]}"',
class_name="text-m-slate-12 dark:text-m-slate-3 text-lg font-[575] p-6 lg:border-r border-m-slate-6 dark:border-m-slate-7 border-dashed max-lg:border-b bg-white-1 dark:bg-m-slate-11",
),
rx.el.div(
rx.el.div(
self._author(data["name"], data["role"]),
class_name="text-end text-nowrap",
),
self._avatar(data["name"], data["image"], class_name="size-14"),
class_name="flex flex-row gap-6 items-center p-6 shrink-0",
),
class_name="flex flex-col gap-4 border-l-[3px] border-slate-4 pl-6 mt-2 mb-6",
class_name="flex lg:flex-row flex-col border border-dashed border-m-slate-6 dark:border-m-slate-7 mt-2 mb-6 rounded-lg overflow-hidden",
)

def _render_big(self, data: dict[str, str]) -> rx.Component:
return rx.el.div(
rx.el.div(
rx.el.span(
f"{data['quote_text']}",
class_name="text-m-slate-12 dark:text-m-slate-3 text-2xl font-[575]",
),
rx.el.div(
self._avatar(data["name"], data["image"], class_name="size-6"),
self._author(
data["name"],
data["role"],
class_name="flex-row gap-3.5 items-center",
),
class_name="flex flex-row gap-3.5 items-center",
),
class_name="flex flex-col gap-12 pr-[12.5rem] relative z-10",
),
rx.image(
src=f"{REFLEX_ASSETS_CDN}common/{rx.color_mode_cond('light', 'dark')}/quote_squares.svg",
loading="lazy",
alt="Quote icon",
class_name="absolute right-0 inset-y-0 h-[calc(100%)] min-h-full w-auto origin-right pointer-events-none object-contain object-right",
),
class_name="flex flex-col dark:border bg-white-1 dark:bg-m-slate-11 dark:border-m-slate-9 mt-2 mb-6 overflow-hidden shadow-[0_0_0_1px_rgba(0,0,0,0.12)_inset,0_6px_12px_0_rgba(0,0,0,0.06),0_1px_1px_0_rgba(0,0,0,0.01),0_4px_6px_0_rgba(0,0,0,0.02)] rounded-xl py-8 px-8 relative",
)

def render(self, env) -> rx.Component:
data = self._parse(env)
renderers = {
"small": self._render_small,
"medium": self._render_medium,
"big": self._render_big,
}
renderer = renderers.get(data["variant"], self._render_small)
return renderer(data)


class TabsBlock(flexdown.blocks.Block):
"""A block that displays content in tabs."""
Expand Down
2 changes: 1 addition & 1 deletion pcweb/pages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from .blog import blog_routes
from .booked import booked as booked
from .check_your_email_demo import page_thank_you as page_thank_you
from .customers import customers as customers
from .customers.data.customers import customers_routes
from .customers.landing import customers as customers
from .databricks.databricks import databricks_page as databricks_page
from .demo.book_demo import book_demo as book_demo
from .docs import doc_routes
Expand Down
21 changes: 21 additions & 0 deletions pcweb/pages/customers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import reflex as rx

from pcweb.pages.customers.views import book_a_demo, companies, hero
from pcweb.templates.marketing_page import marketing_page


@marketing_page(
path="/customers",
title="Reflex Customer Stories - Case Studies",
description="Case studies: Bayesline, SellerX, and Ansa use Reflex to build production Python web apps. Real success stories.",
)
def customers() -> rx.Component:
return rx.el.div(
hero(),
rx.el.hr(
class_name="w-full border-t border-m-slate-4 dark:border-m-slate-9",
),
companies(),
book_a_demo(),
class_name="flex flex-col w-full justify-center items-center",
)
Loading
Loading