Skip to content
This repository was archived by the owner on Apr 28, 2026. It is now read-only.

Commit d828a1f

Browse files
committed
updates
1 parent a835a0a commit d828a1f

14 files changed

Lines changed: 374 additions & 585 deletions

File tree

case-studies/ansa.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
---
22
company: Ansa
33
h1: "How Ansa Uses Reflex for AI-Powered Workflow Automation"
4+
card_header: "How Ansa saved 100 hours of manual work a month with Reflex"
5+
card_description: "See how Ansa automated their fintech workflows with Reflex, eliminating 100 hours of repetitive manual work per month and accelerating their operations."
46
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."
57
domain: "https://www.ansa.co"
68
founded: "New York, 2021"
@@ -144,7 +146,8 @@ Finally, when their team has a short list of companies that fit within an invest
144146
```md quote
145147
- name: Ryan
146148
- role: Investor and Head of Data
147-
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.
149+
- variant: medium
150+
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.
148151
```
149152

150153
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.

case-studies/autodesk.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
22
company: Autodesk
3+
card_header: "How Autodesk saved 25% of their development time"
4+
card_description: "Learn how Autodesk leveraged Reflex to streamline their internal tools development, cutting build time by 25% while maintaining enterprise-grade reliability."
35
description: "Streamlining Complex Workflows: Why Autodesk Chose Reflex Over Streamlit for Scalable, Python-Based Solutions"
46
domain: "https://autodesk.com"
57
founded: "San Francisco, 1982"
@@ -130,6 +132,7 @@ The team was able to:
130132
```md quote
131133
- name: Paolo
132134
- role: Principal Implementation Consultant
135+
- variant: medium
133136
I am able to wear all the caps at once: Solution Architecture, UI/UX, front-end and back-end.
134137
```
135138

@@ -183,5 +186,6 @@ Paolo and his team have now worked on three other projects for different custome
183186
```md quote
184187
- name: Paolo
185188
- role: Principal Implementation Consultant
189+
- variant: medium
186190
Everything I was able to accomplish was because of the framework and unparalleled support and promptness of the Reflex team.
187191
```

case-studies/bayesline.md

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
22
company: Bayesline
3+
card_header: "Why Bayesline chose Reflex over Plotly Dash"
4+
card_description: "Discover how Bayesline built a robust Python web application aimed at creating scalable risk models and data visualizations."
35
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."
46
domain: "https://bayesline.com/"
57
founded: "New York, 2024"
@@ -70,25 +72,30 @@ Quantitative Analysts (Quants), like Sebastian, are usually proficient in data-o
7072
Quants want to spend their time building models, proving out their ideas, and not worrying about the UI.
7173

7274
```md quote
73-
- name: Sebastian
74-
- role: Cofounder
75+
- name: Sebastian Janisch
76+
- role: Cofounder, Bayesline
77+
- image: sebastian.webp
7578
The UI is the necessary evil, that is not our bread and butter.
7679
```
7780

7881
They used to build prototypes with Dash and eventually hand them to a fully-fledged engineering team.
7982
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`).
8083

8184
```md quote
82-
- name: Sebastian
83-
- role: Cofounder
85+
- name: Sebastian Janisch
86+
- role: Cofounder, Bayesline
87+
- image: sebastian.webp
88+
- variant: medium
8489
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.
8590
```
8691

8792
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.
8893

8994
```md quote
90-
- name: Sebastian
91-
- role: Cofounder
95+
- name: Sebastian Janisch
96+
- role: Cofounder, Bayesline
97+
- image: sebastian.webp
98+
- variant: medium
9299
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.
93100
```
94101

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

98105
```md quote
99106
- name: Sebastian
100-
- role: Cofounder
107+
- role: Cofounder, Bayesline
108+
- image: sebastian.webp
109+
- variant: medium
101110
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.
102111
```
103112

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

108117
```md quote
109-
- name: Sebastian
110-
- role: Cofounder
118+
- name: Sebastian Janisch
119+
- role: Cofounder, Bayesline
120+
- image: sebastian.webp
121+
- variant: medium
111122
We wanted to build a frontend that would be as indistinguishable as possible from one built by professional frontend developers.
112123
```
113124

114125
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.
115126

116127
```md quote
117-
- name: Sebastian
118-
- role: Cofounder
128+
- name: Sebastian Janisch
129+
- role: Cofounder, Bayesline
130+
- image: sebastian.webp
131+
- variant: medium
119132
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.
120133
```
121134

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

130143
```md quote
131-
- name: Sebastian
132-
- role: Cofounder
144+
- name: Sebastian Janisch
145+
- role: Cofounder, Bayesline
146+
- image: sebastian.webp
147+
- variant: medium
133148
Turns out I don’t see right now, as it stands at least, reasons to migrate from Reflex to somewhere else.
134149
```
135150

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

145160
```md quote
146-
- name: Misha and Sebastian
147-
- role: Cofounders
161+
- name: Misha Van Beek
162+
- role: Cofounder, Bayesline
163+
- image: misha.webp
164+
- variant: big
148165
Reflex definitely saved us from needing to hire a frontend engineer and sped us up by 4x relative to learning React
149166
```
150167

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

153170
```md quote
154-
- name: Sebastian
155-
- role: Cofounder
171+
- name: Sebastian Janisch
172+
- role: Cofounder, Bayesline
173+
- image: sebastian.webp
174+
- variant: big
156175
50% less code than the same Dash app and easier to read / write / maintain code compared to Dash
157176
```
158177

159178
* Maintain expensive, fragile, and inevitably slow Dash apps
160179

161180
```md quote
162-
- name: Misha
163-
- role: Cofounder
181+
- name: Misha Van Beek
182+
- role: Cofounder, Bayesline
183+
- image: misha.webp
184+
- variant: big
164185
Using Reflex instead of Plotly Dash was like the difference between organized Legos and a plate of spaghetti
165186
```

case-studies/sellerx.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
22
company: SellerX
3+
card_header: "Why SellerX chose Reflex over Streamlit"
4+
card_description: "Find out why SellerX migrated from Streamlit to Reflex to power their e-commerce analytics platform with greater flexibility and performance."
35
description: "Why SellerX chose Reflex over Streamlit for their data processing pipeline. Building scalable e-commerce analytics and internal tools with Python."
46
domain: "https://sellerx.com"
57
founded: "Berlin, 2020"
@@ -141,6 +143,7 @@ The app that Mike and his team built with Reflex has been a huge success. It is
141143
```md quote
142144
- name: Mike
143145
- role: Head of AI
146+
- variant: medium
144147
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.
145148
```
146149

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

pcweb/flexdown.py

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import flexdown
22
import reflex as rx
3+
import reflex_ui as ui
34

5+
from pcweb.constants import REFLEX_ASSETS_CDN
46
from pcweb.styles.colors import c_color
57
from pcweb.styles.fonts import base, code
68
from pcweb.templates.docpage import (
@@ -510,31 +512,123 @@ class QuoteBlock(flexdown.blocks.MarkdownBlock):
510512

511513
include_indicators = True
512514

513-
def render(self, env) -> rx.Component:
515+
def _parse(self, env) -> dict[str, str]:
514516
lines = self.get_lines(env)
515517
quote_content = []
516-
name = ""
517-
role = ""
518+
data = {
519+
"name": "",
520+
"role": "",
521+
"image": "",
522+
"variant": "small",
523+
}
524+
518525
for line in lines[1:-1]: # Skip the first and last lines (indicators)
519526
if line.startswith("- name:"):
520-
name = line.split(":", 1)[1].strip()
527+
data["name"] = line.split(":", 1)[1].strip()
521528
elif line.startswith("- role:"):
522-
role = line.split(":", 1)[1].strip()
529+
data["role"] = line.split(":", 1)[1].strip()
530+
elif line.startswith("- image:"):
531+
data["image"] = line.split(":", 1)[1].strip()
532+
elif line.startswith("- variant:"):
533+
data["variant"] = line.split(":", 1)[1].strip().lower()
523534
else:
524535
quote_content.append(line)
525536

526-
quote_text = "\n".join(quote_content).strip()
537+
data["quote_text"] = "\n".join(quote_content).strip()
538+
return data
527539

528-
return rx.box(
529-
rx.text(f'"{quote_text}"', class_name="text-slate-11 font-base italic"),
530-
rx.box(
531-
rx.text(name, class_name="text-slate-11 font-base"),
532-
rx.text(role, class_name="text-slate-10 font-base"),
533-
class_name="flex flex-col gap-0.5",
540+
def _author(self, name: str, role: str, class_name: str = "") -> rx.Component:
541+
return rx.el.div(
542+
rx.el.span(
543+
name,
544+
class_name="text-xs font-mono uppercase font-[415] text-m-slate-12 dark:text-m-slate-3",
545+
),
546+
rx.el.span(
547+
role,
548+
class_name="text-xs font-mono font-[415] text-m-slate-7 dark:text-m-slate-6 uppercase",
549+
),
550+
class_name=ui.cn("flex flex-col gap-0.5", class_name),
551+
)
552+
553+
def _avatar(
554+
self, name: str, image: str, class_name: str = ""
555+
) -> rx.Component | None:
556+
if not image:
557+
return None
558+
avatar_class = ui.cn("rounded-full object-cover aspect-square", class_name)
559+
return rx.image(
560+
src=f"{REFLEX_ASSETS_CDN}case_studies/people/{image}",
561+
alt=f"{name} profile picture",
562+
class_name=avatar_class,
563+
)
564+
565+
def _render_medium(self, data: dict[str, str]) -> rx.Component:
566+
return rx.el.div(
567+
rx.el.div(
568+
self._avatar(data["name"], data["image"], class_name="size-6"),
569+
class_name="p-4 shrink-0 lg:border-r border-m-slate-6 dark:border-m-slate-7 border-dashed max-lg:border-b",
570+
),
571+
rx.el.span(
572+
f'"{data["quote_text"]}"',
573+
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",
574+
),
575+
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",
576+
)
577+
578+
def _render_small(self, data: dict[str, str]) -> rx.Component:
579+
return rx.el.div(
580+
rx.el.span(
581+
f'"{data["quote_text"]}"',
582+
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",
583+
),
584+
rx.el.div(
585+
rx.el.div(
586+
self._author(data["name"], data["role"]),
587+
class_name="text-end text-nowrap",
588+
),
589+
self._avatar(data["name"], data["image"], class_name="size-14"),
590+
class_name="flex flex-row gap-6 items-center p-6 shrink-0",
534591
),
535-
class_name="flex flex-col gap-4 border-l-[3px] border-slate-4 pl-6 mt-2 mb-6",
592+
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",
536593
)
537594

595+
def _render_big(self, data: dict[str, str]) -> rx.Component:
596+
return rx.el.div(
597+
rx.el.div(
598+
rx.el.span(
599+
f"{data['quote_text']}",
600+
class_name="text-m-slate-12 dark:text-m-slate-3 text-2xl font-[575]",
601+
),
602+
rx.el.div(
603+
self._avatar(data["name"], data["image"], class_name="size-6"),
604+
self._author(
605+
data["name"],
606+
data["role"],
607+
class_name="flex-row gap-3.5 items-center",
608+
),
609+
class_name="flex flex-row gap-3.5 items-center",
610+
),
611+
class_name="flex flex-col gap-12 pr-[12.5rem] relative z-10",
612+
),
613+
rx.image(
614+
src=f"{REFLEX_ASSETS_CDN}common/{rx.color_mode_cond('light', 'dark')}/quote_squares.svg",
615+
loading="lazy",
616+
alt="Quote icon",
617+
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",
618+
),
619+
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",
620+
)
621+
622+
def render(self, env) -> rx.Component:
623+
data = self._parse(env)
624+
renderers = {
625+
"small": self._render_small,
626+
"medium": self._render_medium,
627+
"big": self._render_big,
628+
}
629+
renderer = renderers.get(data["variant"], self._render_small)
630+
return renderer(data)
631+
538632

539633
class TabsBlock(flexdown.blocks.Block):
540634
"""A block that displays content in tabs."""
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
from pcweb.pages.customers.views.book_a_demo import book_a_demo
22
from pcweb.pages.customers.views.companies import companies
3-
from pcweb.pages.customers.views.customer_cards import customer_cards
4-
from pcweb.pages.customers.views.customers_list import customers_list
53
from pcweb.pages.customers.views.hero import hero
64
from pcweb.pages.customers.views.stats import stats
75

86
__all__ = [
97
"book_a_demo",
108
"companies",
11-
"customer_cards",
12-
"customers_list",
139
"hero",
1410
"stats",
1511
]

0 commit comments

Comments
 (0)