nextpy-framework 2.4.4__tar.gz → 2.4.6__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 (77) hide show
  1. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/cli.py +135 -110
  2. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/component_router.py +23 -15
  3. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/router.py +23 -15
  4. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/server/app.py +52 -13
  5. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6/.nextpy_framework/nextpy_framework.egg-info}/PKG-INFO +1 -1
  6. {nextpy_framework-2.4.4/.nextpy_framework/nextpy_framework.egg-info → nextpy_framework-2.4.6}/PKG-INFO +1 -1
  7. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/pyproject.toml +1 -1
  8. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/__init__.py +0 -0
  9. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/auth.py +0 -0
  10. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/builder.py +0 -0
  11. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/__init__.py +0 -0
  12. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/debug/AutoDebug.py +0 -0
  13. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/debug/DebugIcon.py +0 -0
  14. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/debug/DebugIconFixed.py +0 -0
  15. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/feedback.py +0 -0
  16. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/form.py +0 -0
  17. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/head.py +0 -0
  18. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/hooks_provider.py +0 -0
  19. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/image.py +0 -0
  20. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/layout.py +0 -0
  21. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/link.py +0 -0
  22. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/loader.py +0 -0
  23. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/navigation.py +0 -0
  24. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/toast.py +0 -0
  25. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/ui.py +0 -0
  26. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components/visual.py +0 -0
  27. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/components.py +0 -0
  28. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/config.py +0 -0
  29. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/__init__.py +0 -0
  30. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/builder.py +0 -0
  31. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/component_renderer.py +0 -0
  32. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/data_fetching.py +0 -0
  33. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/demo_pages_simple.py +0 -0
  34. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/demo_router.py +0 -0
  35. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/renderer.py +0 -0
  36. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/core/sync.py +0 -0
  37. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/db.py +0 -0
  38. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/dev_server.py +0 -0
  39. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/dev_tools.py +0 -0
  40. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/errors.py +0 -0
  41. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/hooks.py +0 -0
  42. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/hooks_provider.py +0 -0
  43. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/hooks_provider_new.py +0 -0
  44. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/jsx.py +0 -0
  45. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/jsx_preprocessor.py +0 -0
  46. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/jsx_transformer.py +0 -0
  47. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/main.py +0 -0
  48. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/performance.py +0 -0
  49. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/plugins/__init__.py +0 -0
  50. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/plugins/base.py +0 -0
  51. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/plugins/builtin.py +0 -0
  52. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/plugins/config.py +0 -0
  53. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/plugins.py +0 -0
  54. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/py.typed +0 -0
  55. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/security.py +0 -0
  56. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/server/__init__.py +0 -0
  57. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/server/debug.py +0 -0
  58. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/server/middleware.py +0 -0
  59. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/true_jsx.py +0 -0
  60. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/__init__.py +0 -0
  61. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/cache.py +0 -0
  62. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/email.py +0 -0
  63. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/file_upload.py +0 -0
  64. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/logging.py +0 -0
  65. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/search.py +0 -0
  66. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/seo.py +0 -0
  67. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/utils/validators.py +0 -0
  68. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy/websocket.py +0 -0
  69. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy_framework.egg-info/SOURCES.txt +0 -0
  70. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy_framework.egg-info/dependency_links.txt +0 -0
  71. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy_framework.egg-info/entry_points.txt +0 -0
  72. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy_framework.egg-info/requires.txt +0 -0
  73. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/.nextpy_framework/nextpy_framework.egg-info/top_level.txt +0 -0
  74. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/LICENSE +0 -0
  75. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/README.md +0 -0
  76. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/setup.cfg +0 -0
  77. {nextpy_framework-2.4.4 → nextpy_framework-2.4.6}/tests/test_routing.py +0 -0
@@ -196,7 +196,7 @@ def _format_size(size_bytes: int) -> str:
196
196
  return f"{size:.1f} {size_names[i]}"
197
197
 
198
198
  @click.group()
199
- @click.version_option(version="1.0.0", prog_name="NextPy")
199
+ @click.version_option(version="2.4.4", prog_name="NextPy")
200
200
  def cli():
201
201
  """NextPy - A Python web framework inspired by Next.js"""
202
202
  pass
@@ -533,7 +533,7 @@ def version():
533
533
  click.echo(click.style("\n 📋 NextPy Framework Info", fg="cyan", bold=True))
534
534
  click.echo(click.style(" ===================\n", fg="cyan"))
535
535
 
536
- click.echo(f" 🏷️ Version: 2.4.3")
536
+ click.echo(f" 🏷️ Version: 2.4.6 ")
537
537
  click.echo(f" 🐍 Python: {sys.version.split()[0]}")
538
538
  click.echo(f" ⚡ Framework: NextPy")
539
539
  click.echo(f" 🎨 Architecture: True JSX")
@@ -561,7 +561,7 @@ def info():
561
561
 
562
562
  # Framework info
563
563
  click.echo(click.style(" 📦 Framework Details:", fg="blue", bold=True))
564
- click.echo(f" Version: 2.0.0")
564
+ click.echo(f" Version: 2.4.4")
565
565
  click.echo(f" Architecture: True JSX")
566
566
  click.echo(f" Python: {sys.version.split()[0]}")
567
567
 
@@ -878,6 +878,43 @@ def _create_project_structure(project_dir: Path):
878
878
  (project_dir / dir_path).mkdir(parents=True, exist_ok=True)
879
879
  click.echo(f" Created: {dir_path}/")
880
880
 
881
+ # Create essential templates
882
+ (project_dir / "templates" / "_page.html").write_text('''<!DOCTYPE html>
883
+ <html lang="en">
884
+ <head>
885
+ <meta charset="utf-8">
886
+ <meta name="viewport" content="width=device-width, initial-scale=1">
887
+ <title>{{ title or "NextPy App" }}</title>
888
+ <script src="https://cdn.tailwindcss.com"></script>
889
+ </head>
890
+ <body>
891
+ <div id="app">
892
+ {{ content }}
893
+ </div>
894
+ </body>
895
+ </html>''')
896
+ click.echo(" Created: templates/_page.html")
897
+
898
+ (project_dir / "templates" / "_404.html").write_text('''<!DOCTYPE html>
899
+ <html lang="en">
900
+ <head>
901
+ <meta charset="utf-8">
902
+ <meta name="viewport" content="width=device-width, initial-scale=1">
903
+ <title>404 - Page Not Found</title>
904
+ <script src="https://cdn.tailwindcss.com"></script>
905
+ </head>
906
+ <body class="min-h-screen bg-gray-100 flex items-center justify-center">
907
+ <div class="text-center">
908
+ <h1 class="text-6xl font-bold text-gray-900 mb-4">404</h1>
909
+ <p class="text-xl text-gray-600 mb-8">Page not found</p>
910
+ <a href="/" class="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
911
+ Go Home
912
+ </a>
913
+ </div>
914
+ </body>
915
+ </html>''')
916
+ click.echo(" Created: templates/_404.html")
917
+
881
918
  # Create styles.css with Tailwind directives
882
919
  (project_dir / "styles.css").write_text('''/* NextPy Styles */
883
920
  @tailwind base;
@@ -982,7 +1019,7 @@ body {
982
1019
  # Create postcss.config.js with new Tailwind plugin
983
1020
  (project_dir / "postcss.config.js").write_text('''module.exports = {
984
1021
  plugins: {
985
- '@tailwindcss/postcss': {},
1022
+ tailwindcss: {},
986
1023
  autoprefixer: {},
987
1024
  },
988
1025
  };''')
@@ -1005,11 +1042,8 @@ body {
1005
1042
  "devDependencies": {
1006
1043
  "autoprefixer": "^10.4.22",
1007
1044
  "postcss": "^8.5.6",
1008
- "tailwindcss": "^4.1.17"
1009
- },
1010
- "dependencies": {
1011
- "@tailwindcss/postcss": "^4.1.18",
1012
- "postcss-cli": "^11.0.1"
1045
+ "postcss-cli": "^11.0.1",
1046
+ "tailwindcss": "^3.4.1"
1013
1047
  }
1014
1048
  }''')
1015
1049
  click.echo(" Created: package.json")
@@ -1024,7 +1058,6 @@ def Home(props=None):
1024
1058
 
1025
1059
  return (
1026
1060
  <div className="min-h-screen bg-gradient-to-br from-blue-600 via-purple-600 to-pink-600">
1027
- {/* Navigation */}
1028
1061
  <nav className="bg-white border-b border-white bg-opacity-10 backdrop-blur-md border-opacity-20">
1029
1062
  <div className="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
1030
1063
  <div className="flex items-center justify-between h-16">
@@ -1046,7 +1079,6 @@ def Home(props=None):
1046
1079
  </div>
1047
1080
  </nav>
1048
1081
 
1049
- {/* Hero Section */}
1050
1082
  <div className="relative overflow-hidden">
1051
1083
  <div className="mx-auto max-w-7xl">
1052
1084
  <div className="relative z-10 pb-8 bg-transparent sm:pb-16 md:pb-20 lg:pb-28 xl:pb-32">
@@ -1072,7 +1104,6 @@ def Home(props=None):
1072
1104
  </div>
1073
1105
  </div>
1074
1106
 
1075
- {/* Background decoration */}
1076
1107
  <div className="absolute inset-0 -z-10">
1077
1108
  <div className="absolute top-0 transform -translate-x-1/2 left-1/2 blur-3xl opacity-20">
1078
1109
  <div className="rounded-full aspect-square w-96 h-96 bg-gradient-to-r from-blue-400 to-purple-600"></div>
@@ -1083,7 +1114,7 @@ def Home(props=None):
1083
1114
  </div>
1084
1115
  </div>
1085
1116
 
1086
- {/* Features Section */}
1117
+
1087
1118
  <div className="py-12 bg-white">
1088
1119
  <div className="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
1089
1120
  <div className="lg:text-center">
@@ -1097,10 +1128,10 @@ def Home(props=None):
1097
1128
 
1098
1129
  <div className="mt-10">
1099
1130
  <div className="space-y-10 md:space-y-0 md:grid md:grid-cols-2 md:gap-x-8 md:gap-y-10 lg:grid-cols-3">
1100
- {/* Feature 1 */}
1131
+
1101
1132
  <div className="relative">
1102
1133
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-blue-500 rounded-md">
1103
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1134
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1104
1135
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7m0 0v7l9-11h-7z" />
1105
1136
  </svg>
1106
1137
  </div>
@@ -1111,14 +1142,14 @@ def Home(props=None):
1111
1142
  Write React-like components directly in Python with full JSX support.
1112
1143
  </p>
1113
1144
  <a href="/jsx-demo" className="mt-4 ml-16 text-base font-medium text-blue-600 hover:text-blue-500">
1114
- Learn more
1145
+ Learn more &rarr;
1115
1146
  </a>
1116
1147
  </div>
1117
1148
 
1118
- {/* Feature 2 */}
1149
+
1119
1150
  <div className="relative">
1120
1151
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-purple-500 rounded-md">
1121
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1152
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1122
1153
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7" />
1123
1154
  </svg>
1124
1155
  </div>
@@ -1129,14 +1160,14 @@ def Home(props=None):
1129
1160
  Built-in Tailwind CSS v4 with PostCSS compilation and utility classes.
1130
1161
  </p>
1131
1162
  <a href="/tailwind-demo" className="mt-4 ml-16 text-base font-medium text-blue-600 hover:text-blue-500">
1132
- Learn more
1163
+ Learn more &rarr;
1133
1164
  </a>
1134
1165
  </div>
1135
1166
 
1136
- {/* Feature 3 */}
1167
+
1137
1168
  <div className="relative">
1138
1169
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-green-500 rounded-md">
1139
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1170
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1140
1171
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 2 9 9 0 0118 0z" />
1141
1172
  </svg>
1142
1173
  </div>
@@ -1147,7 +1178,7 @@ def Home(props=None):
1147
1178
  Automatic route discovery with support for dynamic routes and API endpoints.
1148
1179
  </p>
1149
1180
  <a href="/routing-demo" className="mt-4 ml-16 text-base font-medium text-blue-600 hover:text-blue-500">
1150
- Learn more
1181
+ Learn more &rarr;
1151
1182
  </a>
1152
1183
  </div>
1153
1184
  </div>
@@ -1155,7 +1186,7 @@ def Home(props=None):
1155
1186
  </div>
1156
1187
  </div>
1157
1188
 
1158
- {/* Interactive Demo Section */}
1189
+
1159
1190
  <div className="py-12 bg-gray-50">
1160
1191
  <div className="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
1161
1192
  <div className="text-center">
@@ -1168,7 +1199,7 @@ def Home(props=None):
1168
1199
  </div>
1169
1200
 
1170
1201
  <div className="grid grid-cols-1 gap-8 mt-12 sm:grid-cols-2 lg:grid-cols-3">
1171
- {/* Interactive Counter */}
1202
+
1172
1203
  <div className="p-6 bg-white rounded-lg shadow-lg">
1173
1204
  <h3 className="text-lg font-medium text-gray-900">Live Counter</h3>
1174
1205
  <p className="mt-2 text-sm text-gray-500">Interactive state management demo</p>
@@ -1180,7 +1211,7 @@ def Home(props=None):
1180
1211
  </div>
1181
1212
  </div>
1182
1213
 
1183
- {/* Form Demo */}
1214
+
1184
1215
  <div className="p-6 bg-white rounded-lg shadow-lg">
1185
1216
  <h3 className="text-lg font-medium text-gray-900">Form Handling</h3>
1186
1217
  <p className="mt-2 text-sm text-gray-500">Server-side form processing</p>
@@ -1192,7 +1223,7 @@ def Home(props=None):
1192
1223
  </div>
1193
1224
  </div>
1194
1225
 
1195
- {/* API Demo */}
1226
+
1196
1227
  <div className="p-6 bg-white rounded-lg shadow-lg">
1197
1228
  <h3 className="text-lg font-medium text-gray-900">API Integration</h3>
1198
1229
  <p className="mt-2 text-sm text-gray-500">RESTful API endpoints</p>
@@ -1207,12 +1238,12 @@ def Home(props=None):
1207
1238
  </div>
1208
1239
  </div>
1209
1240
 
1210
- {/* Footer */}
1241
+
1211
1242
  <footer className="bg-gray-900">
1212
1243
  <div className="px-4 py-12 mx-auto max-w-7xl sm:px-6 lg:px-8">
1213
1244
  <div className="flex flex-col items-center space-y-4">
1214
1245
  <p className="text-base text-center text-gray-400">
1215
- Built with ❤️ using NextPy Framework
1246
+ Built with &hearts; using NextPy Framework
1216
1247
  </p>
1217
1248
  <div className="flex space-x-6">
1218
1249
  <a href="/about" className="text-gray-400 hover:text-gray-300">About</a>
@@ -1249,8 +1280,7 @@ def About(props=None):
1249
1280
 
1250
1281
  return (
1251
1282
  <div className="min-h-screen bg-gray-50">
1252
- {/* Hero Section */}
1253
- <div className="text-white bg-gradient-to-r from-blue-600 to-purple-600">
1283
+ <div className="text-white bg-gradient-to-r from-blue-600 to-purple-600">
1254
1284
  <div className="px-4 py-16 mx-auto max-w-7xl sm:py-24 sm:px-6 lg:px-8">
1255
1285
  <div className="text-center">
1256
1286
  <h1 className="text-4xl font-extrabold tracking-tight sm:text-5xl lg:text-6xl">
@@ -1271,7 +1301,7 @@ def About(props=None):
1271
1301
  </div>
1272
1302
  </div>
1273
1303
 
1274
- {/* Features Grid */}
1304
+
1275
1305
  <div className="py-12 bg-white">
1276
1306
  <div className="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
1277
1307
  <div className="lg:text-center">
@@ -1285,10 +1315,10 @@ def About(props=None):
1285
1315
 
1286
1316
  <div className="mt-10">
1287
1317
  <div className="gap-8 space-y-10 md:space-y-0 md:grid md:grid-cols-2 lg:grid-cols-3">
1288
- {/* Feature 1 */}
1318
+
1289
1319
  <div className="relative">
1290
1320
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-blue-500 rounded-md">
1291
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1321
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1292
1322
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7m0 0v7l9-11h-7z" />
1293
1323
  </svg>
1294
1324
  </div>
@@ -1298,10 +1328,10 @@ def About(props=None):
1298
1328
  </p>
1299
1329
  </div>
1300
1330
 
1301
- {/* Feature 2 */}
1331
+
1302
1332
  <div className="relative">
1303
1333
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-purple-500 rounded-md">
1304
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1334
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1305
1335
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7" />
1306
1336
  </svg>
1307
1337
  </div>
@@ -1311,10 +1341,10 @@ def About(props=None):
1311
1341
  </p>
1312
1342
  </div>
1313
1343
 
1314
- {/* Feature 3 */}
1344
+
1315
1345
  <div className="relative">
1316
1346
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-green-500 rounded-md">
1317
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1347
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1318
1348
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 2 9 9 0 0118 0z" />
1319
1349
  </svg>
1320
1350
  </div>
@@ -1324,10 +1354,10 @@ def About(props=None):
1324
1354
  </p>
1325
1355
  </div>
1326
1356
 
1327
- {/* Feature 4 */}
1357
+
1328
1358
  <div className="relative">
1329
1359
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-red-500 rounded-md">
1330
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1360
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1331
1361
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7m0 0v7l9-11h-7z" />
1332
1362
  </svg>
1333
1363
  </div>
@@ -1337,10 +1367,10 @@ def About(props=None):
1337
1367
  </p>
1338
1368
  </div>
1339
1369
 
1340
- {/* Feature 5 */}
1370
+
1341
1371
  <div className="relative">
1342
1372
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-yellow-500 rounded-md">
1343
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1373
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1344
1374
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 00-1.065 2.572c1.756.426 1.756 2.924 0 3.35-1.756a1.724 1.724 0 00-1.066-2.573c1.756-.426 1.756-2.924 0-3.35 1.756a1.724 1.724 0 00-2.573-1.066c-1.756.426-1.756-2.924 0-3.35 1.756A1.724 1.724 0 006.573 2.572C3.31 7.76 1.574 8.686 4.317 8.686a1.724 1.724 0 00-1.066-2.572c1.756-.426 1.756-2.924 0-3.35 1.756a1.724 1.724 0 00-2.573-1.066c-1.756.426-1.756-2.924 0-3.35 1.756A1.724 1.724 0 001.066 2.572c1.756.426 1.756 2.924 0 3.35-1.756a1.724 1.724 0 002.573 1.066z" />
1345
1375
  </svg>
1346
1376
  </div>
@@ -1350,10 +1380,10 @@ def About(props=None):
1350
1380
  </p>
1351
1381
  </div>
1352
1382
 
1353
- {/* Feature 6 */}
1383
+
1354
1384
  <div className="relative">
1355
1385
  <div className="absolute flex items-center justify-center w-12 h-12 text-white bg-indigo-500 rounded-md">
1356
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1386
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1357
1387
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
1358
1388
  </svg>
1359
1389
  </div>
@@ -1367,7 +1397,7 @@ def About(props=None):
1367
1397
  </div>
1368
1398
  </div>
1369
1399
 
1370
- {/* Interactive Demo Section */}
1400
+
1371
1401
  <div className="py-12 bg-gray-50">
1372
1402
  <div className="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
1373
1403
  <div className="text-center">
@@ -1380,11 +1410,11 @@ def About(props=None):
1380
1410
  </div>
1381
1411
 
1382
1412
  <div className="grid grid-cols-1 gap-8 mt-12 sm:grid-cols-2 lg:grid-cols-3">
1383
- {/* JSX Demo */}
1413
+
1384
1414
  <div className="p-6 transition-shadow bg-white rounded-lg shadow-lg hover:shadow-xl">
1385
1415
  <div className="text-center">
1386
1416
  <div className="flex items-center justify-center w-12 h-12 mx-auto mb-4 text-white bg-blue-500 rounded-md">
1387
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1417
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1388
1418
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7m0 0v7l9-11h-7z" />
1389
1419
  </svg>
1390
1420
  </div>
@@ -1395,11 +1425,11 @@ def About(props=None):
1395
1425
  </button>
1396
1426
  </div>
1397
1427
 
1398
- {/* Tailwind Demo */}
1428
+
1399
1429
  <div className="p-6 transition-shadow bg-white rounded-lg shadow-lg hover:shadow-xl">
1400
1430
  <div className="text-center">
1401
1431
  <div className="flex items-center justify-center w-12 h-12 mx-auto mb-4 text-white bg-purple-500 rounded-md">
1402
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1432
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1403
1433
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7" />
1404
1434
  </svg>
1405
1435
  </div>
@@ -1410,11 +1440,11 @@ def About(props=None):
1410
1440
  </button>
1411
1441
  </div>
1412
1442
 
1413
- {/* API Demo */}
1443
+
1414
1444
  <div className="p-6 transition-shadow bg-white rounded-lg shadow-lg hover:shadow-xl">
1415
1445
  <div className="text-center">
1416
1446
  <div className="flex items-center justify-center w-12 h-12 mx-auto mb-4 text-white bg-green-500 rounded-md">
1417
- <svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
1447
+ <svg className="w-6 h-6" fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1418
1448
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 2 9 9 0 0118 0z" />
1419
1449
  </svg>
1420
1450
  </div>
@@ -1429,7 +1459,7 @@ def About(props=None):
1429
1459
  </div>
1430
1460
  </div>
1431
1461
 
1432
- {/* Stats Section */}
1462
+
1433
1463
  <div className="bg-blue-600">
1434
1464
  <div className="px-4 py-12 mx-auto max-w-7xl sm:px-6 lg:px-8">
1435
1465
  <div className="grid grid-cols-2 gap-8 lg:grid-cols-4">
@@ -1453,12 +1483,12 @@ def About(props=None):
1453
1483
  </div>
1454
1484
  </div>
1455
1485
 
1456
- {/* Footer */}
1486
+
1457
1487
  <footer className="bg-gray-900">
1458
1488
  <div className="px-4 py-8 mx-auto max-w-7xl sm:px-6 lg:px-8">
1459
1489
  <div className="flex flex-col items-center space-y-4">
1460
1490
  <p className="text-base text-center text-gray-400">
1461
- Built with ❤️ using NextPy Framework
1491
+ Built with &hearts; using NextPy Framework
1462
1492
  </p>
1463
1493
  <div className="flex space-x-6">
1464
1494
  <a href="/" className="text-gray-400 hover:text-gray-300">Home</a>
@@ -1497,7 +1527,7 @@ def InteractiveDemo(props=None):
1497
1527
  </h1>
1498
1528
 
1499
1529
  <div className="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
1500
- {/* Counter Demo */}
1530
+
1501
1531
  <div className="p-6 bg-white shadow-lg rounded-xl">
1502
1532
  <h2 className="mb-4 text-2xl font-bold text-gray-900">Live Counter</h2>
1503
1533
  <div className="text-center">
@@ -1516,7 +1546,7 @@ def InteractiveDemo(props=None):
1516
1546
  </div>
1517
1547
  </div>
1518
1548
 
1519
- {/* Todo List Demo */}
1549
+
1520
1550
  <div className="p-6 bg-white shadow-lg rounded-xl">
1521
1551
  <h2 className="mb-4 text-2xl font-bold text-gray-900">Todo List</h2>
1522
1552
  <div className="space-y-4">
@@ -1527,12 +1557,12 @@ def InteractiveDemo(props=None):
1527
1557
  </button>
1528
1558
  </div>
1529
1559
  <ul id="todoList" className="space-y-2">
1530
- {/* Todos will be added here dynamically */}
1560
+
1531
1561
  </ul>
1532
1562
  </div>
1533
1563
  </div>
1534
1564
 
1535
- {/* Color Picker Demo */}
1565
+
1536
1566
  <div className="p-6 bg-white shadow-lg rounded-xl">
1537
1567
  <h2 className="mb-4 text-2xl font-bold text-gray-900">Color Picker</h2>
1538
1568
  <div className="space-y-4">
@@ -1543,7 +1573,7 @@ def InteractiveDemo(props=None):
1543
1573
  </div>
1544
1574
  </div>
1545
1575
 
1546
- {/* Form Validation Demo */}
1576
+
1547
1577
  <div className="p-6 bg-white shadow-lg rounded-xl">
1548
1578
  <h2 className="mb-4 text-2xl font-bold text-gray-900">Form Validation</h2>
1549
1579
  <form onsubmit="validateForm(event)" className="space-y-4">
@@ -1560,7 +1590,7 @@ def InteractiveDemo(props=None):
1560
1590
  </button>
1561
1591
  </form>
1562
1592
  <div id="validationResult" className="hidden p-4 mt-4 rounded-lg">
1563
- {/* Validation results will appear here */}
1593
+
1564
1594
  </div>
1565
1595
  </div>
1566
1596
  </div>
@@ -1594,13 +1624,13 @@ def Features(props=None):
1594
1624
 
1595
1625
  <div className="grid grid-cols-1 gap-12 md:grid-cols-2">
1596
1626
  <div className="space-y-12">
1597
- {/* Core Features */}
1627
+
1598
1628
  <div>
1599
1629
  <h2 className="mb-6 text-2xl font-bold text-gray-900">Core Features</h2>
1600
1630
  <div className="space-y-6">
1601
1631
  <div className="flex items-start space-x-4">
1602
1632
  <div className="flex-shrink-0 w-6 h-6 text-green-500">
1603
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor">
1633
+ <svg fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1604
1634
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
1605
1635
  </svg>
1606
1636
  </div>
@@ -1612,7 +1642,7 @@ def Features(props=None):
1612
1642
 
1613
1643
  <div className="flex items-start space-x-4">
1614
1644
  <div className="flex-shrink-0 w-6 h-6 text-blue-500">
1615
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor">
1645
+ <svg fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1616
1646
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7" />
1617
1647
  </svg>
1618
1648
  </div>
@@ -1624,7 +1654,7 @@ def Features(props=None):
1624
1654
 
1625
1655
  <div className="flex items-start space-x-4">
1626
1656
  <div className="flex-shrink-0 w-6 h-6 text-purple-500">
1627
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor">
1657
+ <svg fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1628
1658
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 2 9 9 0 0118 0z" />
1629
1659
  </svg>
1630
1660
  </div>
@@ -1636,13 +1666,13 @@ def Features(props=None):
1636
1666
  </div>
1637
1667
  </div>
1638
1668
 
1639
- {/* Development Features */}
1669
+
1640
1670
  <div>
1641
1671
  <h2 className="mb-6 text-2xl font-bold text-gray-900">Development Experience</h2>
1642
1672
  <div className="space-y-6">
1643
1673
  <div className="flex items-start space-x-4">
1644
1674
  <div className="flex-shrink-0 w-6 h-6 text-red-500">
1645
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor">
1675
+ <svg fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1646
1676
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v16h16V4H4z" />
1647
1677
  </svg>
1648
1678
  </div>
@@ -1654,7 +1684,7 @@ def Features(props=None):
1654
1684
 
1655
1685
  <div className="flex items-start space-x-4">
1656
1686
  <div className="flex-shrink-0 w-6 h-6 text-yellow-500">
1657
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor">
1687
+ <svg fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1658
1688
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.75 5H6.25v13l4.5 4.5z" />
1659
1689
  </svg>
1660
1690
  </div>
@@ -1666,7 +1696,7 @@ def Features(props=None):
1666
1696
 
1667
1697
  <div className="flex items-start space-x-4">
1668
1698
  <div className="flex-shrink-0 w-6 h-6 text-indigo-500">
1669
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor">
1699
+ <svg fill="none" viewBox={'0 0 24 24'} stroke="currentColor">
1670
1700
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
1671
1701
  </svg>
1672
1702
  </div>
@@ -1707,7 +1737,7 @@ def GettingStarted(props=None):
1707
1737
  </div>
1708
1738
 
1709
1739
  <div className="space-y-16">
1710
- {/* Step 1 */}
1740
+
1711
1741
  <div className="p-8 rounded-lg bg-blue-50">
1712
1742
  <div className="flex items-center mb-4">
1713
1743
  <div className="flex items-center justify-center flex-shrink-0 w-8 h-8 font-bold text-white bg-blue-500 rounded-full">
@@ -1727,7 +1757,7 @@ def GettingStarted(props=None):
1727
1757
  </div>
1728
1758
  </div>
1729
1759
 
1730
- {/* Step 2 */}
1760
+
1731
1761
  <div className="p-8 rounded-lg bg-green-50">
1732
1762
  <div className="flex items-center mb-4">
1733
1763
  <div className="flex items-center justify-center flex-shrink-0 w-8 h-8 font-bold text-white bg-green-500 rounded-full">
@@ -1744,18 +1774,18 @@ def GettingStarted(props=None):
1744
1774
  <h3 className="mb-2 font-semibold text-gray-900">Project Structure</h3>
1745
1775
  <pre className="p-4 overflow-x-auto text-sm bg-gray-100 rounded">
1746
1776
  {`my-app/
1747
- ├── pages/ # Your pages and API routes
1748
- ├── components/ # Reusable components
1749
- ├── templates/ # HTML templates
1750
- ├── public/ # Static assets
1751
- ├── styles.css # Tailwind CSS
1752
- ├── main.py # Application entry point
1753
- └── requirements.txt # Python dependencies`}</pre>
1777
+ |-- pages/ # Your pages and API routes
1778
+ |-- components/ # Reusable components
1779
+ |-- templates/ # HTML templates
1780
+ |-- public/ # Static assets
1781
+ |-- styles.css # Tailwind CSS
1782
+ |-- main.py # Application entry point
1783
+ `-- requirements.txt # Python dependencies`}</pre>
1754
1784
  </div>
1755
1785
  </div>
1756
1786
  </div>
1757
1787
 
1758
- {/* Step 3 */}
1788
+
1759
1789
  <div className="p-8 rounded-lg bg-purple-50">
1760
1790
  <div className="flex items-center mb-4">
1761
1791
  <div className="flex items-center justify-center flex-shrink-0 w-8 h-8 font-bold text-white bg-purple-500 rounded-full">
@@ -1775,7 +1805,7 @@ def GettingStarted(props=None):
1775
1805
  </div>
1776
1806
  </div>
1777
1807
 
1778
- {/* Step 4 */}
1808
+
1779
1809
  <div className="p-8 rounded-lg bg-yellow-50">
1780
1810
  <div className="flex items-center mb-4">
1781
1811
  <div className="flex items-center justify-center flex-shrink-0 w-8 h-8 font-bold text-white bg-yellow-500 rounded-full">
@@ -1927,21 +1957,21 @@ default = Layout
1927
1957
  "css.value.unit": "rem"
1928
1958
  },
1929
1959
  "files.exclude": {
1930
- "**/__pycache__": true,
1931
- "**/*.pyc": true,
1932
- "**/node_modules": true,
1933
- "**/out": true,
1934
- "**/.next": true,
1935
- "**/.pytest_cache": true,
1936
- "**/.mypy_cache": true
1960
+ "*}__pycache__": true,
1961
+ "*}*.pyc": true,
1962
+ "*}node_modules": true,
1963
+ "*}out": true,
1964
+ "*}.next": true,
1965
+ "*}.pytest_cache": true,
1966
+ "*}.mypy_cache": true
1937
1967
  },
1938
1968
  "search.exclude": {
1939
- "**/node_modules": true,
1940
- "**/out": true,
1941
- "**/.next": true,
1942
- "**/__pycache__": true,
1943
- "**/.pytest_cache": true,
1944
- "**/.mypy_cache": true
1969
+ "*}node_modules": true,
1970
+ "*}out": true,
1971
+ "*}.next": true,
1972
+ "*}__pycache__": true,
1973
+ "*}.pytest_cache": true,
1974
+ "*}.mypy_cache": true
1945
1975
  },
1946
1976
  "python.linting.enabled": true,
1947
1977
  "python.linting.pylintEnabled": false,
@@ -2197,19 +2227,19 @@ This is a NextPy application with True JSX, Tailwind CSS, and comprehensive API
2197
2227
 
2198
2228
  ## Project Structure
2199
2229
  ```
2200
- ├── pages/ # File-based routing
2201
- ├── api/ # API routes
2202
- └── *.py # Page components
2203
- ├── components/ # Reusable components
2204
- ├── templates/ # HTML templates
2205
- ├── models/ # Database models
2206
- ├── utils/ # Utility functions
2207
- ├── hooks/ # Custom hooks
2208
- ├── middleware/ # Custom middleware
2209
- ├── tests/ # Test files
2210
- ├── public/ # Static assets
2211
- ├── styles/ # CSS files
2212
- └── docs/ # Documentation
2230
+ |-- pages/ # File-based routing
2231
+ | |-- api/ # API routes
2232
+ | `-- *.py # Page components
2233
+ |-- components/ # Reusable components
2234
+ |-- templates/ # HTML templates
2235
+ |-- models/ # Database models
2236
+ |-- utils/ # Utility functions
2237
+ |-- hooks/ # Custom hooks
2238
+ |-- middleware/ # Custom middleware
2239
+ |-- tests/ # Test files
2240
+ |-- public/ # Static assets
2241
+ |-- styles/ # CSS files
2242
+ `-- docs/ # Documentation
2213
2243
  ```
2214
2244
 
2215
2245
  ## Getting Started
@@ -2254,9 +2284,6 @@ import sys
2254
2284
  import subprocess
2255
2285
  from pathlib import Path
2256
2286
 
2257
- print(f"DEBUG: Current working directory: {Path.cwd()}")
2258
- print(f"DEBUG: sys.path before modification: {sys.path}")
2259
-
2260
2287
  # Compile Tailwind CSS using PostCSS
2261
2288
  try:
2262
2289
  print("Compiling Tailwind CSS...")
@@ -2268,15 +2295,13 @@ try:
2268
2295
  check=True
2269
2296
  )
2270
2297
  print("Tailwind CSS compiled successfully.")
2271
- if result.stdout:
2272
- print(f"CSS Output: {result.stdout[:200]}...")
2273
2298
  except subprocess.CalledProcessError as e:
2274
2299
  print(f"Error compiling Tailwind CSS: {e}")
2275
2300
  if e.stderr:
2276
2301
  print(f"CSS Error: {e.stderr}")
2277
2302
  except FileNotFoundError:
2278
2303
  print("Error: PostCSS not found. Make sure Node.js and Tailwind CSS are installed.")
2279
- print("Install with: npm install postcss-cli @tailwindcss/postcss")
2304
+ print("Install with: npm install postcss-cli tailwindcss autoprefixer")
2280
2305
 
2281
2306
  # Import NextPy modules (works when installed via pip)
2282
2307
  from nextpy.server.app import create_app
@@ -342,26 +342,34 @@ class ComponentRouter:
342
342
  return handler
343
343
 
344
344
  def _create_template_handler(self, file_path: Path) -> Optional[Callable]:
345
- """Load the traditional template-based handler"""
345
+ """Load the traditional template-based handler using JSX transformer"""
346
346
  try:
347
- spec = importlib.util.spec_from_file_location(
348
- file_path.stem,
349
- file_path
350
- )
351
- if spec and spec.loader:
352
- module = importlib.util.module_from_spec(spec)
353
- spec.loader.exec_module(module)
354
-
347
+ # Use JSX transformer for consistent loading
348
+ from ..jsx_transformer import JSXTransformer
349
+ transformer = JSXTransformer()
350
+ module = transformer.load_jsx_module(file_path, file_path.stem)
351
+
352
+ if module:
355
353
  for func_name in ["handler", "page", "get", "post", "default"]:
356
354
  if hasattr(module, func_name):
357
355
  return getattr(module, func_name)
358
-
359
- if hasattr(module, "Page"):
360
- return module.Page
356
+ except Exception:
357
+ # Fallback to regular import if JSX transformer fails
358
+ try:
359
+ spec = importlib.util.spec_from_file_location(
360
+ file_path.stem,
361
+ file_path
362
+ )
363
+ if spec and spec.loader:
364
+ module = importlib.util.module_from_spec(spec)
365
+ spec.loader.exec_module(module)
361
366
 
362
- except Exception as e:
363
- print(f"Error loading handler from {file_path}: {e}")
364
-
367
+ for func_name in ["handler", "page", "get", "post", "default"]:
368
+ if hasattr(module, func_name):
369
+ return getattr(module, func_name)
370
+ except Exception:
371
+ pass # Silently fail if both methods fail
372
+
365
373
  return None
366
374
 
367
375
  def _sort_routes(self) -> None:
@@ -164,26 +164,34 @@ class Router:
164
164
  )
165
165
 
166
166
  def _load_handler(self, file_path: Path) -> Optional[Callable]:
167
- """Dynamically load the handler function from a page file"""
167
+ """Dynamically load the handler function from a page file using JSX transformer"""
168
168
  try:
169
- spec = importlib.util.spec_from_file_location(
170
- file_path.stem,
171
- file_path
172
- )
173
- if spec and spec.loader:
174
- module = importlib.util.module_from_spec(spec)
175
- spec.loader.exec_module(module)
176
-
169
+ # Use JSX transformer for consistent loading
170
+ from ..jsx_transformer import JSXTransformer
171
+ transformer = JSXTransformer()
172
+ module = transformer.load_jsx_module(file_path, file_path.stem)
173
+
174
+ if module:
177
175
  for func_name in ["handler", "page", "get", "post", "default"]:
178
176
  if hasattr(module, func_name):
179
177
  return getattr(module, func_name)
180
-
181
- if hasattr(module, "Page"):
182
- return module.Page
183
-
184
178
  except Exception as e:
185
- print(f"Error loading handler from {file_path}: {e}")
186
-
179
+ # Fallback to regular import if JSX transformer fails
180
+ try:
181
+ spec = importlib.util.spec_from_file_location(
182
+ file_path.stem,
183
+ file_path
184
+ )
185
+ if spec and spec.loader:
186
+ module = importlib.util.module_from_spec(spec)
187
+ spec.loader.exec_module(module)
188
+
189
+ for func_name in ["handler", "page", "get", "post", "default"]:
190
+ if hasattr(module, func_name):
191
+ return getattr(module, func_name)
192
+ except Exception:
193
+ pass # Silently fail if both methods fail
194
+
187
195
  return None
188
196
 
189
197
  def _sort_routes(self) -> None:
@@ -131,34 +131,57 @@ class NextPyApp:
131
131
  # Add all routes from the router
132
132
  for route in self.router.get_all_routes():
133
133
  if route.is_api:
134
- # API routes
134
+ # API routes - FIXED: use default argument to capture route correctly
135
+ def create_api_handler(route_obj):
136
+ def api_handler(request, route=route_obj):
137
+ return self._handle_api_request(request, route, {})
138
+ return api_handler
139
+
135
140
  self.app.add_api_route(
136
141
  route.path,
137
- lambda request, r=route: self._handle_api_request(request, r, {}),
142
+ create_api_handler(route),
138
143
  methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
139
144
  )
140
145
  else:
141
- # Page routes
142
- async def page_handler(request):
143
- return await self._handle_request(request, route.path)
146
+ # Page routes - FIXED: use default argument to capture route correctly
147
+ def create_page_handler(route_path):
148
+ async def page_handler(request, path=route_path):
149
+ return await self._handle_request(request, path)
150
+ return page_handler
144
151
 
145
152
  self.app.add_route(
146
153
  route.path,
147
- page_handler,
154
+ create_page_handler(route.path),
148
155
  methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
149
156
  )
150
157
 
151
158
  def _load_module_from_file(self, file_path: Path) -> Optional[Any]:
152
- """Load a Python module from a file path"""
159
+ """Load a Python module from a file path with caching"""
153
160
  try:
161
+ # Convert relative path to absolute path
162
+ if not file_path.is_absolute():
163
+ file_path = Path.cwd() / file_path
164
+
165
+ # Create cache key
166
+ cache_key = str(file_path.resolve())
167
+
168
+ # Check cache first (unless in debug mode)
169
+ if not self.debug and cache_key in self._modules_cache:
170
+ return self._modules_cache[cache_key]
171
+
154
172
  module_name = f"nextpy_page_{file_path.stem}_{hash(str(file_path))}"
155
173
 
156
- spec = importlib.util.spec_from_file_location(module_name, file_path)
157
- if spec and spec.loader:
158
- module = importlib.util.module_from_spec(spec)
159
- sys.modules[module_name] = module
160
- spec.loader.exec_module(module)
161
- return module
174
+ # Use JSX transformer for JSX files
175
+ from nextpy.jsx_transformer import JSXTransformer
176
+ transformer = JSXTransformer()
177
+ module = transformer.load_jsx_module(file_path, module_name)
178
+
179
+ # Cache the module (unless in debug mode)
180
+ if module and not self.debug:
181
+ self._modules_cache[cache_key] = module
182
+
183
+ return module
184
+
162
185
  except Exception as e:
163
186
  if self.debug:
164
187
  print(f"Error loading module from {file_path}: {e}")
@@ -210,13 +233,29 @@ class NextPyApp:
210
233
 
211
234
  if module:
212
235
  props = await execute_data_fetching(module, context)
236
+
237
+ # Execute the page component to get JSX
238
+ content = ""
239
+ if hasattr(module, 'default'):
240
+ component = module.default
241
+ component_props = {**props, "params": params}
242
+ jsx_element = component(component_props)
213
243
 
244
+ # Convert JSX to HTML
245
+ try:
246
+ from nextpy.jsx import render_jsx
247
+ content = render_jsx(jsx_element)
248
+ except ImportError:
249
+ # Fail fast - JSX renderer is required
250
+ raise RuntimeError("JSX renderer not available. Please install nextpy.jsx module.")
251
+
214
252
  template_name = self._get_template_name(route, module)
215
253
 
216
254
  html = await self.renderer.render_async(
217
255
  template_name,
218
256
  context={
219
257
  **props,
258
+ "content": content,
220
259
  "params": params,
221
260
  "query": dict(request.query_params),
222
261
  "request": request,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextpy-framework
3
- Version: 2.4.4
3
+ Version: 2.4.6
4
4
  Summary: A Python web framework inspired by Next.js with file-based routing, SSR, and SSG and more
5
5
  Author: NextPy Team
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextpy-framework
3
- Version: 2.4.4
3
+ Version: 2.4.6
4
4
  Summary: A Python web framework inspired by Next.js with file-based routing, SSR, and SSG and more
5
5
  Author: NextPy Team
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nextpy-framework"
7
- version = "2.4.4"
7
+ version = "2.4.6"
8
8
  description = "A Python web framework inspired by Next.js with file-based routing, SSR, and SSG and more"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"