pyxle-framework 0.1.0__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 (166) hide show
  1. pyxle_framework-0.1.0/.github/pyxle-logo.svg +19 -0
  2. pyxle_framework-0.1.0/.gitignore +58 -0
  3. pyxle_framework-0.1.0/CLAUDE.md +386 -0
  4. pyxle_framework-0.1.0/Makefile +15 -0
  5. pyxle_framework-0.1.0/PKG-INFO +136 -0
  6. pyxle_framework-0.1.0/README.md +99 -0
  7. pyxle_framework-0.1.0/docs/README.md +67 -0
  8. pyxle_framework-0.1.0/docs/advanced/compiler-internals.md +159 -0
  9. pyxle_framework-0.1.0/docs/advanced/ssr-pipeline.md +144 -0
  10. pyxle_framework-0.1.0/docs/core-concepts/data-loading.md +140 -0
  11. pyxle_framework-0.1.0/docs/core-concepts/layouts.md +103 -0
  12. pyxle_framework-0.1.0/docs/core-concepts/pyx-files.md +174 -0
  13. pyxle_framework-0.1.0/docs/core-concepts/routing.md +132 -0
  14. pyxle_framework-0.1.0/docs/core-concepts/server-actions.md +161 -0
  15. pyxle_framework-0.1.0/docs/faq.md +203 -0
  16. pyxle_framework-0.1.0/docs/getting-started/installation.md +58 -0
  17. pyxle_framework-0.1.0/docs/getting-started/project-structure.md +158 -0
  18. pyxle_framework-0.1.0/docs/getting-started/quick-start.md +99 -0
  19. pyxle_framework-0.1.0/docs/guides/api-routes.md +136 -0
  20. pyxle_framework-0.1.0/docs/guides/client-components.md +146 -0
  21. pyxle_framework-0.1.0/docs/guides/deployment.md +187 -0
  22. pyxle_framework-0.1.0/docs/guides/environment-variables.md +124 -0
  23. pyxle_framework-0.1.0/docs/guides/error-handling.md +136 -0
  24. pyxle_framework-0.1.0/docs/guides/head-management.md +133 -0
  25. pyxle_framework-0.1.0/docs/guides/middleware.md +127 -0
  26. pyxle_framework-0.1.0/docs/guides/security.md +146 -0
  27. pyxle_framework-0.1.0/docs/guides/styling.md +133 -0
  28. pyxle_framework-0.1.0/docs/reference/cli.md +212 -0
  29. pyxle_framework-0.1.0/docs/reference/client-api.md +229 -0
  30. pyxle_framework-0.1.0/docs/reference/configuration.md +212 -0
  31. pyxle_framework-0.1.0/docs/reference/runtime-api.md +161 -0
  32. pyxle_framework-0.1.0/pyproject.toml +74 -0
  33. pyxle_framework-0.1.0/pyxle/__init__.py +7 -0
  34. pyxle_framework-0.1.0/pyxle/cli/__init__.py +1176 -0
  35. pyxle_framework-0.1.0/pyxle/cli/assets.py +17 -0
  36. pyxle_framework-0.1.0/pyxle/cli/init.py +117 -0
  37. pyxle_framework-0.1.0/pyxle/cli/logger.py +192 -0
  38. pyxle_framework-0.1.0/pyxle/cli/scaffold.py +100 -0
  39. pyxle_framework-0.1.0/pyxle/cli/templates.py +49 -0
  40. pyxle_framework-0.1.0/pyxle/client/ClientOnly.jsx +18 -0
  41. pyxle_framework-0.1.0/pyxle/client/Form.jsx +133 -0
  42. pyxle_framework-0.1.0/pyxle/client/Head.jsx +34 -0
  43. pyxle_framework-0.1.0/pyxle/client/Image.jsx +27 -0
  44. pyxle_framework-0.1.0/pyxle/client/Script.jsx +19 -0
  45. pyxle_framework-0.1.0/pyxle/client/index.js +18 -0
  46. pyxle_framework-0.1.0/pyxle/client/useAction.jsx +107 -0
  47. pyxle_framework-0.1.0/pyxle/compiler/__init__.py +7 -0
  48. pyxle_framework-0.1.0/pyxle/compiler/core.py +68 -0
  49. pyxle_framework-0.1.0/pyxle/compiler/exceptions.py +18 -0
  50. pyxle_framework-0.1.0/pyxle/compiler/jsx_imports.py +372 -0
  51. pyxle_framework-0.1.0/pyxle/compiler/jsx_parser.py +127 -0
  52. pyxle_framework-0.1.0/pyxle/compiler/model.py +128 -0
  53. pyxle_framework-0.1.0/pyxle/compiler/parser.py +941 -0
  54. pyxle_framework-0.1.0/pyxle/compiler/writers.py +306 -0
  55. pyxle_framework-0.1.0/pyxle/config.py +500 -0
  56. pyxle_framework-0.1.0/pyxle/devserver/__init__.py +276 -0
  57. pyxle_framework-0.1.0/pyxle/devserver/build.py +181 -0
  58. pyxle_framework-0.1.0/pyxle/devserver/builder.py +167 -0
  59. pyxle_framework-0.1.0/pyxle/devserver/client_files.py +2078 -0
  60. pyxle_framework-0.1.0/pyxle/devserver/csrf.py +160 -0
  61. pyxle_framework-0.1.0/pyxle/devserver/error_pages.py +139 -0
  62. pyxle_framework-0.1.0/pyxle/devserver/layouts.py +295 -0
  63. pyxle_framework-0.1.0/pyxle/devserver/middleware.py +74 -0
  64. pyxle_framework-0.1.0/pyxle/devserver/overlay.py +105 -0
  65. pyxle_framework-0.1.0/pyxle/devserver/path_utils.py +15 -0
  66. pyxle_framework-0.1.0/pyxle/devserver/proxy.py +157 -0
  67. pyxle_framework-0.1.0/pyxle/devserver/registry.py +381 -0
  68. pyxle_framework-0.1.0/pyxle/devserver/route_hooks.py +226 -0
  69. pyxle_framework-0.1.0/pyxle/devserver/routes.py +245 -0
  70. pyxle_framework-0.1.0/pyxle/devserver/scanner.py +102 -0
  71. pyxle_framework-0.1.0/pyxle/devserver/scripts.py +159 -0
  72. pyxle_framework-0.1.0/pyxle/devserver/settings.py +150 -0
  73. pyxle_framework-0.1.0/pyxle/devserver/starlette_app.py +658 -0
  74. pyxle_framework-0.1.0/pyxle/devserver/styles.py +182 -0
  75. pyxle_framework-0.1.0/pyxle/devserver/tailwind.py +269 -0
  76. pyxle_framework-0.1.0/pyxle/devserver/vite.py +374 -0
  77. pyxle_framework-0.1.0/pyxle/devserver/watcher.py +352 -0
  78. pyxle_framework-0.1.0/pyxle/env.py +224 -0
  79. pyxle_framework-0.1.0/pyxle/routing/__init__.py +13 -0
  80. pyxle_framework-0.1.0/pyxle/routing/paths.py +137 -0
  81. pyxle_framework-0.1.0/pyxle/runtime/ClientOnly.jsx +46 -0
  82. pyxle_framework-0.1.0/pyxle/runtime/Head.jsx +41 -0
  83. pyxle_framework-0.1.0/pyxle/runtime/Image.jsx +86 -0
  84. pyxle_framework-0.1.0/pyxle/runtime/Script.jsx +39 -0
  85. pyxle_framework-0.1.0/pyxle/runtime.py +83 -0
  86. pyxle_framework-0.1.0/pyxle/ssr/__init__.py +49 -0
  87. pyxle_framework-0.1.0/pyxle/ssr/head_merger.py +368 -0
  88. pyxle_framework-0.1.0/pyxle/ssr/render_component.mjs +256 -0
  89. pyxle_framework-0.1.0/pyxle/ssr/renderer.py +311 -0
  90. pyxle_framework-0.1.0/pyxle/ssr/ssr_worker.mjs +297 -0
  91. pyxle_framework-0.1.0/pyxle/ssr/template.py +399 -0
  92. pyxle_framework-0.1.0/pyxle/ssr/view.py +691 -0
  93. pyxle_framework-0.1.0/pyxle/ssr/worker_pool.py +285 -0
  94. pyxle_framework-0.1.0/pyxle/templates/__init__.py +1 -0
  95. pyxle_framework-0.1.0/pyxle/templates/scaffold/.gitignore +25 -0
  96. pyxle_framework-0.1.0/pyxle/templates/scaffold/__init__.py +1 -0
  97. pyxle_framework-0.1.0/pyxle/templates/scaffold/package.json +26 -0
  98. pyxle_framework-0.1.0/pyxle/templates/scaffold/pages/api/pulse.py +59 -0
  99. pyxle_framework-0.1.0/pyxle/templates/scaffold/pages/index.pyx +345 -0
  100. pyxle_framework-0.1.0/pyxle/templates/scaffold/pages/layout.pyx +8 -0
  101. pyxle_framework-0.1.0/pyxle/templates/scaffold/pages/styles/tailwind.css +9 -0
  102. pyxle_framework-0.1.0/pyxle/templates/scaffold/postcss.config.cjs +6 -0
  103. pyxle_framework-0.1.0/pyxle/templates/scaffold/public/branding/pyxle-grid.svg +15 -0
  104. pyxle_framework-0.1.0/pyxle/templates/scaffold/public/branding/pyxle-mark.svg +14 -0
  105. pyxle_framework-0.1.0/pyxle/templates/scaffold/public/branding/pyxle-wordmark-dark.svg +5 -0
  106. pyxle_framework-0.1.0/pyxle/templates/scaffold/public/branding/pyxle-wordmark-light.svg +5 -0
  107. pyxle_framework-0.1.0/pyxle/templates/scaffold/public/styles/tailwind.css +1 -0
  108. pyxle_framework-0.1.0/pyxle/templates/scaffold/pyxle.config.json +3 -0
  109. pyxle_framework-0.1.0/pyxle/templates/scaffold/requirements.txt +3 -0
  110. pyxle_framework-0.1.0/pyxle/templates/scaffold/tailwind.config.cjs +19 -0
  111. pyxle_framework-0.1.0/tests/cli/test_commands.py +1602 -0
  112. pyxle_framework-0.1.0/tests/cli/test_logger.py +219 -0
  113. pyxle_framework-0.1.0/tests/cli/test_scaffold.py +51 -0
  114. pyxle_framework-0.1.0/tests/cli/test_templates.py +44 -0
  115. pyxle_framework-0.1.0/tests/compiler/test_action_compile.py +140 -0
  116. pyxle_framework-0.1.0/tests/compiler/test_action_model.py +65 -0
  117. pyxle_framework-0.1.0/tests/compiler/test_action_parser.py +269 -0
  118. pyxle_framework-0.1.0/tests/compiler/test_action_writers.py +145 -0
  119. pyxle_framework-0.1.0/tests/compiler/test_compile.py +487 -0
  120. pyxle_framework-0.1.0/tests/compiler/test_head_jsx.py +298 -0
  121. pyxle_framework-0.1.0/tests/compiler/test_jsx_imports.py +237 -0
  122. pyxle_framework-0.1.0/tests/compiler/test_parser.py +821 -0
  123. pyxle_framework-0.1.0/tests/compiler/test_parser_hardening.py +683 -0
  124. pyxle_framework-0.1.0/tests/compiler/test_script_image_detection.py +195 -0
  125. pyxle_framework-0.1.0/tests/compiler/test_script_image_integration.py +170 -0
  126. pyxle_framework-0.1.0/tests/devserver/sample_middlewares.py +96 -0
  127. pyxle_framework-0.1.0/tests/devserver/test_action_routes.py +448 -0
  128. pyxle_framework-0.1.0/tests/devserver/test_build.py +133 -0
  129. pyxle_framework-0.1.0/tests/devserver/test_builder.py +213 -0
  130. pyxle_framework-0.1.0/tests/devserver/test_client_files.py +232 -0
  131. pyxle_framework-0.1.0/tests/devserver/test_client_only.py +73 -0
  132. pyxle_framework-0.1.0/tests/devserver/test_csrf.py +156 -0
  133. pyxle_framework-0.1.0/tests/devserver/test_devserver_start.py +839 -0
  134. pyxle_framework-0.1.0/tests/devserver/test_error_pages.py +259 -0
  135. pyxle_framework-0.1.0/tests/devserver/test_layouts.py +108 -0
  136. pyxle_framework-0.1.0/tests/devserver/test_middleware.py +41 -0
  137. pyxle_framework-0.1.0/tests/devserver/test_overlay.py +104 -0
  138. pyxle_framework-0.1.0/tests/devserver/test_proxy.py +189 -0
  139. pyxle_framework-0.1.0/tests/devserver/test_registry.py +280 -0
  140. pyxle_framework-0.1.0/tests/devserver/test_route_error_boundary.py +140 -0
  141. pyxle_framework-0.1.0/tests/devserver/test_route_hooks.py +112 -0
  142. pyxle_framework-0.1.0/tests/devserver/test_routes.py +173 -0
  143. pyxle_framework-0.1.0/tests/devserver/test_scanner.py +107 -0
  144. pyxle_framework-0.1.0/tests/devserver/test_scripts.py +132 -0
  145. pyxle_framework-0.1.0/tests/devserver/test_settings.py +223 -0
  146. pyxle_framework-0.1.0/tests/devserver/test_starlette_app.py +628 -0
  147. pyxle_framework-0.1.0/tests/devserver/test_styles.py +151 -0
  148. pyxle_framework-0.1.0/tests/devserver/test_tailwind.py +467 -0
  149. pyxle_framework-0.1.0/tests/devserver/test_vite.py +671 -0
  150. pyxle_framework-0.1.0/tests/devserver/test_watcher.py +565 -0
  151. pyxle_framework-0.1.0/tests/ssr/test_dynamic_head.py +23 -0
  152. pyxle_framework-0.1.0/tests/ssr/test_head_merger_extra.py +404 -0
  153. pyxle_framework-0.1.0/tests/ssr/test_head_merging.py +389 -0
  154. pyxle_framework-0.1.0/tests/ssr/test_integration.py +103 -0
  155. pyxle_framework-0.1.0/tests/ssr/test_renderer.py +399 -0
  156. pyxle_framework-0.1.0/tests/ssr/test_script_injection.py +212 -0
  157. pyxle_framework-0.1.0/tests/ssr/test_template.py +344 -0
  158. pyxle_framework-0.1.0/tests/ssr/test_view.py +1159 -0
  159. pyxle_framework-0.1.0/tests/ssr/test_view_error_boundaries.py +262 -0
  160. pyxle_framework-0.1.0/tests/ssr/test_worker_pool.py +868 -0
  161. pyxle_framework-0.1.0/tests/ssr/utils.py +99 -0
  162. pyxle_framework-0.1.0/tests/test_config.py +316 -0
  163. pyxle_framework-0.1.0/tests/test_config_security.py +225 -0
  164. pyxle_framework-0.1.0/tests/test_env.py +337 -0
  165. pyxle_framework-0.1.0/tests/test_runtime.py +92 -0
  166. pyxle_framework-0.1.0/tests/test_runtime_errors.py +76 -0
@@ -0,0 +1,19 @@
1
+ <svg width="180" height="48" viewBox="0 0 180 48" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="pyxle-mark-a" x1="8" y1="5" x2="40" y2="43" gradientUnits="userSpaceOnUse">
4
+ <stop offset="0" stop-color="#6ee7b7" />
5
+ <stop offset="0.5" stop-color="#34d399" />
6
+ <stop offset="1" stop-color="#059669" />
7
+ </linearGradient>
8
+ </defs>
9
+ <path
10
+ d="M14 40 V8 H28 Q38 8 38 18 Q38 28 28 28 H14"
11
+ stroke="url(#pyxle-mark-a)"
12
+ stroke-width="3.5"
13
+ stroke-linecap="round"
14
+ stroke-linejoin="round"
15
+ fill="none"
16
+ />
17
+ <circle cx="28" cy="18" r="2.8" fill="#6ee7b7" />
18
+ <text x="52" y="34" font-family="system-ui, -apple-system, 'Segoe UI', sans-serif" font-weight="700" font-size="30" fill="#6ee7b7" letter-spacing="0.01em">Pyxle</text>
19
+ </svg>
@@ -0,0 +1,58 @@
1
+ # Pyxle build artifacts
2
+ .pyxle-node-cache/
3
+ .pyxle-build/
4
+ .pyxle/.lang-virtual/
5
+
6
+ # Node
7
+ node_modules/
8
+
9
+ # Python bytecode
10
+ __pycache__/
11
+ *.py[codz]
12
+ *$py.class
13
+
14
+ # Distribution / packaging
15
+ build/
16
+ !docs/build/
17
+ dist/
18
+ *.egg-info/
19
+ *.egg
20
+ .eggs/
21
+
22
+ # Virtual environments
23
+ venv/
24
+ .venv/
25
+
26
+ # Test / coverage
27
+ htmlcov/
28
+ .tox/
29
+ .nox/
30
+ .coverage
31
+ .coverage.*
32
+ .pytest_cache/
33
+ coverage.xml
34
+ *.cover
35
+ *.py.cover
36
+
37
+ # IDE
38
+ .idea/
39
+ .vscode/
40
+ *.swp
41
+ *.swo
42
+ *~
43
+
44
+ # OS
45
+ .DS_Store
46
+ Thumbs.db
47
+
48
+ # Logs
49
+ *.log
50
+
51
+ # Environment
52
+ .env
53
+ .env.*
54
+ !.env.example
55
+
56
+ # Internal docs (kept locally, not published)
57
+ PYXLE_AUDIT.md
58
+ ROADMAP.md
@@ -0,0 +1,386 @@
1
+ # CLAUDE.md — Pyxle Framework Development Guide
2
+
3
+ This file instructs Claude (and any AI agent) on how to work on the Pyxle core framework.
4
+ Every rule here exists to keep Pyxle enterprise-grade, stable, and maintainable.
5
+
6
+ ## Related Repositories
7
+
8
+ Pyxle is split across multiple repos. This is the **core framework**. Related repos:
9
+ - `pyxle-langkit` — LSP server, linter, and VS Code extension (depends on this repo)
10
+ - `pyxle-plugins` — Official plugins (auth, etc.) — each plugin depends on this repo
11
+ - `pyxle-dev` — Private repo for the pyxle.dev website (a Pyxle app) (May not be available to external contributors)
12
+
13
+ ---
14
+
15
+ ## Project Overview
16
+
17
+ Pyxle is a Python-first full-stack web framework. `.pyx` files colocate Python server
18
+ logic (`@server` loaders, `@action` mutations) with React/JSX components. The stack is
19
+ Starlette (ASGI), Vite (bundling), React 18 (rendering), and esbuild (SSR transpilation).
20
+
21
+ **Key files to read first:**
22
+ - `ROADMAP.md` — current phase, pending tasks, design principles
23
+ - `PYXLE_AUDIT.md` — architectural strengths, risks, and bottlenecks
24
+ - `pyproject.toml` — dependencies, test config, coverage thresholds
25
+ - `pyxle/runtime.py` — the `@server` and `@action` decorator contracts
26
+ - `pyxle/compiler/parser.py` — the `.pyx` parser (most complex module)
27
+ - `pyxle/devserver/starlette_app.py` — request routing and middleware stack
28
+ - `pyxle/ssr/renderer.py` — SSR rendering pipeline (performance-critical)
29
+
30
+ ---
31
+
32
+ ## Mandatory Rules
33
+
34
+ ### 1. Run Tests After Every Change
35
+
36
+ **This is non-negotiable.** Every code change must be followed by running the test suite.
37
+
38
+ ```bash
39
+ # Run the full test suite
40
+ pytest
41
+
42
+ # The above command uses pyproject.toml defaults:
43
+ # --strict-markers --strict-config
44
+ # --cov=pyxle.cli --cov=pyxle.compiler --cov=pyxle.devserver --cov=pyxle.ssr
45
+ # --cov-report=term-missing
46
+ ```
47
+
48
+ - **Coverage threshold is 95%.** The build fails below this. Do not lower it.
49
+ - **All tests must pass.** Zero test failures are acceptable.
50
+ - **If you break a test, fix it before moving on.** Do not leave failing tests for later.
51
+ - **If you add a feature, add tests for it** in the same change. No feature ships without tests.
52
+
53
+ ### 2. Write Tests First When Possible
54
+
55
+ Prefer test-driven development:
56
+ 1. Write a failing test that describes the expected behavior
57
+ 2. Implement the minimum code to make it pass
58
+ 3. Refactor while keeping tests green
59
+
60
+ ### 3. Never Skip or Weaken Tests
61
+
62
+ - DO NOT add `@pytest.mark.skip`, `pytest.mark.xfail`, or `# pragma: no cover` to dodge coverage
63
+ - DO NOT delete tests to make the suite pass
64
+ - DO NOT lower `fail_under = 95` in `pyproject.toml`
65
+ - DO NOT remove modules from the `--cov=` list
66
+
67
+ ### 4. Test File Location Convention
68
+
69
+ Tests mirror the source tree:
70
+ ```
71
+ pyxle/cli/ -> tests/cli/
72
+ pyxle/compiler/ -> tests/compiler/
73
+ pyxle/devserver/ -> tests/devserver/
74
+ pyxle/ssr/ -> tests/ssr/
75
+ pyxle/build/ -> tests/build/
76
+ pyxle/config.py -> tests/test_config.py
77
+ ```
78
+
79
+ When creating a new module at `pyxle/foo/bar.py`, create `tests/foo/test_bar.py`.
80
+
81
+ ---
82
+
83
+ ## Architecture Rules
84
+
85
+ ### 5. Respect Module Boundaries
86
+
87
+ The codebase has clear separation of concerns:
88
+
89
+ | Module | Responsibility | May Import From |
90
+ |--------|---------------|-----------------|
91
+ | `pyxle/cli/` | CLI commands, user-facing I/O | Everything below |
92
+ | `pyxle/devserver/` | Dev server, Vite proxy, file watcher | compiler, ssr, routing, config |
93
+ | `pyxle/ssr/` | Server-side rendering, head merging | compiler (models only), config |
94
+ | `pyxle/compiler/` | `.pyx` parsing, code generation | Nothing from pyxle (standalone) |
95
+ | `pyxle/routing/` | File-based route calculation | Nothing from pyxle (standalone) |
96
+ | `pyxle/build/` | Production build pipeline | compiler, devserver, config |
97
+ | `pyxle/config.py` | Configuration parsing | Nothing from pyxle (standalone) |
98
+ | `pyxle/runtime.py` | `@server`, `@action` decorators | Nothing from pyxle (standalone) |
99
+ | `pyxle/client/` | Client-side JS/JSX components | N/A (not Python -- JS only) |
100
+
101
+ **DO NOT** introduce circular imports. **DO NOT** have `compiler` depend on `devserver`.
102
+ **DO NOT** have `runtime.py` import anything from the framework -- it must stay zero-dependency
103
+ because it's injected into user code.
104
+
105
+ ### 6. Frozen Dataclasses Everywhere
106
+
107
+ All data-carrying classes must be frozen dataclasses:
108
+
109
+ ```python
110
+ # CORRECT
111
+ @dataclass(frozen=True)
112
+ class PageRoute:
113
+ path: str
114
+ module_key: str
115
+ has_loader: bool
116
+
117
+ # WRONG -- mutable state causes bugs in async code
118
+ @dataclass
119
+ class PageRoute:
120
+ path: str
121
+ module_key: str
122
+ has_loader: bool
123
+ ```
124
+
125
+ Use `slots=True` for internal-only dataclasses that benefit from memory efficiency.
126
+
127
+ ### 7. Use `Sequence` and `tuple` for Immutable Collections
128
+
129
+ ```python
130
+ # CORRECT -- signals immutability
131
+ def process_routes(routes: Sequence[PageRoute]) -> tuple[str, ...]: ...
132
+
133
+ # WRONG -- signals mutability
134
+ def process_routes(routes: list[PageRoute]) -> list[str]: ...
135
+ ```
136
+
137
+ Store collection fields as `tuple`, not `list`, in frozen dataclasses.
138
+
139
+ ### 8. Async by Default
140
+
141
+ All I/O operations must be async. Never block the event loop.
142
+
143
+ If wrapping a synchronous call (like `subprocess.run`), use `asyncio.to_thread()`.
144
+
145
+ ### 9. Use Structured Error Types
146
+
147
+ Every error that a user or developer might see needs a specific exception class.
148
+ Error classes live in the module they belong to (e.g., `pyxle/compiler/exceptions.py`).
149
+ Error messages must be specific, actionable, and include context (file path, line number, etc.).
150
+
151
+ ### 10. No Magic, No Hidden Behavior
152
+
153
+ Decorators add metadata. They do NOT wrap, transform, or hide behavior.
154
+ The same principle applies to `@action` and any future decorators.
155
+
156
+ ---
157
+
158
+ ## Code Quality Rules
159
+
160
+ ### 11. Type Hints on All Public APIs
161
+
162
+ Every public function, method, and class must have complete type hints.
163
+ Internal helpers may omit return types if the logic is trivial, but parameters must always be typed.
164
+
165
+ ### 12. Docstrings on Public APIs
166
+
167
+ Every public function, class, and module needs a docstring. Keep them concise -- describe
168
+ *what* and *why*, not *how*.
169
+
170
+ ### 13. No Print Statements
171
+
172
+ Use the CLI logger (`pyxle/cli/logger.py`) for user-facing output. Use Python `logging`
173
+ module for internal diagnostics. Never use `print()`.
174
+
175
+ ### 14. Run Ruff Before Committing
176
+
177
+ ```bash
178
+ ruff check pyxle/ tests/
179
+ ```
180
+
181
+ Fix all lint errors. Do not add `# noqa` unless there's a documented reason.
182
+
183
+ ---
184
+
185
+ ## Performance Rules
186
+
187
+ ### 15. SSR is the Hot Path
188
+
189
+ `pyxle/ssr/` is the most performance-critical code. Every millisecond matters.
190
+
191
+ - **DO NOT** add synchronous I/O to the SSR request path
192
+ - **DO NOT** add new imports to modules loaded on every request
193
+ - **DO NOT** grow caches without eviction policies
194
+ - **DO** profile before and after any SSR change
195
+ - **DO** consider the cost at 100 concurrent requests, not just 1
196
+
197
+ ### 16. Lazy Imports for Heavy Modules
198
+
199
+ Modules that are only needed in specific code paths should be imported lazily.
200
+ This keeps CLI startup fast and avoids circular import issues.
201
+
202
+ ### 17. No Unbounded Caches
203
+
204
+ Every cache must have a max size or TTL. Document the eviction strategy.
205
+
206
+ ---
207
+
208
+ ## Security Rules
209
+
210
+ ### 18. Never Trust User Input
211
+
212
+ - Escape all dynamic content injected into HTML (especially HEAD elements)
213
+ - Validate file paths -- never allow path traversal (`../`)
214
+ - Use parameterized queries -- never string-interpolate SQL
215
+ - Sanitize route parameters
216
+ - Never expose stack traces, file paths, or internal state in production error responses
217
+
218
+ ### 19. Subprocess Safety
219
+
220
+ - Build command arrays programmatically -- never use `shell=True` with user input
221
+ - Set timeouts on all subprocess calls
222
+ - Capture stderr and handle errors
223
+ - Clean up temp files in `finally` blocks
224
+
225
+ ### 20. Secrets Stay Server-Side
226
+
227
+ - Environment variables without `PYXLE_PUBLIC_` prefix must NEVER appear in client bundles
228
+ - Loader and action return values are serialized to JSON and sent to the client -- never
229
+ include secrets, tokens, or internal IDs that shouldn't be exposed
230
+
231
+ ---
232
+
233
+ ## Development Workflow
234
+
235
+ ### 21. Branch and Change Management
236
+
237
+ - Read `ROADMAP.md` before starting work -- find the relevant phase and task
238
+ - Work on one task at a time -- complete it (including tests) before moving to the next
239
+ - Mark completed tasks in `ROADMAP.md` by changing `[ ]` to `[x]`
240
+ - Keep commits focused: one logical change per commit
241
+
242
+ ### 22. Adding a New Feature -- Checklist
243
+
244
+ Before writing code:
245
+ 1. Identify the relevant `ROADMAP.md` task
246
+ 2. Understand how it fits in the architecture (which modules are affected?)
247
+ 3. Check for existing patterns to follow (look at similar completed features)
248
+
249
+ While writing code:
250
+ 4. Add/update frozen dataclasses in the relevant `model.py`
251
+ 5. Implement the logic following module boundary rules
252
+ 6. Write tests in the matching `tests/` directory
253
+ 7. Run `pytest` -- all tests must pass, coverage must stay above 95%
254
+ 8. Run `ruff check` -- zero lint errors
255
+
256
+ After writing code:
257
+ 9. Mark the task as `[x]` in `ROADMAP.md`
258
+ 10. If you discovered new work needed, add it to the appropriate phase in `ROADMAP.md`
259
+
260
+ ### 23. Commit Instructions
261
+
262
+ Follow Conventional Commits: `feat`, `fix`, `refactor`, `test`, `chore`, `docs`.
263
+ Scope is the primary module changed: `compiler`, `devserver`, `ssr`, `cli`, `runtime`,
264
+ `client`, `build`, `routing`, `tests`, `scaffold`.
265
+
266
+ ### 24. Modifying the Compiler or Parser
267
+
268
+ The parser (`pyxle/compiler/parser.py`) is the most sensitive code. Changes here can
269
+ break every `.pyx` file in existence.
270
+
271
+ - **Always** add regression tests for the specific input pattern you're handling
272
+ - **Never** remove an existing test
273
+ - **Test edge cases**: empty files, files with only Python, files with only JSX,
274
+ multiline strings, nested brackets, decorator chains, comments that look like code
275
+ - After changes, run the full compiler test suite AND manually compile the scaffold
276
+ templates to verify they still work
277
+
278
+ ### 25. Modifying the SSR Pipeline
279
+
280
+ Changes to `pyxle/ssr/` affect every page render.
281
+
282
+ - **Benchmark** before and after: measure render time for simple and complex pages
283
+ - **Test error paths**: loader failure, render failure, head evaluation failure
284
+ - **Test with missing data**: what happens when a loader returns `None`? Empty dict?
285
+ - **Verify the error overlay** still receives correct breadcrumbs after your change
286
+
287
+ ---
288
+
289
+ ## Testing Patterns
290
+
291
+ ### 26. Use Fixtures, Not Setup Methods
292
+
293
+ ### 27. Use Parametrize for Variant Testing
294
+
295
+ ### 28. Mock External Dependencies
296
+
297
+ Node.js, npm, Vite, and file system operations should be mocked in unit tests.
298
+ Use `tmp_path` for any test that creates files. Never write to the real filesystem.
299
+
300
+ ### 29. Test Error Messages, Not Just Error Types
301
+
302
+ ---
303
+
304
+ ## DO NOT List
305
+
306
+ - **DO NOT** lower the coverage threshold below 95%
307
+ - **DO NOT** skip or delete tests to make the suite pass
308
+ - **DO NOT** add `print()` statements (use logger or `logging`)
309
+ - **DO NOT** introduce circular imports between modules
310
+ - **DO NOT** make `runtime.py` import anything from the framework
311
+ - **DO NOT** use mutable dataclasses for data-carrying types
312
+ - **DO NOT** block the async event loop with synchronous I/O
313
+ - **DO NOT** grow caches without eviction policies
314
+ - **DO NOT** use `shell=True` in subprocess calls
315
+ - **DO NOT** expose internal error details in production responses
316
+ - **DO NOT** hardcode host/port/path values (use config or env vars)
317
+ - **DO NOT** commit `.env` files, secrets, or credentials
318
+ - **DO NOT** add dependencies to `pyproject.toml` without explicit need and version pinning
319
+ - **DO NOT** break backward compatibility without updating `ROADMAP.md` migration notes
320
+ - **DO NOT** modify templates without verifying `pyxle init` + `pyxle dev` still works end-to-end
321
+ - **DO NOT** write framework code that only works on macOS/Linux -- support Windows paths
322
+
323
+ ---
324
+
325
+ ## Quick Reference
326
+
327
+ ### Running Tests
328
+ ```bash
329
+ pytest # Full suite with coverage
330
+ pytest tests/compiler/ # Just compiler tests
331
+ pytest -x # Stop on first failure
332
+ pytest -k "test_parser" # Run tests matching pattern
333
+ pytest --no-cov # Skip coverage (faster for iteration)
334
+ ```
335
+
336
+ ### Linting
337
+ ```bash
338
+ ruff check pyxle/ tests/
339
+ ```
340
+
341
+ ### Key Paths
342
+ ```
343
+ pyxle/ # Framework source
344
+ |-- cli/ # CLI commands (Typer)
345
+ |-- compiler/ # .pyx -> .py + .jsx compiler
346
+ | |-- parser.py # State-machine parser (most complex)
347
+ | |-- writers.py # Server/client code emission
348
+ | |-- model.py # Compilation data models
349
+ | |-- jsx_parser.py # Babel-based JSX validation
350
+ | +-- jsx_imports.py # Import specifier rewriter
351
+ |-- devserver/ # Development server
352
+ | |-- starlette_app.py # ASGI app assembly
353
+ | |-- vite.py # Vite subprocess management
354
+ | |-- builder.py # Incremental build orchestration
355
+ | |-- proxy.py # Vite asset proxy
356
+ | |-- routes.py # Route descriptors
357
+ | |-- registry.py # Page metadata registry
358
+ | |-- middleware.py # Middleware loading
359
+ | |-- layouts.py # Layout/template composition
360
+ | |-- scanner.py # Source file discovery
361
+ | +-- overlay.py # WebSocket error overlay
362
+ |-- ssr/ # Server-side rendering
363
+ | |-- renderer.py # Component render orchestration
364
+ | |-- render_component.mjs # Node.js SSR runtime (esbuild + React)
365
+ | |-- view.py # Page response building
366
+ | |-- head_merger.py # Head element deduplication
367
+ | +-- template.py # HTML document assembly
368
+ |-- build/ # Production build pipeline
369
+ |-- routing/ # File-based route calculation
370
+ |-- client/ # Client-side JS components (not Python)
371
+ |-- config.py # Configuration parsing + validation
372
+ |-- runtime.py # @server, @action decorators (zero deps)
373
+ +-- templates/scaffold/ # pyxle init project template
374
+
375
+ tests/ # Mirrors pyxle/ structure
376
+ docs/ # Framework documentation
377
+ ```
378
+
379
+ ### Design Principles (from ROADMAP.md)
380
+ 1. **Python-first, not Python-only** -- great Python AND great React
381
+ 2. **Convention over configuration** -- zero config for common cases
382
+ 3. **Compiler-driven** -- extract metadata at build time, not runtime
383
+ 4. **No magic** -- decorators add metadata, not hidden behavior
384
+ 5. **Progressive disclosure** -- simple things simple, complex things possible
385
+ 6. **Batteries includable** -- ship hooks and integration points, not opinions
386
+ 7. **AI-first DX** -- predictable patterns, strong types, clear errors
@@ -0,0 +1,15 @@
1
+ .PHONY: install test lint clean
2
+
3
+ install:
4
+ pip install -e .[dev]
5
+
6
+ test:
7
+ pytest
8
+
9
+ lint:
10
+ ruff check pyxle/ tests/
11
+
12
+ clean:
13
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
14
+ find . -type d -name .pytest_cache -exec rm -rf {} + 2>/dev/null || true
15
+ rm -rf .coverage htmlcov/ dist/ *.egg-info/
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyxle-framework
3
+ Version: 0.1.0
4
+ Summary: Python-first full-stack framework with an intelligent CLI.
5
+ Project-URL: Homepage, https://pyxle.dev
6
+ Project-URL: Repository, https://github.com/shivamsn97/pyxle
7
+ Project-URL: Documentation, https://github.com/shivamsn97/pyxle/tree/main/docs
8
+ Project-URL: Bug Tracker, https://github.com/shivamsn97/pyxle/issues
9
+ Project-URL: PyPI, https://pypi.org/project/pyxle-framework/
10
+ Author-email: Shivam Saini <hello@pyxle.dev>
11
+ License: MIT
12
+ Keywords: full-stack,python,react,ssr,web framework
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Framework :: AsyncIO
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
23
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: httpx<0.28,>=0.27
27
+ Requires-Dist: starlette<0.38,>=0.37
28
+ Requires-Dist: typer>=0.12
29
+ Requires-Dist: uvicorn[standard]<1.0,>=0.29
30
+ Requires-Dist: watchdog<5.0,>=4.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: coverage<8.0,>=7.4; extra == 'dev'
33
+ Requires-Dist: pytest-cov<5.0,>=4.1; extra == 'dev'
34
+ Requires-Dist: pytest<9.0,>=8.0; extra == 'dev'
35
+ Requires-Dist: ruff<0.7,>=0.6; extra == 'dev'
36
+ Description-Content-Type: text/markdown
37
+
38
+ <p align="center">
39
+ <br />
40
+ <a href="https://pyxle.dev">
41
+ <img src=".github/pyxle-logo.svg" alt="Pyxle" height="52" />
42
+ </a>
43
+ <br />
44
+ <br />
45
+ <strong>The Python full-stack framework.</strong>
46
+ <br />
47
+ Server logic in Python. UI in React. One file.
48
+ <br />
49
+ <br />
50
+ <a href="https://pypi.org/project/pyxle-framework/"><img src="https://img.shields.io/pypi/v/pyxle-framework?color=22c55e&labelColor=0a0a0b&label=pypi" alt="PyPI" /></a>
51
+ &nbsp;
52
+ <a href="https://pyxle.dev"><img src="https://img.shields.io/badge/pyxle.dev-0a0a0b?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij48Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNiIgZmlsbD0iIzIyYzU1ZSIvPjwvc3ZnPg==&label=" alt="Website" /></a>
53
+ </p>
54
+
55
+ ---
56
+
57
+ ```python
58
+ # pages/index.pyx
59
+
60
+ @server
61
+ async def load(request):
62
+ return {"message": "Hello from Python"}
63
+
64
+ # --- JSX ---
65
+ export default function Home({ data }) {
66
+ return <h1>{data.message}</h1>;
67
+ }
68
+ ```
69
+
70
+ Pyxle compiles `.pyx` files into Python server modules and React client components.
71
+ `@server` loaders run on the backend, SSR renders the HTML, React hydrates on the client.
72
+
73
+ ## Get started
74
+
75
+ ```bash
76
+ pip install pyxle-framework
77
+ pyxle init my-app && cd my-app
78
+ pyxle install
79
+ pyxle dev
80
+ ```
81
+
82
+ Open **http://localhost:8000**.
83
+
84
+ ## Features
85
+
86
+ **`.pyx` files** -- Python + React in a single file, split at compile time
87
+ **File-based routing** -- `pages/` maps to URLs, dynamic segments with `[param].pyx`
88
+ **SSR** -- Server-side rendering via esbuild + React 18
89
+ **`@server` / `@action`** -- Typed data loading and form mutations
90
+ **Layouts** -- Nested layouts and templates with slot composition
91
+ **Vite HMR** -- Fast refresh in development
92
+ **Tailwind** -- Pre-configured out of the box
93
+ **Production build** -- `pyxle build` + `pyxle serve` for deployment
94
+
95
+ ## Documentation
96
+
97
+ Full docs are in the [`docs/`](docs/README.md) directory:
98
+
99
+ - [Quick Start](docs/getting-started/quick-start.md)
100
+ - [`.pyx` Files](docs/core-concepts/pyx-files.md)
101
+ - [Routing](docs/core-concepts/routing.md)
102
+ - [Data Loading](docs/core-concepts/data-loading.md)
103
+ - [Server Actions](docs/core-concepts/server-actions.md)
104
+ - [Layouts](docs/core-concepts/layouts.md)
105
+ - [Deployment](docs/guides/deployment.md)
106
+ - [CLI Reference](docs/reference/cli.md)
107
+ - [Configuration](docs/reference/configuration.md)
108
+
109
+ ## CLI
110
+
111
+ ```
112
+ pyxle init <name> Scaffold a new project
113
+ pyxle install Install Python + Node dependencies
114
+ pyxle dev Development server with HMR
115
+ pyxle build Production build
116
+ pyxle serve Serve the production build
117
+ ```
118
+
119
+ ## Requirements
120
+
121
+ Python 3.10+ and Node.js 18+.
122
+
123
+ ## Contributing
124
+
125
+ ```bash
126
+ git clone https://github.com/shivamsn97/pyxle.git
127
+ cd pyxle
128
+ pip install -e ".[dev]"
129
+ pytest
130
+ ```
131
+
132
+ ## Links
133
+
134
+ - [pyxle.dev](https://pyxle.dev)
135
+ - [PyPI](https://pypi.org/project/pyxle-framework/)
136
+ - [Issues](https://github.com/shivamsn97/pyxle/issues)