Skip to content

Commit 9d25b05

Browse files
LineIndentAlek99adhami3310devin-ai-integration[bot]carlosabadia
authored
ENG-7371: bring back pricing & change demo url (includes ENG-7392) (#1585)
* bring back pricing & change demo url * remove duplicate * update pricing cards * change credits -> msgs * rebase on main * Update link * refresh lemcal on mount * clean whitelist * Update to use lemcal component from reflex-ui - Replace pcweb.components.lemcal imports with reflex_ui.blocks.lemcal - Update pcweb.py to use get_lemcal_script() instead of hardcoded script tag - Update navbar.py to use lemcal_calendar from reflex-ui - Remove old pcweb/components/lemcal.py file - Maintain same functionality while using reusable component Co-Authored-By: Alek <[email protected]> * use reflex ui lemcal component * bump * bump reflex ui * add border to pricing cards * replace dialog with lemcal link * free tier update --------- Co-authored-by: Alek Petuskey <[email protected]> Co-authored-by: Khaleel Al-Adhami <[email protected]> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Alek <[email protected]> Co-authored-by: carlosabadia <[email protected]> Co-authored-by: Carlos <[email protected]>
1 parent 6ac4492 commit 9d25b05

File tree

14 files changed

+728
-436
lines changed

14 files changed

+728
-436
lines changed

pcweb/components/docpage/navbar/navbar.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
from pcweb.pages.framework.framework import framework
1414
from pcweb.pages.hosting.hosting import hosting_landing
1515
from pcweb.pages.use_cases.use_cases import use_cases_page
16-
16+
from reflex_ui.blocks.lemcal import lemcal_dialog, LEMCAL_DEMO_URL
17+
import reflex_ui as ui
1718
from ...link_button import resources_button
1819
from ..sidebar import SidebarState
1920
from .buttons.discord import discord
@@ -443,7 +444,7 @@ def new_component_section() -> rx.Component:
443444
"hidden lg:flex",
444445
"hidden",
445446
)
446-
)
447+
),
447448
),
448449
class_name="flex flex-row gap-x-0 items-center",
449450
),
@@ -534,14 +535,13 @@ def new_component_section() -> rx.Component:
534535
class_name="desktop-only",
535536
),
536537
nav_menu.item(
537-
rx.link(
538-
button(
538+
ui.link(
539+
render_=button(
539540
"Book a Demo",
540541
class_name="!h-8 !font-small-smbold !rounded-[0.625rem] whitespace-nowrap",
541542
),
542-
underline="none",
543-
is_external=True,
544-
href="/pricing",
543+
target="_blank",
544+
to=LEMCAL_DEMO_URL,
545545
),
546546
class_name="xl:flex hidden",
547547
),

pcweb/constants.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
REFLEX_DEV_WEB_LANDING_FORM_SALES_CALL_WEBHOOK_URL: str = (
66
"https://hooks.zapier.com/hooks/catch/20661176/2s1nxp9/"
77
)
8+
REFLEX_DEV_WEB_LANDING_FORM_URL_GET_DEMO: str = (
9+
"https://cal.com/forms/f87bd9b2-b339-4915-b4d4-0098e2db4394"
10+
)
811

912
REFLEX_DEV_WEB_NEWSLETTER_FORM_WEBHOOK_URL: str = "https://hkdk.events/t0qopjbznnp2fr"
1013
REFLEX_DEV_WEB_GENERAL_FORM_FEEDBACK_WEBHOOK_URL: str = os.environ.get(
@@ -40,7 +43,7 @@
4043
SPLINE_URL = "https://github.com/splinetool/react-spline"
4144
ENTERPRISE_DOCS_URL = "https://enterprise.reflex.dev"
4245
DATABRICKS_NOTION_URL = "https://reflex-dev.notion.site/reflex-x-databricks"
43-
DEMO_VIDEO_URL = "https://www.youtube.com/watch?v=s-kr8v7827g"
46+
DEMO_VIDEO_URL = "https://www.youtube.com/watch?v=lO-N_IRaWhQ"
4447

4548
# Install urls.
4649
BUN_URL = "https://bun.sh"

pcweb/pages/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from .page404 import page404 as page404
1919
from .pricing.pricing import pricing as pricing
2020
from .sales import sales as sales
21+
from .demo.book_demo import book_demo as book_demo
2122
from .booked import booked as booked
2223
from .to_be_booked import to_be_booked as to_be_booked
2324

pcweb/pages/demo/book_demo.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import reflex as rx
2+
from pcweb.pages.framework.index_colors import index_colors
3+
from pcweb.pages.framework.views.footer_index import footer_index
4+
from pcweb.meta.meta import meta_tags
5+
from pcweb.pages.demo.header import header
6+
from pcweb.templates.mainpage import mainpage
7+
from pcweb.components.icons.patterns import default_patterns
8+
9+
10+
@mainpage(path="/demo", title="Reflex · Book Demo", meta=meta_tags)
11+
def book_demo() -> rx.Component:
12+
"""Get the Book Demo landing page."""
13+
14+
return rx.el.main(
15+
rx.el.section(
16+
*default_patterns(),
17+
header(),
18+
class_name="overflow-hidden w-full relative mx-auto flex flex-col justify-center items-center max-w-[64.19rem]",
19+
),
20+
class_name="flex flex-col w-full max-w-[94.5rem] justify-center items-center mx-auto px-4 lg:px-5 relative overflow-hidden",
21+
)

pcweb/pages/demo/header.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import reflex as rx
2+
import reflex_ui as ui
3+
from reflex_ui.blocks.lemcal import lemcal_dialog, LEMCAL_DEMO_URL
4+
from pcweb.components.hosting_banner import HostingBannerState
5+
from pcweb.pages.framework.views.companies import pricing_page_companies
6+
7+
8+
def custom_quote_form() -> rx.Component:
9+
"""Custom quote form component with clean, maintainable structure."""
10+
return rx.box(
11+
rx.box(
12+
rx.el.h2(
13+
"Book a Demo",
14+
class_name="text-slate-12 text-4xl font-bold",
15+
),
16+
rx.el.p(
17+
"Enterprise-ready solutions designed for scale, compliance, and support. Contact us for a tailored quote based on your infrastructure and team size.",
18+
class_name="text-slate-11 text-md leading-relaxed font-medium text-center max-w-xl mx-auto",
19+
),
20+
ui.link(
21+
render_=rx.el.div(
22+
ui.button(
23+
"Contact Sales",
24+
class_name="font-semibold",
25+
size="lg",
26+
),
27+
class_name="p-3 border border-slate-3 rounded-[1.375rem] border-solid mt-2",
28+
),
29+
target="_blank",
30+
to=LEMCAL_DEMO_URL,
31+
),
32+
rx.box(
33+
rx.el.span(
34+
"Trusted by",
35+
class_name="text-slate-10 text-sm leading-relaxed font-medium text-center max-w-lg mx-auto mt-2",
36+
),
37+
pricing_page_companies(),
38+
class_name="flex flex-col items-center justify-center gap-4",
39+
),
40+
class_name="flex flex-col items-center justify-center gap-6",
41+
),
42+
id="demo-form",
43+
class_name="pb-12 sm:pb-20 px-4 sm:px-8 scroll-m-20 text-center",
44+
)
45+
46+
47+
def header() -> rx.Component:
48+
return rx.box(
49+
custom_quote_form(),
50+
class_name="flex flex-col gap-2 justify-center items-center max-w-[64.19rem] xl:border-x border-slate-4 w-full -mb-10 pb-16 "
51+
+ rx.cond(
52+
HostingBannerState.show_banner,
53+
"pt-[8rem] lg:pt-[11rem]",
54+
"pt-[8rem] lg:pt-[12rem]",
55+
),
56+
)

pcweb/pages/gallery/apps.py

Lines changed: 77 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,39 @@
22
import reflex as rx
33
import re
44
from pcweb.components.button import button, button_with_icon
5+
from reflex_ui.blocks.lemcal import lemcal_dialog, LEMCAL_DEMO_URL
56
from pcweb.components.code_card import gallery_app_card
67
from pcweb.components.icons import get_icon
78
from pcweb.constants import SCREENSHOT_BUCKET
89
from pcweb.flexdown import xd2 as xd
910
from pcweb.pages.gallery import gallery
1011
from pcweb.templates.gallery_app_page import gallery_app_page
1112
import copy
13+
import reflex_ui as ui
1214

1315
GALLERY_APP_SOURCES = [
1416
("templates/", "docs/getting-started/open-source-templates/"),
1517
("reflex_build_templates/", "templates/"),
1618
]
1719

20+
1821
def load_all_gallery_apps():
1922
"""Load markdown files from all supported paths and associate them with their base folder."""
2023
gallery_apps = {}
2124
for folder, _ in GALLERY_APP_SOURCES:
2225
paths = flexdown.utils.get_flexdown_files(folder)
2326
for path in reversed(sorted(paths)):
2427
document = flexdown.Document.from_file(path) # This has metadata
25-
document.metadata["title"] = document.metadata.get("title", "Untitled").replace("_", " ").title()
28+
document.metadata["title"] = (
29+
document.metadata.get("title", "Untitled").replace("_", " ").title()
30+
)
2631
clean_path = str(path).replace(".md", "/")
2732
gallery_apps[(clean_path, folder)] = document
2833
return gallery_apps
2934

3035

3136
gallery_apps_data = load_all_gallery_apps()
32-
gallery_apps_data_copy = {
33-
path: doc for (path, _), doc in gallery_apps_data.items()
34-
}
37+
gallery_apps_data_copy = {path: doc for (path, _), doc in gallery_apps_data.items()}
3538
gallery_apps_data_open_source = {
3639
(path, folder): doc
3740
for (path, folder), doc in load_all_gallery_apps().items()
@@ -55,7 +58,7 @@ def more_posts(current_post: dict) -> rx.Component:
5558
if current_index is None:
5659
selected_posts = app_items[-3:]
5760
else:
58-
other_posts = app_items[:current_index] + app_items[current_index + 1:]
61+
other_posts = app_items[:current_index] + app_items[current_index + 1 :]
5962
if len(other_posts) <= 3:
6063
selected_posts = other_posts
6164
elif current_index == 0:
@@ -64,9 +67,9 @@ def more_posts(current_post: dict) -> rx.Component:
6467
selected_posts = other_posts[-3:]
6568
else:
6669
if current_index < len(app_items) - 2:
67-
selected_posts = other_posts[current_index - 1: current_index + 2]
70+
selected_posts = other_posts[current_index - 1 : current_index + 2]
6871
else:
69-
selected_posts = other_posts[current_index - 2: current_index + 1]
72+
selected_posts = other_posts[current_index - 2 : current_index + 1]
7073

7174
for path, document in selected_posts:
7275
posts.append(gallery_app_card(app=document.metadata))
@@ -76,7 +79,9 @@ def more_posts(current_post: dict) -> rx.Component:
7679
rx.el.h2("More Templates", class_name="font-large text-slate-12"),
7780
rx.link(
7881
rx.box(
79-
rx.text("View All", class_name="font-small text-slate-9 text-nowrap"),
82+
rx.text(
83+
"View All", class_name="font-small text-slate-9 text-nowrap"
84+
),
8085
get_icon(icon="new_tab", class_name=""),
8186
class_name="flex items-center gap-1.5 border-slate-5 bg-slate-1 hover:bg-slate-3 shadow-small px-1.5 py-0.5 border rounded-md w-auto max-w-full text-slate-9 transition-bg cursor-pointer overflow-hidden border-solid",
8287
),
@@ -104,8 +109,8 @@ def page(document, is_reflex_template: bool) -> rx.Component:
104109
loading="lazy",
105110
class_name="w-full object-cover max-w-full aspect-[1500/938] border-y border-slate-3 border-solid",
106111
)
107-
if not is_reflex_template else
108-
rx.el.div(
112+
if not is_reflex_template
113+
else rx.el.div(
109114
rx.box(
110115
rx.el.h1(
111116
meta["title"].replace("_", " ").title(),
@@ -114,7 +119,7 @@ def page(document, is_reflex_template: bool) -> rx.Component:
114119
class_name="w-full self-start pl-4",
115120
),
116121
rx.el.iframe(
117-
src=meta['video'],
122+
src=meta["video"],
118123
class_name="w-full h-full xl:rounded-md shadow-small",
119124
id="iFrame",
120125
title="Reflex Build",
@@ -124,7 +129,11 @@ def page(document, is_reflex_template: bool) -> rx.Component:
124129
)
125130
)
126131

127-
back_route_origin = "/docs/getting-started/open-source-templates/" if not is_reflex_template else "/templates/"
132+
back_route_origin = (
133+
"/docs/getting-started/open-source-templates/"
134+
if not is_reflex_template
135+
else "/templates/"
136+
)
128137

129138
return rx.el.section(
130139
rx.el.article(
@@ -141,52 +150,61 @@ def page(document, is_reflex_template: bool) -> rx.Component:
141150
class_name="flex w-fit",
142151
href=back_route_origin,
143152
),
144-
rx.el.h1(meta["title"], class_name="font-x-large text-slate-12") if not is_reflex_template else rx.fragment(),
153+
(
154+
rx.el.h1(meta["title"], class_name="font-x-large text-slate-12")
155+
if not is_reflex_template
156+
else rx.fragment()
157+
),
145158
rx.el.h2(meta["description"], class_name="font-md text-slate-11"),
146159
class_name="flex flex-col gap-3 p-8",
147160
),
148161
rx.box(
149162
*(
150-
[rx.box(
151-
rx.link(
152-
button_with_icon(
153-
"Book a Demo",
154-
icon="new_tab",
155-
class_name="flex-row-reverse gap-2 !w-full",
156-
),
157-
is_external=True,
158-
href="/pricing",
159-
class_name="!w-full"
163+
[
164+
rx.box(
165+
ui.link(
166+
render_=button_with_icon(
167+
"Book a Demo",
168+
icon="new_tab",
169+
class_name="flex-row-reverse gap-2 !w-full",
160170
),
161-
class_name="flex justify-center items-center h-full !w-full",
162-
)] if is_reflex_template else
163-
(
164-
[rx.link(
165-
button_with_icon(
166-
"View Demo",
167-
icon="new_tab",
168-
class_name="!w-full flex-row-reverse gap-2",
171+
target="_blank",
172+
to=LEMCAL_DEMO_URL,
169173
),
170-
is_external=True,
171-
href=meta["demo"],
172-
)] if meta.get("demo") else []
174+
class_name="flex justify-center items-center h-full !w-full [&_button]:!w-full",
175+
)
176+
]
177+
),
178+
(
179+
rx.link(
180+
button("View Code", variant="muted", class_name="!w-full"),
181+
is_external=True,
182+
href=meta.get("source", "#"),
173183
)
184+
if not is_reflex_template
185+
else rx.fragment()
186+
),
187+
(
188+
rx.cond(
189+
"Reflex" in meta["author"],
190+
rx.box(
191+
rx.text(
192+
"Created by", class_name="text-slate-9 font-base"
193+
),
194+
get_icon(icon="badge_logo"),
195+
rx.text(
196+
meta["author"], class_name="text-slate-9 font-base"
197+
),
198+
class_name="flex flex-row items-center gap-1 self-end",
199+
),
200+
rx.text(
201+
f"by {meta['author']}",
202+
class_name="text-slate-9 font-base",
203+
),
204+
)
205+
if not is_reflex_template
206+
else rx.fragment()
174207
),
175-
rx.link(
176-
button("View Code", variant="muted", class_name="!w-full"),
177-
is_external=True,
178-
href=meta.get('source', "#"),
179-
) if not is_reflex_template else rx.fragment(),
180-
rx.cond(
181-
"Reflex" in meta["author"],
182-
rx.box(
183-
rx.text("Created by", class_name="text-slate-9 font-base"),
184-
get_icon(icon="badge_logo"),
185-
rx.text(meta["author"], class_name="text-slate-9 font-base"),
186-
class_name="flex flex-row items-center gap-1 self-end",
187-
),
188-
rx.text(f"by {meta['author']}", class_name="text-slate-9 font-base"),
189-
) if not is_reflex_template else rx.fragment(),
190208
class_name="p-8 flex flex-col gap-4",
191209
),
192210
class_name="grid grid-cols-1 lg:grid-cols-2 divide-y lg:divide-y-0 lg:divide-x divide-slate-3 border-b border-slate-3",
@@ -204,7 +222,11 @@ def page(document, is_reflex_template: bool) -> rx.Component:
204222
gallery_apps_routes = []
205223
for (path, source_folder), document in gallery_apps_data.items():
206224
is_reflex_template = source_folder.startswith("reflex_build_templates")
207-
base_url = "templates/" if is_reflex_template else "docs/getting-started/open-source-templates/"
225+
base_url = (
226+
"templates/"
227+
if is_reflex_template
228+
else "docs/getting-started/open-source-templates/"
229+
)
208230
slug = re.sub(r"[\s_]+", "-", document.metadata["title"]).lower()
209231
route = f"/{base_url}{slug}"
210232

@@ -221,6 +243,10 @@ def page(document, is_reflex_template: bool) -> rx.Component:
221243
image=document.metadata["image"],
222244
demo=document.metadata.get("demo"),
223245
meta=document.metadata.get("meta", []),
224-
)(lambda doc=document, is_reflex_template=is_reflex_template: page(doc, is_reflex_template))
246+
)(
247+
lambda doc=document, is_reflex_template=is_reflex_template: page(
248+
doc, is_reflex_template
249+
)
250+
)
225251

226252
gallery_apps_routes.append(comp)

pcweb/pages/landing/views/outcomes_section.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def outcomes_showcase() -> rx.Component:
148148
),
149149
underline="none",
150150
is_external=True,
151-
href="/pricing",
151+
href="/demo",
152152
class_name="mt-6",
153153
),
154154
class_name="flex flex-col justify-center items-center h-full",

0 commit comments

Comments
 (0)