Skip to content

Commit 75ac78a

Browse files
committed
✨ Add waitlist form
1 parent 2e0e717 commit 75ac78a

2 files changed

Lines changed: 122 additions & 10 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ dependencies = [
3535
"uvicorn[standard] >= 0.15.0",
3636
"rignore >= 0.5.1",
3737
"httpx >= 0.27.0,< 0.28.0",
38-
"rich-toolkit >= 0.14.3",
39-
"pydantic >= 1.6.1",
38+
"rich-toolkit >= 0.14.5",
39+
"pydantic[email] >= 1.6.1",
4040
]
4141

4242
[project.optional-dependencies]

src/fastapi_cloud_cli/commands/deploy.py

Lines changed: 120 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import contextlib
12
import json
23
import logging
4+
import subprocess
35
import tarfile
46
import tempfile
57
import time
@@ -12,7 +14,7 @@
1214
import rignore
1315
import typer
1416
from httpx import Client
15-
from pydantic import BaseModel
17+
from pydantic import BaseModel, EmailStr, TypeAdapter, ValidationError
1618
from rich.text import Text
1719
from rich_toolkit import RichToolkit
1820
from rich_toolkit.menu import Option
@@ -385,6 +387,119 @@ def _setup_environment_variables(toolkit: RichToolkit, app_id: str) -> None:
385387
progress.log("Environment variables set up successfully!")
386388

387389

390+
class SignupToWaitingList(BaseModel):
391+
email: EmailStr
392+
name: str | None = None
393+
organization: str | None = None
394+
role: str | None = None
395+
team_size: str | None = None
396+
location: str | None = None
397+
use_case: str | None = None
398+
secret_code: str | None = None
399+
400+
401+
def _send_waitlist_form(
402+
result: SignupToWaitingList,
403+
toolkit: RichToolkit,
404+
) -> None:
405+
with toolkit.progress("Sending your request...") as progress:
406+
with APIClient() as client:
407+
with handle_http_errors(progress):
408+
response = client.post(
409+
"/users/waiting-list",
410+
json=result.model_dump(mode="json"),
411+
)
412+
413+
response.raise_for_status()
414+
415+
progress.log("Request sent successfully!")
416+
417+
418+
def _waitlist_form(toolkit: RichToolkit) -> None:
419+
from rich_toolkit.form import Form
420+
421+
toolkit.print(
422+
"We're currently in private beta. If you want to be notified when we launch, please fill out the form below.",
423+
tag="waitlist",
424+
)
425+
426+
toolkit.print_line()
427+
428+
email = toolkit.input(
429+
"Enter your email:",
430+
required=True,
431+
validator=TypeAdapter(EmailStr),
432+
)
433+
434+
toolkit.print_line()
435+
436+
result = SignupToWaitingList(email=email)
437+
438+
if toolkit.confirm(
439+
"Do you want to get access faster by giving us more information?",
440+
tag="waitlist",
441+
):
442+
toolkit.print_line()
443+
form = Form("Waitlist form", style=toolkit.style)
444+
445+
form.add_input("name", label="Name", placeholder="John Doe")
446+
form.add_input("organization", label="Organization", placeholder="Acme Inc.")
447+
form.add_input("team", label="Team", placeholder="Team A")
448+
form.add_input("role", label="Role", placeholder="Developer")
449+
form.add_input("location", label="Location", placeholder="San Francisco")
450+
form.add_input(
451+
"how_do_you_plan_to_use_fastapi_cloud",
452+
label="How do you plan to use FastAPI Cloud?",
453+
placeholder="I'm building a web app",
454+
)
455+
form.add_input("secret_code", label="Secret code", placeholder="123456")
456+
457+
result = form.run()
458+
459+
try:
460+
result = SignupToWaitingList.model_validate(
461+
{
462+
"email": email,
463+
**result,
464+
}
465+
)
466+
except ValidationError:
467+
toolkit.print(
468+
"[error]Invalid form data. Please try again.[/]",
469+
)
470+
471+
return
472+
473+
toolkit.print_line()
474+
475+
if toolkit.confirm(
476+
(
477+
"Do you agree to\n"
478+
"- Terms of Service: [link=https://fastapicloud.com/legal/terms]https://fastapicloud.com/legal/terms[/link]\n"
479+
"- Privacy Policy: [link=https://fastapicloud.com/legal/privacy-policy]https://fastapicloud.com/legal/privacy-policy[/link]\n"
480+
),
481+
tag="terms",
482+
):
483+
toolkit.print_line()
484+
485+
_send_waitlist_form(
486+
result,
487+
toolkit,
488+
)
489+
490+
with contextlib.suppress(Exception):
491+
subprocess.run(
492+
["open", "raycast://confetti"],
493+
stdout=subprocess.DEVNULL,
494+
stderr=subprocess.DEVNULL,
495+
check=False,
496+
)
497+
498+
toolkit.print_line()
499+
500+
toolkit.print("Thank you for your interest in FastAPI Cloud! 🚀")
501+
502+
388503
def deploy(
389504
path: Annotated[
390505
Union[Path, None],
@@ -401,17 +516,14 @@ def deploy(
401516
"""
402517

403518
with get_rich_toolkit() as toolkit:
404-
toolkit.print_title("Starting deployment", tag="FastAPI")
405-
toolkit.print_line()
406-
407519
if not is_logged_in():
408-
toolkit.print(
409-
"No credentials found. Use [blue]`fastapi login`[/] to login.",
410-
tag="auth",
411-
)
520+
_waitlist_form(toolkit)
412521

413522
raise typer.Exit(1)
414523

524+
toolkit.print_title("Starting deployment", tag="FastAPI")
525+
toolkit.print_line()
526+
415527
path_to_deploy = path or Path.cwd()
416528

417529
app_config = get_app_config(path_to_deploy)

0 commit comments

Comments
 (0)