fastapi-fullstack 0.1.7__py3-none-any.whl

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 (241) hide show
  1. fastapi_fullstack-0.1.7.dist-info/METADATA +739 -0
  2. fastapi_fullstack-0.1.7.dist-info/RECORD +241 -0
  3. fastapi_fullstack-0.1.7.dist-info/WHEEL +4 -0
  4. fastapi_fullstack-0.1.7.dist-info/entry_points.txt +2 -0
  5. fastapi_fullstack-0.1.7.dist-info/licenses/LICENSE +21 -0
  6. fastapi_gen/__init__.py +3 -0
  7. fastapi_gen/cli.py +442 -0
  8. fastapi_gen/config.py +356 -0
  9. fastapi_gen/generator.py +207 -0
  10. fastapi_gen/prompts.py +874 -0
  11. fastapi_gen/template/VARIABLES.md +276 -0
  12. fastapi_gen/template/cookiecutter.json +93 -0
  13. fastapi_gen/template/hooks/post_gen_project.py +355 -0
  14. fastapi_gen/template/{{cookiecutter.project_slug}}/.env.prod.example +56 -0
  15. fastapi_gen/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +150 -0
  16. fastapi_gen/template/{{cookiecutter.project_slug}}/.gitignore +109 -0
  17. fastapi_gen/template/{{cookiecutter.project_slug}}/AGENTS.md +55 -0
  18. fastapi_gen/template/{{cookiecutter.project_slug}}/CLAUDE.md +99 -0
  19. fastapi_gen/template/{{cookiecutter.project_slug}}/Makefile +315 -0
  20. fastapi_gen/template/{{cookiecutter.project_slug}}/README.md +768 -0
  21. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.dockerignore +60 -0
  22. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.env.example +155 -0
  23. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +32 -0
  24. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/Dockerfile +56 -0
  25. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +76 -0
  26. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +30 -0
  27. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
  28. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic.ini +48 -0
  29. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +3 -0
  30. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/admin.py +447 -0
  31. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +23 -0
  32. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +226 -0
  33. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/langchain_assistant.py +226 -0
  34. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py +10 -0
  35. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +13 -0
  36. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +17 -0
  37. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +1 -0
  38. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +541 -0
  39. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +98 -0
  40. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +10 -0
  41. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +9 -0
  42. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +87 -0
  43. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +902 -0
  44. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +395 -0
  45. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +498 -0
  46. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +227 -0
  47. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +275 -0
  48. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +205 -0
  49. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +168 -0
  50. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +333 -0
  51. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +477 -0
  52. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +46 -0
  53. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +221 -0
  54. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +14 -0
  55. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +88 -0
  56. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +117 -0
  57. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +75 -0
  58. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +28 -0
  59. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +266 -0
  60. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +5 -0
  61. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +23 -0
  62. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +267 -0
  63. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +153 -0
  64. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +122 -0
  65. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +101 -0
  66. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +99 -0
  67. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +23 -0
  68. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +58 -0
  69. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +271 -0
  70. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +102 -0
  71. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +7 -0
  72. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +41 -0
  73. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +31 -0
  74. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +319 -0
  75. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +96 -0
  76. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +126 -0
  77. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +218 -0
  78. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +244 -0
  79. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +130 -0
  80. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/main.py +334 -0
  81. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +9 -0
  82. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +73 -0
  83. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +49 -0
  84. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +154 -0
  85. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +838 -0
  86. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +222 -0
  87. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +318 -0
  88. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +322 -0
  89. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +358 -0
  90. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +50 -0
  91. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +57 -0
  92. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +192 -0
  93. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +52 -0
  94. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +42 -0
  95. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +31 -0
  96. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +64 -0
  97. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +89 -0
  98. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +38 -0
  99. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +850 -0
  100. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +246 -0
  101. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +333 -0
  102. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +432 -0
  103. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +561 -0
  104. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +5 -0
  105. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +64 -0
  106. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +38 -0
  107. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +25 -0
  108. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +106 -0
  109. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +29 -0
  110. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +92 -0
  111. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +1 -0
  112. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +438 -0
  113. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +180 -0
  114. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
  115. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +1 -0
  116. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +1 -0
  117. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +242 -0
  118. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +151 -0
  119. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +113 -0
  120. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +310 -0
  121. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +253 -0
  122. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +151 -0
  123. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_admin.py +890 -0
  124. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +261 -0
  125. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +183 -0
  126. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +173 -0
  127. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +143 -0
  128. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +118 -0
  129. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +181 -0
  130. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +124 -0
  131. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +363 -0
  132. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +85 -0
  133. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +242 -0
  134. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +31 -0
  135. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +435 -0
  136. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml +241 -0
  137. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/adding_features.md +132 -0
  138. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/architecture.md +63 -0
  139. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/patterns.md +161 -0
  140. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/testing.md +120 -0
  141. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.dockerignore +40 -0
  142. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.env.example +12 -0
  143. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.gitignore +45 -0
  144. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +19 -0
  145. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +11 -0
  146. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +44 -0
  147. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/README.md +648 -0
  148. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +49 -0
  149. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +134 -0
  150. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +207 -0
  151. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +73 -0
  152. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +14 -0
  153. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +84 -0
  154. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +84 -0
  155. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +76 -0
  156. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/package.json +69 -0
  157. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +101 -0
  158. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +7 -0
  159. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/layout.tsx +11 -0
  160. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/login/page.tsx +5 -0
  161. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/register/page.tsx +5 -0
  162. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/chat/page.tsx +48 -0
  163. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/dashboard/page.tsx +99 -0
  164. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/layout.tsx +17 -0
  165. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/profile/page.tsx +152 -0
  166. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/auth/callback/page.tsx +113 -0
  167. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/layout.tsx +46 -0
  168. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/page.tsx +73 -0
  169. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +58 -0
  170. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +24 -0
  171. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +39 -0
  172. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +50 -0
  173. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +54 -0
  174. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +26 -0
  175. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +41 -0
  176. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +108 -0
  177. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +73 -0
  178. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +21 -0
  179. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +323 -0
  180. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +22 -0
  181. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +29 -0
  182. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +2 -0
  183. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +120 -0
  184. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +153 -0
  185. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +234 -0
  186. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +72 -0
  187. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +328 -0
  188. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/copy-button.tsx +46 -0
  189. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +11 -0
  190. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/local-conversation-sidebar.tsx +295 -0
  191. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/markdown-content.tsx +167 -0
  192. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +79 -0
  193. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +18 -0
  194. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +79 -0
  195. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +32 -0
  196. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +3 -0
  197. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +97 -0
  198. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +65 -0
  199. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +2 -0
  200. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +82 -0
  201. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +7 -0
  202. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +53 -0
  203. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +105 -0
  204. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +35 -0
  205. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +75 -0
  206. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +56 -0
  207. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +82 -0
  208. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +13 -0
  209. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +21 -0
  210. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +21 -0
  211. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/sheet.tsx +109 -0
  212. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +7 -0
  213. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +97 -0
  214. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +203 -0
  215. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +181 -0
  216. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-local-chat.ts +165 -0
  217. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +105 -0
  218. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +37 -0
  219. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +90 -0
  220. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +39 -0
  221. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +78 -0
  222. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +44 -0
  223. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +44 -0
  224. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +31 -0
  225. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +72 -0
  226. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +64 -0
  227. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-sidebar-store.ts +17 -0
  228. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +65 -0
  229. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +76 -0
  230. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +9 -0
  231. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/local-chat-store.ts +255 -0
  232. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/sidebar-store.ts +17 -0
  233. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +44 -0
  234. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +27 -0
  235. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +52 -0
  236. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +83 -0
  237. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +49 -0
  238. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +10 -0
  239. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +28 -0
  240. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +36 -0
  241. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +56 -0
fastapi_gen/config.py ADDED
@@ -0,0 +1,356 @@
1
+ """Configuration models for project generation."""
2
+
3
+ from datetime import UTC, datetime
4
+ from enum import Enum
5
+ from importlib.metadata import version
6
+ from typing import Any
7
+
8
+ from pydantic import BaseModel, EmailStr, Field, computed_field, model_validator
9
+
10
+ GENERATOR_NAME = "fastapi-fullstack"
11
+
12
+
13
+ def get_generator_version() -> str:
14
+ """Get the current generator version from package metadata."""
15
+ try:
16
+ return version(GENERATOR_NAME)
17
+ except Exception:
18
+ return "0.0.0"
19
+
20
+
21
+ class DatabaseType(str, Enum):
22
+ """Supported database types."""
23
+
24
+ POSTGRESQL = "postgresql"
25
+ MONGODB = "mongodb"
26
+ SQLITE = "sqlite"
27
+ NONE = "none"
28
+
29
+
30
+ class AuthType(str, Enum):
31
+ """Supported authentication types."""
32
+
33
+ JWT = "jwt"
34
+ API_KEY = "api_key"
35
+ BOTH = "both"
36
+ NONE = "none"
37
+
38
+
39
+ class BackgroundTaskType(str, Enum):
40
+ """Supported background task systems."""
41
+
42
+ NONE = "none"
43
+ CELERY = "celery"
44
+ TASKIQ = "taskiq"
45
+ ARQ = "arq"
46
+
47
+
48
+ class CIType(str, Enum):
49
+ """Supported CI/CD systems."""
50
+
51
+ GITHUB = "github"
52
+ GITLAB = "gitlab"
53
+ NONE = "none"
54
+
55
+
56
+ class FrontendType(str, Enum):
57
+ """Supported frontend frameworks."""
58
+
59
+ NONE = "none"
60
+ NEXTJS = "nextjs"
61
+
62
+
63
+ class WebSocketAuthType(str, Enum):
64
+ """WebSocket authentication types for AI Agent."""
65
+
66
+ NONE = "none"
67
+ JWT = "jwt"
68
+ API_KEY = "api_key"
69
+
70
+
71
+ class AdminEnvironmentType(str, Enum):
72
+ """Admin panel environment restriction types."""
73
+
74
+ ALL = "all" # Available in all environments
75
+ DEV_ONLY = "dev_only" # Only in development
76
+ DEV_STAGING = "dev_staging" # Development + Staging (recommended)
77
+ DISABLED = "disabled" # Disabled everywhere
78
+
79
+
80
+ class OAuthProvider(str, Enum):
81
+ """Supported OAuth2 providers."""
82
+
83
+ NONE = "none"
84
+ GOOGLE = "google"
85
+
86
+
87
+ class AIFrameworkType(str, Enum):
88
+ """Supported AI agent frameworks."""
89
+
90
+ PYDANTIC_AI = "pydantic_ai"
91
+ LANGCHAIN = "langchain"
92
+
93
+
94
+ class LLMProviderType(str, Enum):
95
+ """Supported LLM providers."""
96
+
97
+ OPENAI = "openai"
98
+ ANTHROPIC = "anthropic"
99
+ OPENROUTER = "openrouter"
100
+
101
+
102
+ class RateLimitStorageType(str, Enum):
103
+ """Rate limiting storage backends."""
104
+
105
+ MEMORY = "memory"
106
+ REDIS = "redis"
107
+
108
+
109
+ class ReverseProxyType(str, Enum):
110
+ """Reverse proxy configuration options."""
111
+
112
+ TRAEFIK_INCLUDED = "traefik_included" # Include Traefik service + labels
113
+ TRAEFIK_EXTERNAL = "traefik_external" # External Traefik, include labels only
114
+ NONE = "none" # No reverse proxy, expose ports directly
115
+
116
+
117
+ class LogfireFeatures(BaseModel):
118
+ """Logfire instrumentation features."""
119
+
120
+ fastapi: bool = True
121
+ database: bool = True
122
+ redis: bool = False
123
+ celery: bool = False
124
+ httpx: bool = False
125
+
126
+
127
+ class ProjectConfig(BaseModel):
128
+ """Full project configuration."""
129
+
130
+ # Basic info
131
+ project_name: str = Field(..., min_length=1, pattern=r"^[a-z][a-z0-9_]*$")
132
+ project_description: str = "A FastAPI project"
133
+
134
+ author_name: str = "Your Name"
135
+ author_email: EmailStr = "your@email.com"
136
+
137
+ # Database
138
+ database: DatabaseType = DatabaseType.POSTGRESQL
139
+ db_pool_size: int = 5
140
+ db_max_overflow: int = 10
141
+ db_pool_timeout: int = 30
142
+
143
+ # Authentication
144
+ auth: AuthType = AuthType.JWT
145
+ oauth_provider: OAuthProvider = OAuthProvider.NONE
146
+ enable_session_management: bool = False
147
+
148
+ # Observability
149
+ enable_logfire: bool = True
150
+ logfire_features: LogfireFeatures = Field(default_factory=LogfireFeatures)
151
+
152
+ # Background tasks
153
+ background_tasks: BackgroundTaskType = BackgroundTaskType.NONE
154
+
155
+ # Optional integrations
156
+ enable_redis: bool = False
157
+ enable_caching: bool = False
158
+ enable_rate_limiting: bool = False
159
+ rate_limit_requests: int = 100
160
+ rate_limit_period: int = 60
161
+ rate_limit_storage: RateLimitStorageType = RateLimitStorageType.MEMORY
162
+ enable_pagination: bool = True
163
+ enable_sentry: bool = False
164
+ enable_prometheus: bool = False
165
+ enable_admin_panel: bool = False
166
+ admin_environments: AdminEnvironmentType = AdminEnvironmentType.DEV_STAGING
167
+ admin_require_auth: bool = True
168
+ enable_websockets: bool = False
169
+ enable_file_storage: bool = False
170
+ enable_ai_agent: bool = False
171
+ ai_framework: AIFrameworkType = AIFrameworkType.PYDANTIC_AI
172
+ llm_provider: LLMProviderType = LLMProviderType.OPENAI
173
+ enable_conversation_persistence: bool = False
174
+ enable_webhooks: bool = False
175
+ websocket_auth: WebSocketAuthType = WebSocketAuthType.NONE
176
+ enable_cors: bool = True
177
+ enable_orjson: bool = True
178
+
179
+ # Frontend features
180
+ enable_i18n: bool = False
181
+
182
+ # Example CRUD
183
+ include_example_crud: bool = True
184
+
185
+ # Dev tools
186
+ enable_pytest: bool = True
187
+ enable_precommit: bool = True
188
+ enable_makefile: bool = True
189
+ enable_docker: bool = True
190
+ reverse_proxy: ReverseProxyType = ReverseProxyType.TRAEFIK_INCLUDED
191
+ ci_type: CIType = CIType.GITHUB
192
+ enable_kubernetes: bool = False
193
+ generate_env: bool = True
194
+
195
+ # Python version
196
+ python_version: str = "3.12"
197
+
198
+ # Frontend
199
+ frontend: FrontendType = FrontendType.NONE
200
+ frontend_port: int = 3000
201
+
202
+ # Backend
203
+ backend_port: int = 8000
204
+
205
+ @computed_field
206
+ @property
207
+ def project_slug(self) -> str:
208
+ """Return project slug (underscores instead of hyphens)."""
209
+ return self.project_name.replace("-", "_")
210
+
211
+ @model_validator(mode="after")
212
+ def validate_option_combinations(self) -> "ProjectConfig":
213
+ """Validate that option combinations are valid.
214
+
215
+ Raises ValueError for invalid combinations:
216
+ - Admin panel requires a database (PostgreSQL or SQLite)
217
+ - Admin panel (SQLAdmin) does not support MongoDB
218
+ - Caching requires Redis to be enabled
219
+ - Session management requires a database
220
+ - Conversation persistence requires a database
221
+ """
222
+ if self.enable_admin_panel and self.database == DatabaseType.NONE:
223
+ raise ValueError("Admin panel requires a database")
224
+ if self.enable_admin_panel and self.database == DatabaseType.MONGODB:
225
+ raise ValueError("Admin panel (SQLAdmin) requires PostgreSQL or SQLite")
226
+ if self.enable_caching and not self.enable_redis:
227
+ raise ValueError("Caching requires Redis to be enabled")
228
+ if self.enable_session_management and self.database == DatabaseType.NONE:
229
+ raise ValueError("Session management requires a database")
230
+ if self.enable_conversation_persistence and self.database == DatabaseType.NONE:
231
+ raise ValueError("Conversation persistence requires a database")
232
+ if (
233
+ self.enable_ai_agent
234
+ and self.ai_framework == AIFrameworkType.LANGCHAIN
235
+ and self.llm_provider == LLMProviderType.OPENROUTER
236
+ ):
237
+ raise ValueError("OpenRouter is not supported with LangChain")
238
+ if (
239
+ self.enable_rate_limiting
240
+ and self.rate_limit_storage == RateLimitStorageType.REDIS
241
+ and not self.enable_redis
242
+ ):
243
+ raise ValueError("Rate limiting with Redis storage requires Redis to be enabled")
244
+ return self
245
+
246
+ def to_cookiecutter_context(self) -> dict[str, Any]:
247
+ """Convert config to cookiecutter context."""
248
+ return {
249
+ # Generator metadata
250
+ "generator_name": GENERATOR_NAME,
251
+ "generator_version": get_generator_version(),
252
+ "generated_at": datetime.now(UTC).isoformat(),
253
+ # Project info
254
+ "project_name": self.project_name,
255
+ "project_slug": self.project_slug,
256
+ "project_description": self.project_description,
257
+ "author_name": self.author_name,
258
+ "author_email": self.author_email,
259
+ # Database
260
+ "database": self.database.value,
261
+ "use_postgresql": self.database == DatabaseType.POSTGRESQL,
262
+ "use_mongodb": self.database == DatabaseType.MONGODB,
263
+ "use_sqlite": self.database == DatabaseType.SQLITE,
264
+ "use_database": self.database != DatabaseType.NONE,
265
+ "db_pool_size": self.db_pool_size,
266
+ "db_max_overflow": self.db_max_overflow,
267
+ "db_pool_timeout": self.db_pool_timeout,
268
+ # Auth
269
+ "auth": self.auth.value,
270
+ "use_jwt": self.auth in (AuthType.JWT, AuthType.BOTH),
271
+ "use_api_key": self.auth in (AuthType.API_KEY, AuthType.BOTH),
272
+ "use_auth": self.auth != AuthType.NONE,
273
+ # OAuth
274
+ "oauth_provider": self.oauth_provider.value,
275
+ "enable_oauth": self.oauth_provider != OAuthProvider.NONE,
276
+ "enable_oauth_google": self.oauth_provider == OAuthProvider.GOOGLE,
277
+ # Session Management
278
+ "enable_session_management": self.enable_session_management,
279
+ # Logfire
280
+ "enable_logfire": self.enable_logfire,
281
+ "logfire_fastapi": self.logfire_features.fastapi,
282
+ "logfire_database": self.logfire_features.database,
283
+ "logfire_redis": self.logfire_features.redis,
284
+ "logfire_celery": self.logfire_features.celery,
285
+ "logfire_httpx": self.logfire_features.httpx,
286
+ # Background tasks
287
+ "background_tasks": self.background_tasks.value,
288
+ "use_celery": self.background_tasks == BackgroundTaskType.CELERY,
289
+ "use_taskiq": self.background_tasks == BackgroundTaskType.TASKIQ,
290
+ "use_arq": self.background_tasks == BackgroundTaskType.ARQ,
291
+ # Integrations
292
+ "enable_redis": self.enable_redis,
293
+ "enable_caching": self.enable_caching,
294
+ "enable_rate_limiting": self.enable_rate_limiting,
295
+ "rate_limit_requests": self.rate_limit_requests,
296
+ "rate_limit_period": self.rate_limit_period,
297
+ "rate_limit_storage": self.rate_limit_storage.value,
298
+ "rate_limit_storage_memory": self.rate_limit_storage == RateLimitStorageType.MEMORY,
299
+ "rate_limit_storage_redis": self.rate_limit_storage == RateLimitStorageType.REDIS,
300
+ "enable_pagination": self.enable_pagination,
301
+ "enable_sentry": self.enable_sentry,
302
+ "enable_prometheus": self.enable_prometheus,
303
+ "enable_admin_panel": self.enable_admin_panel,
304
+ "admin_environments": self.admin_environments.value,
305
+ "admin_env_all": self.admin_environments == AdminEnvironmentType.ALL,
306
+ "admin_env_dev_only": self.admin_environments == AdminEnvironmentType.DEV_ONLY,
307
+ "admin_env_dev_staging": self.admin_environments == AdminEnvironmentType.DEV_STAGING,
308
+ "admin_env_disabled": self.admin_environments == AdminEnvironmentType.DISABLED,
309
+ "admin_require_auth": self.admin_require_auth,
310
+ "enable_websockets": self.enable_websockets,
311
+ "enable_file_storage": self.enable_file_storage,
312
+ "enable_ai_agent": self.enable_ai_agent,
313
+ "ai_framework": self.ai_framework.value,
314
+ "use_pydantic_ai": self.ai_framework == AIFrameworkType.PYDANTIC_AI,
315
+ "use_langchain": self.ai_framework == AIFrameworkType.LANGCHAIN,
316
+ "llm_provider": self.llm_provider.value,
317
+ "use_openai": self.llm_provider == LLMProviderType.OPENAI,
318
+ "use_anthropic": self.llm_provider == LLMProviderType.ANTHROPIC,
319
+ "use_openrouter": self.llm_provider == LLMProviderType.OPENROUTER,
320
+ "enable_conversation_persistence": self.enable_conversation_persistence,
321
+ "enable_webhooks": self.enable_webhooks,
322
+ "websocket_auth": self.websocket_auth.value,
323
+ "websocket_auth_jwt": self.websocket_auth == WebSocketAuthType.JWT,
324
+ "websocket_auth_api_key": self.websocket_auth == WebSocketAuthType.API_KEY,
325
+ "websocket_auth_none": self.websocket_auth == WebSocketAuthType.NONE,
326
+ "enable_cors": self.enable_cors,
327
+ "enable_orjson": self.enable_orjson,
328
+ # Frontend features
329
+ "enable_i18n": self.enable_i18n,
330
+ # Example CRUD
331
+ "include_example_crud": self.include_example_crud,
332
+ # Dev tools
333
+ "enable_pytest": self.enable_pytest,
334
+ "enable_precommit": self.enable_precommit,
335
+ "enable_makefile": self.enable_makefile,
336
+ "enable_docker": self.enable_docker,
337
+ # Reverse proxy
338
+ "reverse_proxy": self.reverse_proxy.value,
339
+ "include_traefik_service": self.reverse_proxy == ReverseProxyType.TRAEFIK_INCLUDED,
340
+ "include_traefik_labels": self.reverse_proxy
341
+ in (ReverseProxyType.TRAEFIK_INCLUDED, ReverseProxyType.TRAEFIK_EXTERNAL),
342
+ "ci_type": self.ci_type.value,
343
+ "use_github_actions": self.ci_type == CIType.GITHUB,
344
+ "use_gitlab_ci": self.ci_type == CIType.GITLAB,
345
+ "enable_kubernetes": self.enable_kubernetes,
346
+ "generate_env": self.generate_env,
347
+ # Python version
348
+ "python_version": self.python_version,
349
+ # Frontend
350
+ "frontend": self.frontend.value,
351
+ "use_frontend": self.frontend != FrontendType.NONE,
352
+ "use_nextjs": self.frontend == FrontendType.NEXTJS,
353
+ "frontend_port": self.frontend_port,
354
+ # Backend
355
+ "backend_port": self.backend_port,
356
+ }
@@ -0,0 +1,207 @@
1
+ """Project generation logic."""
2
+
3
+ import shutil
4
+ from pathlib import Path
5
+
6
+ from cookiecutter.main import cookiecutter
7
+ from rich.console import Console
8
+ from rich.progress import Progress, SpinnerColumn, TextColumn
9
+
10
+ from .config import DatabaseType, FrontendType, ProjectConfig
11
+
12
+ console = Console()
13
+
14
+
15
+ def _get_database_setup_commands(database: DatabaseType) -> list[str]:
16
+ """Get database-specific setup commands for post-generation messages.
17
+
18
+ Args:
19
+ database: The database type selected by the user
20
+
21
+ Returns:
22
+ List of command strings to display
23
+ """
24
+ if database == DatabaseType.SQLITE:
25
+ return [
26
+ "# SQLite database will be created automatically at first run",
27
+ "make db-migrate # Create initial migration",
28
+ "make db-upgrade # Apply migrations",
29
+ ]
30
+ elif database == DatabaseType.MONGODB:
31
+ return [
32
+ "make docker-mongo # Start MongoDB container",
33
+ "# Or configure MongoDB Atlas connection in .env",
34
+ ]
35
+ else: # PostgreSQL
36
+ return [
37
+ "make docker-db # Start PostgreSQL container",
38
+ "make db-migrate # Create initial migration",
39
+ "make db-upgrade # Apply migrations",
40
+ ]
41
+
42
+
43
+ def _find_template_dir() -> Path:
44
+ """Find the template directory.
45
+
46
+ Works both in development (template at project root) and when installed
47
+ (template bundled inside the package).
48
+ """
49
+ # Development: template is at project root (sibling to fastapi_gen/)
50
+ dev_path = Path(__file__).parent.parent / "template"
51
+ if dev_path.exists() and (dev_path / "cookiecutter.json").exists():
52
+ return dev_path
53
+
54
+ # Installed: template is inside the package
55
+ installed_path = Path(__file__).parent / "template"
56
+ if installed_path.exists() and (installed_path / "cookiecutter.json").exists():
57
+ return installed_path
58
+
59
+ raise FileNotFoundError(
60
+ "Could not find cookiecutter template. "
61
+ "Expected at 'template/' (development) or 'fastapi_gen/template/' (installed)."
62
+ )
63
+
64
+
65
+ TEMPLATE_DIR = _find_template_dir()
66
+
67
+
68
+ def get_template_path() -> str:
69
+ """Get the path to the cookiecutter template."""
70
+ return str(TEMPLATE_DIR)
71
+
72
+
73
+ def generate_project(config: ProjectConfig, output_dir: Path | None = None) -> Path:
74
+ """Generate a new FastAPI project from configuration.
75
+
76
+ Args:
77
+ config: Project configuration
78
+ output_dir: Output directory (defaults to current directory)
79
+
80
+ Returns:
81
+ Path to the generated project
82
+
83
+ Raises:
84
+ ValueError: If target directory exists and is not empty
85
+ """
86
+ if output_dir is None:
87
+ output_dir = Path.cwd()
88
+
89
+ # Check if target directory already exists and is not empty
90
+ target_dir = output_dir / config.project_slug
91
+ if target_dir.exists() and any(target_dir.iterdir()):
92
+ raise ValueError(f"Directory '{target_dir}' already exists and is not empty")
93
+
94
+ context = config.to_cookiecutter_context()
95
+ template_path = get_template_path()
96
+
97
+ with Progress(
98
+ SpinnerColumn(),
99
+ TextColumn("[progress.description]{task.description}"),
100
+ console=console,
101
+ ) as progress:
102
+ progress.add_task(description="Generating project...", total=None)
103
+
104
+ try:
105
+ # Generate project using cookiecutter
106
+ project_path = cookiecutter(
107
+ template_path,
108
+ extra_context=context,
109
+ output_dir=str(output_dir),
110
+ no_input=True,
111
+ )
112
+ except Exception:
113
+ # Cleanup partial files on failure
114
+ if target_dir.exists():
115
+ shutil.rmtree(target_dir)
116
+ raise
117
+
118
+ return Path(project_path)
119
+
120
+
121
+ def post_generation_tasks(project_path: Path, config: ProjectConfig) -> None:
122
+ """Run post-generation tasks.
123
+
124
+ Args:
125
+ project_path: Path to the generated project
126
+ config: Project configuration
127
+ """
128
+ console.print()
129
+ console.print(f"[bold green]Project created at:[/] {project_path}")
130
+ console.print()
131
+ console.print("[bold cyan]Next steps:[/]")
132
+ console.print()
133
+ console.print(f" cd {project_path.name}")
134
+
135
+ step = 1
136
+ if config.frontend != FrontendType.NONE:
137
+ # Full-stack project
138
+ console.print()
139
+ if config.generate_env:
140
+ console.print(f"[bold]{step}. Environment:[/]")
141
+ console.print(" backend/.env and frontend/.env.local are pre-configured")
142
+ console.print(" # Review and update settings as needed")
143
+ else:
144
+ console.print(f"[bold]{step}. Configure environment:[/]")
145
+ console.print(" cd backend && cp .env.example .env")
146
+ console.print(" cd frontend && cp .env.example .env.local")
147
+ console.print(" # Edit with your settings (database, secrets, etc.)")
148
+ step += 1
149
+ console.print()
150
+ console.print(f"[bold]{step}. Install backend dependencies:[/]")
151
+ console.print(" make install")
152
+ step += 1
153
+ if config.database.value != "none":
154
+ console.print()
155
+ console.print(f"[bold]{step}. Database setup:[/]")
156
+ for cmd in _get_database_setup_commands(config.database):
157
+ console.print(f" {cmd}")
158
+ step += 1
159
+ console.print()
160
+ console.print(f"[bold]{step}. Run backend:[/]")
161
+ console.print(" make run")
162
+ step += 1
163
+ console.print()
164
+ console.print(f"[bold]{step}. Frontend setup (in new terminal):[/]")
165
+ console.print(" cd frontend")
166
+ console.print(" bun install")
167
+ console.print(" bun run dev")
168
+ else:
169
+ # Backend-only project
170
+ console.print()
171
+ if config.generate_env:
172
+ console.print(f"[bold]{step}. Environment:[/]")
173
+ console.print(" backend/.env is pre-configured for development")
174
+ console.print(" # Review and update settings as needed")
175
+ else:
176
+ console.print(f"[bold]{step}. Configure environment:[/]")
177
+ console.print(" cd backend && cp .env.example .env")
178
+ console.print(" # Edit backend/.env with your settings")
179
+ step += 1
180
+ console.print()
181
+ console.print(f"[bold]{step}. Install dependencies:[/]")
182
+ console.print(" make install")
183
+ step += 1
184
+ if config.database.value != "none":
185
+ console.print()
186
+ console.print(f"[bold]{step}. Database setup:[/]")
187
+ for cmd in _get_database_setup_commands(config.database):
188
+ console.print(f" {cmd}")
189
+ step += 1
190
+ console.print()
191
+ console.print(f"[bold]{step}. Run server:[/]")
192
+ console.print(" make run")
193
+
194
+ console.print()
195
+
196
+ if config.enable_logfire:
197
+ console.print("[dim]To enable Logfire, set LOGFIRE_TOKEN in backend/.env[/]")
198
+ console.print("[dim]Get your token at: https://logfire.pydantic.dev[/]")
199
+ console.print()
200
+
201
+ if config.frontend == FrontendType.NEXTJS:
202
+ console.print(f"[dim]Frontend runs on http://localhost:{config.frontend_port}[/]")
203
+ console.print(f"[dim]Backend API runs on http://localhost:{config.backend_port}[/]")
204
+ else:
205
+ console.print(f"[dim]API runs on http://localhost:{config.backend_port}[/]")
206
+ console.print(f"[dim]API docs: http://localhost:{config.backend_port}/docs[/]")
207
+ console.print()