nickyni commited on
Commit
c0910f7
Β·
verified Β·
1 Parent(s): de5f9cf

Add AI User Journey Generator demo (Breadcrumb Product Hunt)

Browse files
Files changed (1) hide show
  1. journey_generator_app.py +222 -0
journey_generator_app.py ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import nexaapi
3
+ import requests
4
+ import json
5
+ from io import BytesIO
6
+ from PIL import Image
7
+
8
+ def generate_journey_diagram(
9
+ api_key: str,
10
+ journey_title: str,
11
+ steps_json: str,
12
+ model: str,
13
+ width: int,
14
+ height: int
15
+ ):
16
+ """
17
+ Generate a user journey diagram using NexaAPI.
18
+
19
+ Args:
20
+ api_key: NexaAPI key from nexa-api.com
21
+ journey_title: Title for the journey diagram
22
+ steps_json: JSON string with steps data
23
+ model: AI model to use
24
+ width: Image width
25
+ height: Image height
26
+
27
+ Returns:
28
+ PIL Image of the generated diagram
29
+ """
30
+ if not api_key or api_key.strip() == "":
31
+ return None, "❌ Please enter your NexaAPI key. Get one free at https://nexa-api.com"
32
+
33
+ try:
34
+ steps = json.loads(steps_json)
35
+ except json.JSONDecodeError as e:
36
+ return None, f"❌ Invalid JSON format: {e}"
37
+
38
+ if not steps or len(steps) < 2:
39
+ return None, "❌ Please provide at least 2 journey steps"
40
+
41
+ # Build prompt
42
+ steps_desc = " β†’ ".join([
43
+ f"{s.get('name', 'Step')} ({s.get('users', 0):,} users)"
44
+ for s in steps
45
+ ])
46
+
47
+ drop_offs = [
48
+ f"{s.get('name', 'Step')}: {int(s.get('drop_off', 0) * 100)}% drop-off"
49
+ for s in steps
50
+ if s.get("drop_off", 0) > 0
51
+ ]
52
+
53
+ prompt = (
54
+ f"Professional user journey funnel diagram titled '{journey_title}'. "
55
+ f"Sequential steps: {steps_desc}. "
56
+ f"Drop-off rates: {', '.join(drop_offs) if drop_offs else 'not specified'}. "
57
+ "Clean modern flat design, gradient blue-to-green color scheme, "
58
+ "white background, clear typography, directional arrows, "
59
+ "user count labels, professional business style."
60
+ )
61
+
62
+ try:
63
+ client = nexaapi.Client(api_key=api_key.strip())
64
+
65
+ response = client.images.generate(
66
+ model=model,
67
+ prompt=prompt,
68
+ width=width,
69
+ height=height,
70
+ num_images=1
71
+ )
72
+
73
+ image_url = response.data[0].url
74
+
75
+ # Download image
76
+ img_response = requests.get(image_url, timeout=30)
77
+ img_response.raise_for_status()
78
+
79
+ image = Image.open(BytesIO(img_response.content))
80
+
81
+ return image, f"βœ… Generated successfully!\nπŸ”— URL: {image_url}"
82
+
83
+ except Exception as e:
84
+ return None, f"❌ Generation failed: {str(e)}\n\nMake sure your API key is valid at https://nexa-api.com"
85
+
86
+
87
+ # Example journey data
88
+ EXAMPLE_STEPS = json.dumps([
89
+ {"name": "Landing Page", "users": 10000, "drop_off": 0.35},
90
+ {"name": "Sign Up", "users": 6500, "drop_off": 0.20},
91
+ {"name": "Email Verified", "users": 5200, "drop_off": 0.15},
92
+ {"name": "First Action", "users": 4420, "drop_off": 0.10},
93
+ {"name": "Paid Conversion", "users": 3978, "drop_off": 0.00}
94
+ ], indent=2)
95
+
96
+ ECOMMERCE_STEPS = json.dumps([
97
+ {"name": "Homepage", "users": 50000, "drop_off": 0.60},
98
+ {"name": "Product Page", "users": 20000, "drop_off": 0.40},
99
+ {"name": "Add to Cart", "users": 12000, "drop_off": 0.50},
100
+ {"name": "Checkout", "users": 6000, "drop_off": 0.30},
101
+ {"name": "Purchase", "users": 4200, "drop_off": 0.00}
102
+ ], indent=2)
103
+
104
+ MOBILE_STEPS = json.dumps([
105
+ {"name": "App Install", "users": 5000, "drop_off": 0.20},
106
+ {"name": "Permissions", "users": 4000, "drop_off": 0.15},
107
+ {"name": "Account Setup","users": 3400, "drop_off": 0.10},
108
+ {"name": "Tutorial", "users": 3060, "drop_off": 0.08},
109
+ {"name": "First Use", "users": 2815, "drop_off": 0.00}
110
+ ], indent=2)
111
+
112
+
113
+ # Build Gradio interface
114
+ with gr.Blocks(
115
+ title="AI User Journey Generator",
116
+ theme=gr.themes.Soft(),
117
+ css="""
118
+ .header { text-align: center; padding: 20px; }
119
+ .links { text-align: center; font-size: 14px; }
120
+ """
121
+ ) as demo:
122
+
123
+ gr.HTML("""
124
+ <div class="header">
125
+ <h1>πŸ—ΊοΈ AI User Journey Generator</h1>
126
+ <p>Generate beautiful user journey diagrams from your analytics data using AI</p>
127
+ <p>Inspired by <strong>Breadcrumb.ai</strong> on Product Hunt πŸš€</p>
128
+ </div>
129
+ """)
130
+
131
+ with gr.Row():
132
+ with gr.Column(scale=1):
133
+ gr.Markdown("### βš™οΈ Configuration")
134
+
135
+ api_key = gr.Textbox(
136
+ label="NexaAPI Key",
137
+ placeholder="Enter your API key from nexa-api.com",
138
+ type="password",
139
+ info="Get a free key at https://nexa-api.com"
140
+ )
141
+
142
+ journey_title = gr.Textbox(
143
+ label="Journey Title",
144
+ value="SaaS Onboarding Funnel",
145
+ placeholder="e.g., SaaS Onboarding Funnel"
146
+ )
147
+
148
+ model = gr.Dropdown(
149
+ label="AI Model",
150
+ choices=["flux-schnell", "flux-dev", "sdxl", "dall-e-3"],
151
+ value="flux-schnell",
152
+ info="flux-schnell is fastest; flux-dev is highest quality"
153
+ )
154
+
155
+ with gr.Row():
156
+ width = gr.Slider(512, 1920, value=1200, step=64, label="Width")
157
+ height = gr.Slider(512, 1080, value=700, step=64, label="Height")
158
+
159
+ gr.Markdown("### πŸ“Š Journey Steps (JSON)")
160
+ gr.Markdown("Format: `[{\"name\": \"Step\", \"users\": 1000, \"drop_off\": 0.20}]`")
161
+
162
+ steps_json = gr.Code(
163
+ label="Steps Data",
164
+ value=EXAMPLE_STEPS,
165
+ language="json",
166
+ lines=12
167
+ )
168
+
169
+ with gr.Row():
170
+ gr.Button("πŸ“± Mobile Example", size="sm").click(
171
+ fn=lambda: ("Mobile App Onboarding", MOBILE_STEPS),
172
+ outputs=[journey_title, steps_json]
173
+ )
174
+ gr.Button("πŸ›’ E-commerce Example", size="sm").click(
175
+ fn=lambda: ("E-commerce Purchase Flow", ECOMMERCE_STEPS),
176
+ outputs=[journey_title, steps_json]
177
+ )
178
+
179
+ generate_btn = gr.Button(
180
+ "🎨 Generate Journey Diagram",
181
+ variant="primary",
182
+ size="lg"
183
+ )
184
+
185
+ with gr.Column(scale=1):
186
+ gr.Markdown("### πŸ–ΌοΈ Generated Diagram")
187
+
188
+ output_image = gr.Image(
189
+ label="User Journey Visualization",
190
+ type="pil",
191
+ height=500
192
+ )
193
+
194
+ status_text = gr.Textbox(
195
+ label="Status",
196
+ interactive=False,
197
+ lines=3
198
+ )
199
+
200
+ generate_btn.click(
201
+ fn=generate_journey_diagram,
202
+ inputs=[api_key, journey_title, steps_json, model, width, height],
203
+ outputs=[output_image, status_text]
204
+ )
205
+
206
+ gr.HTML("""
207
+ <div class="links">
208
+ <p>
209
+ 🌐 <a href="https://nexa-api.com" target="_blank">nexa-api.com</a> &nbsp;|&nbsp;
210
+ πŸ“¦ <a href="https://pypi.org/project/nexaapi" target="_blank">PyPI</a> &nbsp;|&nbsp;
211
+ πŸ“¦ <a href="https://npmjs.com/package/nexaapi" target="_blank">npm</a> &nbsp;|&nbsp;
212
+ πŸ”— <a href="https://rapidapi.com/user/nexaquency" target="_blank">RapidAPI</a>
213
+ </p>
214
+ <p style="color: #666; font-size: 12px;">
215
+ Powered by NexaAPI β€” 38+ AI models, one API key
216
+ </p>
217
+ </div>
218
+ """)
219
+
220
+
221
+ if __name__ == "__main__":
222
+ demo.launch()