python2mobile 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. python2mobile-1.0.1/PKG-INFO +238 -0
  2. python2mobile-1.0.1/README.md +203 -0
  3. python2mobile-1.0.1/examples/example_ecommerce_app.py +189 -0
  4. python2mobile-1.0.1/examples/example_todo_app.py +159 -0
  5. python2mobile-1.0.1/p2m/__init__.py +31 -0
  6. python2mobile-1.0.1/p2m/cli.py +470 -0
  7. python2mobile-1.0.1/p2m/config.py +205 -0
  8. python2mobile-1.0.1/p2m/core/__init__.py +18 -0
  9. python2mobile-1.0.1/p2m/core/api.py +191 -0
  10. python2mobile-1.0.1/p2m/core/ast_walker.py +171 -0
  11. python2mobile-1.0.1/p2m/core/database.py +192 -0
  12. python2mobile-1.0.1/p2m/core/events.py +56 -0
  13. python2mobile-1.0.1/p2m/core/render_engine.py +597 -0
  14. python2mobile-1.0.1/p2m/core/runtime.py +128 -0
  15. python2mobile-1.0.1/p2m/core/state.py +51 -0
  16. python2mobile-1.0.1/p2m/core/validator.py +284 -0
  17. python2mobile-1.0.1/p2m/devserver/__init__.py +9 -0
  18. python2mobile-1.0.1/p2m/devserver/server.py +84 -0
  19. python2mobile-1.0.1/p2m/i18n/__init__.py +7 -0
  20. python2mobile-1.0.1/p2m/i18n/translator.py +74 -0
  21. python2mobile-1.0.1/p2m/imagine/__init__.py +35 -0
  22. python2mobile-1.0.1/p2m/imagine/agent.py +463 -0
  23. python2mobile-1.0.1/p2m/imagine/legacy.py +217 -0
  24. python2mobile-1.0.1/p2m/llm/__init__.py +20 -0
  25. python2mobile-1.0.1/p2m/llm/anthropic_provider.py +78 -0
  26. python2mobile-1.0.1/p2m/llm/base.py +42 -0
  27. python2mobile-1.0.1/p2m/llm/compatible_provider.py +120 -0
  28. python2mobile-1.0.1/p2m/llm/factory.py +72 -0
  29. python2mobile-1.0.1/p2m/llm/ollama_provider.py +89 -0
  30. python2mobile-1.0.1/p2m/llm/openai_provider.py +79 -0
  31. python2mobile-1.0.1/p2m/testing/__init__.py +41 -0
  32. python2mobile-1.0.1/p2m/ui/__init__.py +43 -0
  33. python2mobile-1.0.1/p2m/ui/components.py +301 -0
  34. python2mobile-1.0.1/pyproject.toml +68 -0
  35. python2mobile-1.0.1/python2mobile.egg-info/PKG-INFO +238 -0
  36. python2mobile-1.0.1/python2mobile.egg-info/SOURCES.txt +53 -0
  37. python2mobile-1.0.1/python2mobile.egg-info/dependency_links.txt +1 -0
  38. python2mobile-1.0.1/python2mobile.egg-info/entry_points.txt +2 -0
  39. python2mobile-1.0.1/python2mobile.egg-info/requires.txt +20 -0
  40. python2mobile-1.0.1/python2mobile.egg-info/top_level.txt +4 -0
  41. python2mobile-1.0.1/setup.cfg +4 -0
  42. python2mobile-1.0.1/tests/test_basic_engine.py +281 -0
  43. python2mobile-1.0.1/tests/test_build_generation.py +603 -0
  44. python2mobile-1.0.1/tests/test_build_test_gate.py +150 -0
  45. python2mobile-1.0.1/tests/test_carousel_modal.py +84 -0
  46. python2mobile-1.0.1/tests/test_config_system.py +272 -0
  47. python2mobile-1.0.1/tests/test_i18n.py +101 -0
  48. python2mobile-1.0.1/tests/test_ifood_app_integration.py +172 -0
  49. python2mobile-1.0.1/tests/test_imagine_cli.py +133 -0
  50. python2mobile-1.0.1/tests/test_imagine_command.py +341 -0
  51. python2mobile-1.0.1/tests/test_llm_providers.py +321 -0
  52. python2mobile-1.0.1/tests/test_new_apps_integration.py +588 -0
  53. python2mobile-1.0.1/tests/test_ollama_functional.py +329 -0
  54. python2mobile-1.0.1/tests/test_real_world_apps.py +228 -0
  55. python2mobile-1.0.1/tests/test_run_integration.py +776 -0
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.4
2
+ Name: python2mobile
3
+ Version: 1.0.1
4
+ Summary: Python to Mobile - Write mobile apps in pure Python with DSL
5
+ Author-email: P2M Team <team@python2mobile.dev>
6
+ License-Expression: MIT
7
+ Keywords: mobile,python,dsl,flutter,react-native,llm,ai
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: click>=8.1.0
17
+ Requires-Dist: fastapi>=0.104.0
18
+ Requires-Dist: uvicorn>=0.24.0
19
+ Requires-Dist: watchdog>=3.0.0
20
+ Requires-Dist: jinja2>=3.1.0
21
+ Requires-Dist: pydantic>=2.0.0
22
+ Requires-Dist: python-dotenv>=1.0.0
23
+ Requires-Dist: requests>=2.31.0
24
+ Requires-Dist: openai>=1.3.0
25
+ Requires-Dist: anthropic>=0.7.0
26
+ Requires-Dist: toml>=0.10.0
27
+ Requires-Dist: websockets>=12.0
28
+ Requires-Dist: agno>=2.1.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
31
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
32
+ Requires-Dist: black>=23.0.0; extra == "dev"
33
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
34
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
35
+
36
+ # Python2Mobile (P2M)
37
+
38
+ Write mobile apps in **pure Python** with a declarative DSL. P2M generates or runs native/hybrid apps for Android, iOS, and Web.
39
+
40
+ ## Features
41
+
42
+ - **Python DSL** - Write UI and logic in familiar Python syntax
43
+ - **Tailwind-like Styling** - Use CSS class names for mobile styling
44
+ - **Hot Reload** - See changes instantly during development
45
+ - **Multi-LLM Support** - OpenAI, Claude, Ollama, or any OpenAI-compatible API
46
+ - **Multiple Targets** - Generate React Native or Flutter code
47
+ - **DevServer** - Preview apps in browser before building
48
+
49
+ ## Quick Start
50
+
51
+ ```bash
52
+ pip install python2mobile
53
+
54
+ # Create a new app
55
+ p2m new myapp
56
+ cd myapp
57
+
58
+ # Run in development mode (hot reload)
59
+ p2m run
60
+
61
+ # Build for production
62
+ p2m build --target android
63
+ p2m build --target ios
64
+ p2m build --target web
65
+ ```
66
+
67
+ ## Example App
68
+
69
+ ```python
70
+ from p2m.core import Render
71
+ from p2m.ui import Container, Text, Button
72
+
73
+ def click_button():
74
+ print("Button clicked!")
75
+
76
+ def create_view():
77
+ container = Container(class_="bg-gray-100 min-h-screen flex items-center justify-center")
78
+ inner = Container(class_="text-center space-y-6 p-8 bg-white rounded-2xl shadow-lg")
79
+
80
+ text = Text("Welcome to P2M", class_="text-gray-800 text-2xl font-bold")
81
+ button = Button(
82
+ "Click Me",
83
+ class_="bg-blue-600 text-white font-semibold py-3 px-8 rounded-xl hover:bg-blue-700",
84
+ on_click=click_button
85
+ )
86
+
87
+ inner.add(text).add(button)
88
+ container.add(inner)
89
+ return container.build()
90
+
91
+ def main():
92
+ Render.execute(create_view)
93
+
94
+ if __name__ == "__main__":
95
+ main()
96
+ ```
97
+
98
+ ## Configuration
99
+
100
+ Create a `p2m.toml` file:
101
+
102
+ ```toml
103
+ [project]
104
+ name = "MyApp"
105
+ version = "0.1.0"
106
+ entry = "main.py"
107
+
108
+ [build]
109
+ target = ["android", "ios", "web"]
110
+ generator = "flutter" # or "react-native"
111
+ llm_provider = "openai" # openai | anthropic | ollama | openai-compatible
112
+ llm_model = "gpt-4o"
113
+ output_dir = "./build"
114
+ cache = true
115
+
116
+ [devserver]
117
+ port = 3000
118
+ hot_reload = true
119
+ mobile_frame = true
120
+
121
+ [style]
122
+ system = "tailwind"
123
+ ```
124
+
125
+ ## LLM Configuration
126
+
127
+ ### OpenAI
128
+ ```toml
129
+ [llm.openai]
130
+ api_key = "sk-..."
131
+ model = "gpt-4o"
132
+ ```
133
+
134
+ ### Claude (Anthropic)
135
+ ```toml
136
+ [llm.anthropic]
137
+ api_key = "sk-ant-..."
138
+ model = "claude-3-opus-20240229"
139
+ ```
140
+
141
+ ### Ollama (Local)
142
+ ```toml
143
+ [llm.ollama]
144
+ base_url = "http://localhost:11434"
145
+ model = "llama2"
146
+ ```
147
+
148
+ ### OpenAI Compatible
149
+ ```toml
150
+ [llm.custom]
151
+ base_url = "https://api.example.com/v1"
152
+ api_key = "your-api-key"
153
+ model = "your-model-name"
154
+ x_api_key = "optional-header"
155
+ ```
156
+
157
+ ## Architecture
158
+
159
+ ```
160
+ ┌─────────────────────────────────────────────────────┐
161
+ │ DEVELOPER │
162
+ │ writes in Python P2M │
163
+ └──────────────────────┬──────────────────────────────┘
164
+
165
+ ┌────────────▼────────────┐
166
+ │ p2m CLI │
167
+ │ (p2m run / p2m build) │
168
+ └────────────┬────────────┘
169
+
170
+ ┌─────────────┴──────────────┐
171
+ │ │
172
+ ┌────▼────┐ ┌─────▼──────┐
173
+ │ p2m run │ │ p2m build │
174
+ │ (dev) │ │ (prod) │
175
+ └────┬────┘ └─────┬──────┘
176
+ │ │
177
+ ┌────▼────────────┐ ┌──────▼───────────┐
178
+ │ P2M Runtime │ │ AI Code Generator│
179
+ │ - AST Parser │ │ - LLM Integration│
180
+ │ - Safe Eval │ │ - React Native │
181
+ │ - HTML Renderer │ │ - Flutter │
182
+ │ - Hot Reload │ │ - Web │
183
+ └────┬────────────┘ └──────┬───────────┘
184
+ │ │
185
+ ┌────▼────────────┐ ┌──────▼───────────┐
186
+ │ Web Visualizer │ │ /build/ │
187
+ │ localhost:3000 │ │ android/ │
188
+ │ Mobile Preview │ │ ios/ │
189
+ └─────────────────┘ │ web/ │
190
+ └──────────────────┘
191
+ ```
192
+
193
+ ## Project Structure
194
+
195
+ ```
196
+ p2m/
197
+ ├── __init__.py
198
+ ├── cli.py # CLI entry point
199
+ ├── config.py # Configuration management
200
+ ├── core/
201
+ │ ├── __init__.py
202
+ │ ├── runtime.py # Python runtime engine
203
+ │ ├── ast_walker.py # AST analysis
204
+ │ ├── render_engine.py # Component tree → HTML
205
+ │ ├── hot_reload.py # File watcher
206
+ │ └── event_bridge.py # JS ↔ Python bridge
207
+ ├── ui/
208
+ │ ├── __init__.py
209
+ │ ├── components.py # Base components
210
+ │ ├── layouts.py # Layout components
211
+ │ └── styles.py # Style system
212
+ ├── devserver/
213
+ │ ├── __init__.py
214
+ │ ├── server.py # FastAPI server
215
+ │ ├── templates.py # Jinja2 templates
216
+ │ └── websocket_handler.py # WebSocket bridge
217
+ ├── llm/
218
+ │ ├── __init__.py
219
+ │ ├── base.py # Base LLM interface
220
+ │ ├── openai_provider.py # OpenAI integration
221
+ │ ├── anthropic_provider.py # Claude integration
222
+ │ ├── ollama_provider.py # Ollama integration
223
+ │ └── factory.py # LLM factory
224
+ ├── build/
225
+ │ ├── __init__.py
226
+ │ ├── generator.py # Code generator
227
+ │ ├── react_native.py # React Native templates
228
+ │ ├── flutter.py # Flutter templates
229
+ │ └── cache.py # Build cache
230
+ └── utils/
231
+ ├── __init__.py
232
+ ├── logger.py # Logging
233
+ └── validators.py # Validation
234
+ ```
235
+
236
+ ## License
237
+
238
+ MIT
@@ -0,0 +1,203 @@
1
+ # Python2Mobile (P2M)
2
+
3
+ Write mobile apps in **pure Python** with a declarative DSL. P2M generates or runs native/hybrid apps for Android, iOS, and Web.
4
+
5
+ ## Features
6
+
7
+ - **Python DSL** - Write UI and logic in familiar Python syntax
8
+ - **Tailwind-like Styling** - Use CSS class names for mobile styling
9
+ - **Hot Reload** - See changes instantly during development
10
+ - **Multi-LLM Support** - OpenAI, Claude, Ollama, or any OpenAI-compatible API
11
+ - **Multiple Targets** - Generate React Native or Flutter code
12
+ - **DevServer** - Preview apps in browser before building
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ pip install python2mobile
18
+
19
+ # Create a new app
20
+ p2m new myapp
21
+ cd myapp
22
+
23
+ # Run in development mode (hot reload)
24
+ p2m run
25
+
26
+ # Build for production
27
+ p2m build --target android
28
+ p2m build --target ios
29
+ p2m build --target web
30
+ ```
31
+
32
+ ## Example App
33
+
34
+ ```python
35
+ from p2m.core import Render
36
+ from p2m.ui import Container, Text, Button
37
+
38
+ def click_button():
39
+ print("Button clicked!")
40
+
41
+ def create_view():
42
+ container = Container(class_="bg-gray-100 min-h-screen flex items-center justify-center")
43
+ inner = Container(class_="text-center space-y-6 p-8 bg-white rounded-2xl shadow-lg")
44
+
45
+ text = Text("Welcome to P2M", class_="text-gray-800 text-2xl font-bold")
46
+ button = Button(
47
+ "Click Me",
48
+ class_="bg-blue-600 text-white font-semibold py-3 px-8 rounded-xl hover:bg-blue-700",
49
+ on_click=click_button
50
+ )
51
+
52
+ inner.add(text).add(button)
53
+ container.add(inner)
54
+ return container.build()
55
+
56
+ def main():
57
+ Render.execute(create_view)
58
+
59
+ if __name__ == "__main__":
60
+ main()
61
+ ```
62
+
63
+ ## Configuration
64
+
65
+ Create a `p2m.toml` file:
66
+
67
+ ```toml
68
+ [project]
69
+ name = "MyApp"
70
+ version = "0.1.0"
71
+ entry = "main.py"
72
+
73
+ [build]
74
+ target = ["android", "ios", "web"]
75
+ generator = "flutter" # or "react-native"
76
+ llm_provider = "openai" # openai | anthropic | ollama | openai-compatible
77
+ llm_model = "gpt-4o"
78
+ output_dir = "./build"
79
+ cache = true
80
+
81
+ [devserver]
82
+ port = 3000
83
+ hot_reload = true
84
+ mobile_frame = true
85
+
86
+ [style]
87
+ system = "tailwind"
88
+ ```
89
+
90
+ ## LLM Configuration
91
+
92
+ ### OpenAI
93
+ ```toml
94
+ [llm.openai]
95
+ api_key = "sk-..."
96
+ model = "gpt-4o"
97
+ ```
98
+
99
+ ### Claude (Anthropic)
100
+ ```toml
101
+ [llm.anthropic]
102
+ api_key = "sk-ant-..."
103
+ model = "claude-3-opus-20240229"
104
+ ```
105
+
106
+ ### Ollama (Local)
107
+ ```toml
108
+ [llm.ollama]
109
+ base_url = "http://localhost:11434"
110
+ model = "llama2"
111
+ ```
112
+
113
+ ### OpenAI Compatible
114
+ ```toml
115
+ [llm.custom]
116
+ base_url = "https://api.example.com/v1"
117
+ api_key = "your-api-key"
118
+ model = "your-model-name"
119
+ x_api_key = "optional-header"
120
+ ```
121
+
122
+ ## Architecture
123
+
124
+ ```
125
+ ┌─────────────────────────────────────────────────────┐
126
+ │ DEVELOPER │
127
+ │ writes in Python P2M │
128
+ └──────────────────────┬──────────────────────────────┘
129
+
130
+ ┌────────────▼────────────┐
131
+ │ p2m CLI │
132
+ │ (p2m run / p2m build) │
133
+ └────────────┬────────────┘
134
+
135
+ ┌─────────────┴──────────────┐
136
+ │ │
137
+ ┌────▼────┐ ┌─────▼──────┐
138
+ │ p2m run │ │ p2m build │
139
+ │ (dev) │ │ (prod) │
140
+ └────┬────┘ └─────┬──────┘
141
+ │ │
142
+ ┌────▼────────────┐ ┌──────▼───────────┐
143
+ │ P2M Runtime │ │ AI Code Generator│
144
+ │ - AST Parser │ │ - LLM Integration│
145
+ │ - Safe Eval │ │ - React Native │
146
+ │ - HTML Renderer │ │ - Flutter │
147
+ │ - Hot Reload │ │ - Web │
148
+ └────┬────────────┘ └──────┬───────────┘
149
+ │ │
150
+ ┌────▼────────────┐ ┌──────▼───────────┐
151
+ │ Web Visualizer │ │ /build/ │
152
+ │ localhost:3000 │ │ android/ │
153
+ │ Mobile Preview │ │ ios/ │
154
+ └─────────────────┘ │ web/ │
155
+ └──────────────────┘
156
+ ```
157
+
158
+ ## Project Structure
159
+
160
+ ```
161
+ p2m/
162
+ ├── __init__.py
163
+ ├── cli.py # CLI entry point
164
+ ├── config.py # Configuration management
165
+ ├── core/
166
+ │ ├── __init__.py
167
+ │ ├── runtime.py # Python runtime engine
168
+ │ ├── ast_walker.py # AST analysis
169
+ │ ├── render_engine.py # Component tree → HTML
170
+ │ ├── hot_reload.py # File watcher
171
+ │ └── event_bridge.py # JS ↔ Python bridge
172
+ ├── ui/
173
+ │ ├── __init__.py
174
+ │ ├── components.py # Base components
175
+ │ ├── layouts.py # Layout components
176
+ │ └── styles.py # Style system
177
+ ├── devserver/
178
+ │ ├── __init__.py
179
+ │ ├── server.py # FastAPI server
180
+ │ ├── templates.py # Jinja2 templates
181
+ │ └── websocket_handler.py # WebSocket bridge
182
+ ├── llm/
183
+ │ ├── __init__.py
184
+ │ ├── base.py # Base LLM interface
185
+ │ ├── openai_provider.py # OpenAI integration
186
+ │ ├── anthropic_provider.py # Claude integration
187
+ │ ├── ollama_provider.py # Ollama integration
188
+ │ └── factory.py # LLM factory
189
+ ├── build/
190
+ │ ├── __init__.py
191
+ │ ├── generator.py # Code generator
192
+ │ ├── react_native.py # React Native templates
193
+ │ ├── flutter.py # Flutter templates
194
+ │ └── cache.py # Build cache
195
+ └── utils/
196
+ ├── __init__.py
197
+ ├── logger.py # Logging
198
+ └── validators.py # Validation
199
+ ```
200
+
201
+ ## License
202
+
203
+ MIT
@@ -0,0 +1,189 @@
1
+ """
2
+ Example: E-commerce App - Real-world P2M application
3
+ """
4
+
5
+ from p2m.core import Render
6
+ from p2m.ui import Container, Text, Button, Input, Image, Row, Column, Card, Badge
7
+
8
+
9
+ # Mock product data
10
+ products = [
11
+ {
12
+ "id": 1,
13
+ "name": "Wireless Headphones",
14
+ "price": 79.99,
15
+ "rating": 4.5,
16
+ "image": "https://via.placeholder.com/200x200?text=Headphones",
17
+ "in_stock": True,
18
+ },
19
+ {
20
+ "id": 2,
21
+ "name": "Smart Watch",
22
+ "price": 199.99,
23
+ "rating": 4.8,
24
+ "image": "https://via.placeholder.com/200x200?text=SmartWatch",
25
+ "in_stock": True,
26
+ },
27
+ {
28
+ "id": 3,
29
+ "name": "USB-C Cable",
30
+ "price": 12.99,
31
+ "rating": 4.2,
32
+ "image": "https://via.placeholder.com/200x200?text=Cable",
33
+ "in_stock": False,
34
+ },
35
+ ]
36
+
37
+ # Shopping cart
38
+ cart = []
39
+
40
+
41
+ def add_to_cart(product_id: int):
42
+ """Add product to cart"""
43
+ product = next((p for p in products if p["id"] == product_id), None)
44
+ if product:
45
+ cart.append(product)
46
+ print(f"Added {product['name']} to cart")
47
+
48
+
49
+ def remove_from_cart(product_id: int):
50
+ """Remove product from cart"""
51
+ global cart
52
+ cart = [p for p in cart if p["id"] != product_id]
53
+ print(f"Removed product {product_id} from cart")
54
+
55
+
56
+ def render_product_card(product: dict):
57
+ """Render a product card"""
58
+ card = Card(class_="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow")
59
+
60
+ # Product image
61
+ image = Image(
62
+ src=product["image"],
63
+ alt=product["name"],
64
+ class_="w-full h-48 object-cover"
65
+ )
66
+ card.add(image)
67
+
68
+ # Product info
69
+ info = Container(class_="p-4")
70
+
71
+ # Name
72
+ name = Text(product["name"], class_="text-lg font-semibold text-gray-800 mb-2")
73
+ info.add(name)
74
+
75
+ # Rating and price row
76
+ rating_price = Row(class_="flex justify-between items-center mb-3")
77
+
78
+ rating = Badge(
79
+ label=f"⭐ {product['rating']}",
80
+ class_="bg-yellow-100 text-yellow-800 px-2 py-1 rounded text-sm"
81
+ )
82
+ rating_price.add(rating)
83
+
84
+ price = Text(f"${product['price']}", class_="text-xl font-bold text-blue-600")
85
+ rating_price.add(price)
86
+
87
+ info.add(rating_price)
88
+
89
+ # Stock status
90
+ stock_class = "bg-green-100 text-green-800" if product["in_stock"] else "bg-red-100 text-red-800"
91
+ stock_text = "In Stock" if product["in_stock"] else "Out of Stock"
92
+ stock = Badge(
93
+ label=stock_text,
94
+ class_=f"{stock_class} px-2 py-1 rounded text-xs font-semibold"
95
+ )
96
+ info.add(stock)
97
+
98
+ # Add to cart button
99
+ btn_class = "bg-blue-600 hover:bg-blue-700 text-white" if product["in_stock"] else "bg-gray-400 text-gray-600 cursor-not-allowed"
100
+ add_btn = Button(
101
+ "Add to Cart",
102
+ class_=f"{btn_class} w-full mt-4 px-4 py-2 rounded font-semibold",
103
+ on_click=lambda: add_to_cart(product["id"]) if product["in_stock"] else None
104
+ )
105
+ info.add(add_btn)
106
+
107
+ card.add(info)
108
+ return card
109
+
110
+
111
+ def create_view():
112
+ """Create the e-commerce app view"""
113
+
114
+ # Main container
115
+ main = Container(class_="bg-gray-50 min-h-screen")
116
+
117
+ # Header
118
+ header = Container(class_="bg-blue-600 text-white p-4 shadow-md")
119
+
120
+ title = Text("TechStore", class_="text-2xl font-bold mb-2")
121
+ header.add(title)
122
+
123
+ subtitle = Text("Your favorite tech products", class_="text-blue-100")
124
+ header.add(subtitle)
125
+
126
+ main.add(header)
127
+
128
+ # Search bar
129
+ search_section = Container(class_="bg-white p-4 border-b border-gray-200")
130
+ search_input = Input(
131
+ placeholder="Search products...",
132
+ class_="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
133
+ )
134
+ search_section.add(search_input)
135
+ main.add(search_section)
136
+
137
+ # Products section
138
+ products_section = Container(class_="p-4")
139
+
140
+ section_title = Text("Featured Products", class_="text-xl font-bold text-gray-800 mb-4")
141
+ products_section.add(section_title)
142
+
143
+ # Products grid
144
+ products_grid = Container(class_="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4")
145
+
146
+ for product in products:
147
+ product_card = render_product_card(product)
148
+ products_grid.add(product_card)
149
+
150
+ products_section.add(products_grid)
151
+ main.add(products_section)
152
+
153
+ # Cart summary
154
+ cart_section = Container(class_="bg-white p-4 border-t border-gray-200 sticky bottom-0")
155
+
156
+ cart_row = Row(class_="flex justify-between items-center")
157
+
158
+ cart_info = Column()
159
+ cart_label = Text("Shopping Cart", class_="font-semibold text-gray-800")
160
+ cart_info.add(cart_label)
161
+
162
+ cart_count = Text(
163
+ f"{len(cart)} items • ${sum(p['price'] for p in cart):.2f}",
164
+ class_="text-sm text-gray-600"
165
+ )
166
+ cart_info.add(cart_count)
167
+
168
+ cart_row.add(cart_info)
169
+
170
+ checkout_btn = Button(
171
+ "Checkout",
172
+ class_="bg-green-600 hover:bg-green-700 text-white px-6 py-2 rounded font-semibold",
173
+ on_click=lambda: print("Checkout clicked")
174
+ )
175
+ cart_row.add(checkout_btn)
176
+
177
+ cart_section.add(cart_row)
178
+ main.add(cart_section)
179
+
180
+ return main.build()
181
+
182
+
183
+ def main():
184
+ """Main entry point"""
185
+ Render.execute(create_view)
186
+
187
+
188
+ if __name__ == "__main__":
189
+ main()