fastapi-fullstack 0.1.11__tar.gz → 0.1.13__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 (258) hide show
  1. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/PKG-INFO +4 -2
  2. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/README.md +3 -1
  3. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/fastapi_gen/config.py +87 -2
  4. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/fastapi_gen/generator.py +34 -14
  5. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/fastapi_gen/prompts.py +130 -32
  6. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/pyproject.toml +10 -1
  7. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/VARIABLES.md +4 -2
  8. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/cookiecutter.json +1 -0
  9. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/hooks/post_gen_project.py +55 -2
  10. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/CLAUDE.md +1 -0
  11. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/admin.py +1 -1
  12. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +10 -0
  13. fastapi_fullstack-0.1.13/template/{{cookiecutter.project_slug}}/backend/app/agents/crewai_assistant.py +563 -0
  14. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/agents/langchain_assistant.py +4 -3
  15. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +461 -0
  16. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +3 -7
  17. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +2 -2
  18. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +7 -2
  19. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +12 -7
  20. fastapi_fullstack-0.1.13/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +14 -0
  21. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +10 -2
  22. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +1 -2
  23. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/main.py +8 -2
  24. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +6 -0
  25. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +4 -4
  26. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +9 -9
  27. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +6 -6
  28. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +7 -7
  29. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +9 -0
  30. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +2 -0
  31. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +6 -0
  32. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +39 -0
  33. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/.env.example +5 -0
  34. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +22 -4
  35. fastapi_fullstack-0.1.13/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +38 -0
  36. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +164 -17
  37. fastapi_fullstack-0.1.13/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-local-chat.ts +313 -0
  38. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +1 -1
  39. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +16 -1
  40. fastapi_fullstack-0.1.11/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +0 -7
  41. fastapi_fullstack-0.1.11/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +0 -18
  42. fastapi_fullstack-0.1.11/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-local-chat.ts +0 -165
  43. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/.gitignore +0 -0
  44. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/LICENSE +0 -0
  45. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/fastapi_gen/__init__.py +0 -0
  46. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/fastapi_gen/cli.py +0 -0
  47. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/.env.prod.example +0 -0
  48. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +0 -0
  49. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/.gitignore +0 -0
  50. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/.gitlab-ci.yml +0 -0
  51. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/AGENTS.md +0 -0
  52. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/Makefile +0 -0
  53. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/README.md +0 -0
  54. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/.dockerignore +0 -0
  55. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/.env.example +0 -0
  56. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +0 -0
  57. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/Dockerfile +0 -0
  58. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +0 -0
  59. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +0 -0
  60. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
  61. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/alembic.ini +0 -0
  62. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +0 -0
  63. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +0 -0
  64. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/agents/langgraph_assistant.py +0 -0
  65. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py +0 -0
  66. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +0 -0
  67. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +0 -0
  68. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +0 -0
  69. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +0 -0
  70. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +0 -0
  71. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +0 -0
  72. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +0 -0
  73. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +0 -0
  74. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +0 -0
  75. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +0 -0
  76. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +0 -0
  77. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +0 -0
  78. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +0 -0
  79. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +0 -0
  80. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +0 -0
  81. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +0 -0
  82. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +0 -0
  83. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +0 -0
  84. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +0 -0
  85. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +0 -0
  86. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +0 -0
  87. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +0 -0
  88. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +0 -0
  89. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +0 -0
  90. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +0 -0
  91. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +0 -0
  92. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +0 -0
  93. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +0 -0
  94. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +0 -0
  95. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +0 -0
  96. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +0 -0
  97. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +0 -0
  98. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +0 -0
  99. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +0 -0
  100. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +0 -0
  101. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +0 -0
  102. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +0 -0
  103. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +0 -0
  104. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +0 -0
  105. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +0 -0
  106. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +0 -0
  107. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +0 -0
  108. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +0 -0
  109. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +0 -0
  110. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +0 -0
  111. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +0 -0
  112. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +0 -0
  113. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +0 -0
  114. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +0 -0
  115. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +0 -0
  116. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +0 -0
  117. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +0 -0
  118. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +0 -0
  119. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +0 -0
  120. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +0 -0
  121. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +0 -0
  122. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/arq_app.py +0 -0
  123. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +0 -0
  124. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +0 -0
  125. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +0 -0
  126. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +0 -0
  127. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +0 -0
  128. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +0 -0
  129. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +0 -0
  130. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +0 -0
  131. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
  132. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +0 -0
  133. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +0 -0
  134. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +0 -0
  135. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +0 -0
  136. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +0 -0
  137. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +0 -0
  138. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_metrics.py +0 -0
  139. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +0 -0
  140. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +0 -0
  141. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_admin.py +0 -0
  142. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +0 -0
  143. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +0 -0
  144. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +0 -0
  145. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +0 -0
  146. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +0 -0
  147. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +0 -0
  148. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +0 -0
  149. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +0 -0
  150. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +0 -0
  151. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docker-compose.yml +0 -0
  152. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docs/adding_features.md +0 -0
  153. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docs/architecture.md +0 -0
  154. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docs/patterns.md +0 -0
  155. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/docs/testing.md +0 -0
  156. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/.dockerignore +0 -0
  157. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/.gitignore +0 -0
  158. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +0 -0
  159. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +0 -0
  160. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +0 -0
  161. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/README.md +0 -0
  162. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +0 -0
  163. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +0 -0
  164. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +0 -0
  165. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +0 -0
  166. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +0 -0
  167. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +0 -0
  168. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +0 -0
  169. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +0 -0
  170. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/package.json +0 -0
  171. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +0 -0
  172. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +0 -0
  173. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/layout.tsx +0 -0
  174. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/login/page.tsx +0 -0
  175. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/register/page.tsx +0 -0
  176. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/chat/page.tsx +0 -0
  177. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/dashboard/page.tsx +0 -0
  178. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/layout.tsx +0 -0
  179. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/profile/page.tsx +0 -0
  180. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/auth/callback/page.tsx +0 -0
  181. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/layout.tsx +0 -0
  182. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/page.tsx +0 -0
  183. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +0 -0
  184. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +0 -0
  185. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +0 -0
  186. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +0 -0
  187. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +0 -0
  188. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +0 -0
  189. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +0 -0
  190. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +0 -0
  191. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +0 -0
  192. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +0 -0
  193. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +0 -0
  194. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +0 -0
  195. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +0 -0
  196. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +0 -0
  197. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +0 -0
  198. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +0 -0
  199. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +0 -0
  200. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +0 -0
  201. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +0 -0
  202. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/copy-button.tsx +0 -0
  203. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +0 -0
  204. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/local-conversation-sidebar.tsx +0 -0
  205. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/markdown-content.tsx +0 -0
  206. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +0 -0
  207. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +0 -0
  208. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +0 -0
  209. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +0 -0
  210. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +0 -0
  211. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +0 -0
  212. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +0 -0
  213. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +0 -0
  214. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +0 -0
  215. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +0 -0
  216. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +0 -0
  217. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +0 -0
  218. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +0 -0
  219. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +0 -0
  220. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +0 -0
  221. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +0 -0
  222. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +0 -0
  223. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/sheet.tsx +0 -0
  224. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +0 -0
  225. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +0 -0
  226. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +0 -0
  227. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +0 -0
  228. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +0 -0
  229. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +0 -0
  230. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +0 -0
  231. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +0 -0
  232. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +0 -0
  233. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +0 -0
  234. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +0 -0
  235. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +0 -0
  236. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-sidebar-store.ts +0 -0
  237. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +0 -0
  238. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +0 -0
  239. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +0 -0
  240. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/local-chat-store.ts +0 -0
  241. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/sidebar-store.ts +0 -0
  242. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +0 -0
  243. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +0 -0
  244. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +0 -0
  245. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +0 -0
  246. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +0 -0
  247. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +0 -0
  248. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +0 -0
  249. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +0 -0
  250. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/kubernetes/configmap.yaml +0 -0
  251. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/kubernetes/deployment.yaml +0 -0
  252. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/kubernetes/ingress.yaml +0 -0
  253. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/kubernetes/kustomization.yaml +0 -0
  254. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/kubernetes/namespace.yaml +0 -0
  255. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/kubernetes/secret.yaml +0 -0
  256. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/kubernetes/service.yaml +0 -0
  257. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/nginx/nginx.conf +0 -0
  258. {fastapi_fullstack-0.1.11 → fastapi_fullstack-0.1.13}/template/{{cookiecutter.project_slug}}/nginx/ssl/.gitkeep +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-fullstack
3
- Version: 0.1.11
3
+ Version: 0.1.13
4
4
  Summary: Full-stack FastAPI + Next.js template generator with PydanticAI/LangChain agents, WebSocket streaming, 20+ enterprise integrations, and Logfire/LangSmith observability. Ship AI apps fast. CLI tool to generate production-ready FastAPI + Next.js projects with AI agents, auth, and observability.
5
5
  Project-URL: Homepage, https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template
6
6
  Project-URL: Documentation, https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template#readme
@@ -199,8 +199,10 @@ make docker-db
199
199
 
200
200
  #### 3. Create and apply database migrations
201
201
 
202
+ > ⚠️ **Important:** Both commands are required! `db-migrate` creates the migration file, `db-upgrade` applies it to the database.
203
+
202
204
  ```bash
203
- # Create initial migration (first time only)
205
+ # Create initial migration (REQUIRED first time)
204
206
  make db-migrate
205
207
  # Enter message: "Initial migration"
206
208
 
@@ -163,8 +163,10 @@ make docker-db
163
163
 
164
164
  #### 3. Create and apply database migrations
165
165
 
166
+ > ⚠️ **Important:** Both commands are required! `db-migrate` creates the migration file, `db-upgrade` applies it to the database.
167
+
166
168
  ```bash
167
- # Create initial migration (first time only)
169
+ # Create initial migration (REQUIRED first time)
168
170
  make db-migrate
169
171
  # Enter message: "Initial migration"
170
172
 
@@ -90,6 +90,7 @@ class AIFrameworkType(str, Enum):
90
90
  PYDANTIC_AI = "pydantic_ai"
91
91
  LANGCHAIN = "langchain"
92
92
  LANGGRAPH = "langgraph"
93
+ CREWAI = "crewai"
93
94
 
94
95
 
95
96
  class LLMProviderType(str, Enum):
@@ -178,7 +179,7 @@ class ProjectConfig(BaseModel):
178
179
  admin_require_auth: bool = True
179
180
  enable_websockets: bool = False
180
181
  enable_file_storage: bool = False
181
- enable_ai_agent: bool = False
182
+ enable_ai_agent: bool = True
182
183
  ai_framework: AIFrameworkType = AIFrameworkType.PYDANTIC_AI
183
184
  llm_provider: LLMProviderType = LLMProviderType.OPENAI
184
185
  enable_conversation_persistence: bool = False
@@ -207,7 +208,7 @@ class ProjectConfig(BaseModel):
207
208
  python_version: str = "3.12"
208
209
 
209
210
  # Frontend
210
- frontend: FrontendType = FrontendType.NONE
211
+ frontend: FrontendType = FrontendType.NEXTJS
211
212
  frontend_port: int = 3000
212
213
 
213
214
  # Backend
@@ -270,12 +271,95 @@ class ProjectConfig(BaseModel):
270
271
  and self.llm_provider == LLMProviderType.OPENROUTER
271
272
  ):
272
273
  raise ValueError("OpenRouter is not supported with LangGraph")
274
+ if (
275
+ self.enable_ai_agent
276
+ and self.ai_framework == AIFrameworkType.CREWAI
277
+ and self.llm_provider == LLMProviderType.OPENROUTER
278
+ ):
279
+ raise ValueError("OpenRouter is not supported with CrewAI")
273
280
  if (
274
281
  self.enable_rate_limiting
275
282
  and self.rate_limit_storage == RateLimitStorageType.REDIS
276
283
  and not self.enable_redis
277
284
  ):
278
285
  raise ValueError("Rate limiting with Redis storage requires Redis to be enabled")
286
+
287
+ # WebSocket JWT auth requires main JWT auth
288
+ if self.websocket_auth == WebSocketAuthType.JWT and self.auth not in (
289
+ AuthType.JWT,
290
+ AuthType.BOTH,
291
+ ):
292
+ raise ValueError("WebSocket JWT authentication requires JWT auth to be enabled")
293
+
294
+ # WebSocket API key auth requires main API key auth
295
+ if self.websocket_auth == WebSocketAuthType.API_KEY and self.auth not in (
296
+ AuthType.API_KEY,
297
+ AuthType.BOTH,
298
+ ):
299
+ raise ValueError("WebSocket API key authentication requires API key auth to be enabled")
300
+
301
+ # Admin panel authentication requires JWT (for User model and security functions)
302
+ if (
303
+ self.enable_admin_panel
304
+ and self.admin_require_auth
305
+ and self.auth not in (AuthType.JWT, AuthType.BOTH)
306
+ ):
307
+ raise ValueError(
308
+ "Admin panel authentication requires JWT auth to be enabled. "
309
+ "Either enable JWT auth or set admin_require_auth=False"
310
+ )
311
+
312
+ # Conversation persistence requires AI agent
313
+ if self.enable_conversation_persistence and not self.enable_ai_agent:
314
+ raise ValueError("Conversation persistence requires AI agent to be enabled")
315
+
316
+ # Admin panel requires SQLAlchemy (SQLAdmin doesn't fully support SQLModel)
317
+ if self.enable_admin_panel and self.orm_type == OrmType.SQLMODEL:
318
+ raise ValueError(
319
+ "Admin panel (SQLAdmin) requires SQLAlchemy ORM. "
320
+ "SQLModel is not fully supported. Use orm_type=sqlalchemy or disable admin panel."
321
+ )
322
+
323
+ # Session management requires JWT auth
324
+ if self.enable_session_management and self.auth not in (AuthType.JWT, AuthType.BOTH):
325
+ raise ValueError("Session management requires JWT auth to be enabled")
326
+
327
+ # Webhooks require a database
328
+ if self.enable_webhooks and self.database == DatabaseType.NONE:
329
+ raise ValueError(
330
+ "Webhooks require a database to store subscriptions and delivery history"
331
+ )
332
+
333
+ # Background task queues require Redis
334
+ if (
335
+ self.background_tasks
336
+ in (
337
+ BackgroundTaskType.CELERY,
338
+ BackgroundTaskType.TASKIQ,
339
+ BackgroundTaskType.ARQ,
340
+ )
341
+ and not self.enable_redis
342
+ ):
343
+ raise ValueError(
344
+ f"{self.background_tasks.value.title()} requires Redis to be enabled. "
345
+ "All task queue systems use Redis as broker/backend."
346
+ )
347
+
348
+ # Logfire feature-specific validations (only when logfire is enabled)
349
+ if self.enable_logfire:
350
+ if self.logfire_features.database and self.database == DatabaseType.NONE:
351
+ raise ValueError(
352
+ "Logfire database instrumentation requires a database to be enabled"
353
+ )
354
+
355
+ if self.logfire_features.redis and not self.enable_redis:
356
+ raise ValueError("Logfire Redis instrumentation requires Redis to be enabled")
357
+
358
+ if self.logfire_features.celery and self.background_tasks != BackgroundTaskType.CELERY:
359
+ raise ValueError(
360
+ "Logfire Celery instrumentation requires Celery as background task system"
361
+ )
362
+
279
363
  return self
280
364
 
281
365
  def to_cookiecutter_context(self) -> dict[str, Any]:
@@ -353,6 +437,7 @@ class ProjectConfig(BaseModel):
353
437
  "use_pydantic_ai": self.ai_framework == AIFrameworkType.PYDANTIC_AI,
354
438
  "use_langchain": self.ai_framework == AIFrameworkType.LANGCHAIN,
355
439
  "use_langgraph": self.ai_framework == AIFrameworkType.LANGGRAPH,
440
+ "use_crewai": self.ai_framework == AIFrameworkType.CREWAI,
356
441
  "llm_provider": self.llm_provider.value,
357
442
  "use_openai": self.llm_provider == LLMProviderType.OPENAI,
358
443
  "use_anthropic": self.llm_provider == LLMProviderType.ANTHROPIC,
@@ -12,31 +12,31 @@ from .config import DatabaseType, FrontendType, ProjectConfig
12
12
  console = Console()
13
13
 
14
14
 
15
- def _get_database_setup_commands(database: DatabaseType) -> list[str]:
15
+ def _get_database_setup_commands(database: DatabaseType) -> list[tuple[str, str]]:
16
16
  """Get database-specific setup commands for post-generation messages.
17
17
 
18
18
  Args:
19
19
  database: The database type selected by the user
20
20
 
21
21
  Returns:
22
- List of command strings to display
22
+ List of (command, description) tuples to display
23
23
  """
24
24
  if database == DatabaseType.SQLITE:
25
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",
26
+ ("# SQLite database will be created automatically", ""),
27
+ ("make db-migrate", "Create initial migration"),
28
+ ("make db-upgrade", "Apply migrations"),
29
29
  ]
30
30
  elif database == DatabaseType.MONGODB:
31
31
  return [
32
- "make docker-mongo # Start MongoDB container",
33
- "# Or configure MongoDB Atlas connection in .env",
32
+ ("make docker-mongo", "Start MongoDB container"),
33
+ ("# Or configure MongoDB Atlas connection in .env", ""),
34
34
  ]
35
35
  else: # PostgreSQL
36
36
  return [
37
- "make docker-db # Start PostgreSQL container",
38
- "make db-migrate # Create initial migration",
39
- "make db-upgrade # Apply migrations",
37
+ ("make docker-db", "Start PostgreSQL container"),
38
+ ("make db-migrate", "Create initial migration"),
39
+ ("make db-upgrade", "Apply migrations"),
40
40
  ]
41
41
 
42
42
 
@@ -153,8 +153,18 @@ def post_generation_tasks(project_path: Path, config: ProjectConfig) -> None:
153
153
  if config.database.value != "none":
154
154
  console.print()
155
155
  console.print(f"[bold]{step}. Database setup:[/]")
156
- for cmd in _get_database_setup_commands(config.database):
157
- console.print(f" {cmd}")
156
+ db_commands = _get_database_setup_commands(config.database)
157
+ for cmd, desc in db_commands:
158
+ if desc:
159
+ console.print(f" {cmd:22}# {desc}")
160
+ else:
161
+ console.print(f" {cmd}")
162
+ if config.database != DatabaseType.MONGODB:
163
+ console.print()
164
+ console.print(
165
+ " [dim]⚠️ Run all commands in order:[/] "
166
+ "[dim]db-migrate creates the migration, db-upgrade applies it[/]"
167
+ )
158
168
  step += 1
159
169
  console.print()
160
170
  console.print(f"[bold]{step}. Run backend:[/]")
@@ -184,8 +194,18 @@ def post_generation_tasks(project_path: Path, config: ProjectConfig) -> None:
184
194
  if config.database.value != "none":
185
195
  console.print()
186
196
  console.print(f"[bold]{step}. Database setup:[/]")
187
- for cmd in _get_database_setup_commands(config.database):
188
- console.print(f" {cmd}")
197
+ db_commands = _get_database_setup_commands(config.database)
198
+ for cmd, desc in db_commands:
199
+ if desc:
200
+ console.print(f" {cmd:22}# {desc}")
201
+ else:
202
+ console.print(f" {cmd}")
203
+ if config.database != DatabaseType.MONGODB:
204
+ console.print()
205
+ console.print(
206
+ " [dim]⚠️ Run all commands in order:[/] "
207
+ "[dim]db-migrate creates the migration, db-upgrade applies it[/]"
208
+ )
189
209
  step += 1
190
210
  console.print()
191
211
  console.print(f"[bold]{step}. Run server:[/]")
@@ -157,11 +157,11 @@ def prompt_orm_type() -> OrmType:
157
157
  """Prompt for ORM library selection."""
158
158
  choices = [
159
159
  questionary.Choice(
160
- "SQLAlchemy (recommended - full control, mature)",
160
+ "SQLAlchemy full control, supports admin panel",
161
161
  value=OrmType.SQLALCHEMY,
162
162
  ),
163
163
  questionary.Choice(
164
- "SQLModel (simplified - less boilerplate, FastAPI-native)",
164
+ "SQLModel less boilerplate, no admin panel support",
165
165
  value=OrmType.SQLMODEL,
166
166
  ),
167
167
  ]
@@ -289,36 +289,120 @@ def prompt_background_tasks() -> BackgroundTaskType:
289
289
  )
290
290
 
291
291
 
292
- def prompt_integrations() -> dict[str, bool]:
293
- """Prompt for optional integrations."""
292
+ def prompt_integrations(
293
+ database: DatabaseType,
294
+ orm_type: OrmType,
295
+ ) -> dict[str, bool]:
296
+ """Prompt for optional integrations.
297
+
298
+ Args:
299
+ database: Selected database type (affects which options are shown).
300
+ orm_type: Selected ORM type (SQLModel doesn't support admin panel).
301
+ """
294
302
  console.print()
295
303
  console.print("[bold cyan]Optional Integrations[/]")
296
304
  console.print()
297
305
 
306
+ # Build choices dynamically based on context
307
+ choices: list[questionary.Choice] = [
308
+ questionary.Choice(
309
+ "Redis — required for caching, rate limiting (Redis), task queues",
310
+ value="redis",
311
+ ),
312
+ questionary.Choice(
313
+ "Caching (fastapi-cache2) — requires Redis",
314
+ value="caching",
315
+ ),
316
+ questionary.Choice(
317
+ "Rate limiting (slowapi) — optional Redis storage",
318
+ value="rate_limiting",
319
+ ),
320
+ questionary.Choice(
321
+ "Pagination (fastapi-pagination)",
322
+ value="pagination",
323
+ checked=True,
324
+ ),
325
+ questionary.Choice(
326
+ "Sentry — error tracking & monitoring",
327
+ value="sentry",
328
+ ),
329
+ questionary.Choice(
330
+ "Prometheus — metrics endpoint for monitoring",
331
+ value="prometheus",
332
+ ),
333
+ ]
334
+
335
+ # Admin Panel only available with SQLAlchemy (not SQLModel) and SQL database
336
+ if (
337
+ database in (DatabaseType.POSTGRESQL, DatabaseType.SQLITE)
338
+ and orm_type == OrmType.SQLALCHEMY
339
+ ):
340
+ choices.append(
341
+ questionary.Choice(
342
+ "Admin Panel (SQLAdmin) — web UI for database management",
343
+ value="admin_panel",
344
+ )
345
+ )
346
+
347
+ choices.extend(
348
+ [
349
+ questionary.Choice(
350
+ "WebSockets — real-time bidirectional communication",
351
+ value="websockets",
352
+ ),
353
+ questionary.Choice(
354
+ "File Storage (S3/MinIO) — file upload/download support",
355
+ value="file_storage",
356
+ ),
357
+ questionary.Choice(
358
+ "AI Agent (PydanticAI/LangGraph/CrewAI) — LLM-powered assistant",
359
+ value="ai_agent",
360
+ checked=True,
361
+ ),
362
+ ]
363
+ )
364
+
365
+ # Webhooks require database
366
+ if database != DatabaseType.NONE:
367
+ choices.append(
368
+ questionary.Choice(
369
+ "Webhooks — outbound event notifications",
370
+ value="webhooks",
371
+ )
372
+ )
373
+
374
+ choices.extend(
375
+ [
376
+ questionary.Choice(
377
+ "Example CRUD (Item model) — sample API endpoints",
378
+ value="example_crud",
379
+ checked=True,
380
+ ),
381
+ questionary.Choice(
382
+ "CORS middleware — cross-origin request support",
383
+ value="cors",
384
+ checked=True,
385
+ ),
386
+ questionary.Choice(
387
+ "orjson — faster JSON serialization",
388
+ value="orjson",
389
+ checked=True,
390
+ ),
391
+ ]
392
+ )
393
+
298
394
  features = _check_cancelled(
299
395
  questionary.checkbox(
300
396
  "Select additional features:",
301
- choices=[
302
- questionary.Choice("Redis (caching/sessions)", value="redis"),
303
- questionary.Choice("Caching (fastapi-cache2)", value="caching"),
304
- questionary.Choice("Rate limiting (slowapi)", value="rate_limiting"),
305
- questionary.Choice(
306
- "Pagination (fastapi-pagination)", value="pagination", checked=True
307
- ),
308
- questionary.Choice("Sentry (error tracking)", value="sentry"),
309
- questionary.Choice("Prometheus (metrics)", value="prometheus"),
310
- questionary.Choice("Admin Panel (SQLAdmin)", value="admin_panel"),
311
- questionary.Choice("WebSockets", value="websockets"),
312
- questionary.Choice("File Storage (S3/MinIO)", value="file_storage"),
313
- questionary.Choice("AI Agent (PydanticAI/LangChain)", value="ai_agent"),
314
- questionary.Choice("Webhooks (outbound events)", value="webhooks"),
315
- questionary.Choice("Example CRUD (Item model)", value="example_crud", checked=True),
316
- questionary.Choice("CORS middleware", value="cors", checked=True),
317
- questionary.Choice("orjson (faster JSON)", value="orjson", checked=True),
318
- ],
397
+ choices=choices,
319
398
  ).ask()
320
399
  )
321
400
 
401
+ # Auto-enable Redis for caching (show info message)
402
+ if "caching" in features and "redis" not in features:
403
+ console.print("[yellow]ℹ Caching requires Redis — auto-enabled[/]")
404
+ features.append("redis")
405
+
322
406
  return {
323
407
  "enable_redis": "redis" in features,
324
408
  "enable_caching": "caching" in features,
@@ -485,8 +569,8 @@ def prompt_frontend() -> FrontendType:
485
569
  console.print()
486
570
 
487
571
  choices = [
488
- questionary.Choice("None (API only)", value=FrontendType.NONE),
489
572
  questionary.Choice("Next.js 15 (App Router, TypeScript, Bun)", value=FrontendType.NEXTJS),
573
+ questionary.Choice("None (API only)", value=FrontendType.NONE),
490
574
  ]
491
575
 
492
576
  return cast(
@@ -531,6 +615,7 @@ def prompt_ai_framework() -> AIFrameworkType:
531
615
  questionary.Choice("PydanticAI (recommended)", value=AIFrameworkType.PYDANTIC_AI),
532
616
  questionary.Choice("LangChain", value=AIFrameworkType.LANGCHAIN),
533
617
  questionary.Choice("LangGraph (ReAct agent)", value=AIFrameworkType.LANGGRAPH),
618
+ questionary.Choice("CrewAI (multi-agent crews)", value=AIFrameworkType.CREWAI),
534
619
  ]
535
620
 
536
621
  return cast(
@@ -550,7 +635,7 @@ def prompt_llm_provider(ai_framework: AIFrameworkType) -> LLMProviderType:
550
635
 
551
636
  Args:
552
637
  ai_framework: The selected AI framework. OpenRouter is only
553
- available for PydanticAI (not LangChain or LangGraph).
638
+ available for PydanticAI (not LangChain, LangGraph, or CrewAI).
554
639
  """
555
640
  console.print()
556
641
  console.print("[bold cyan]LLM Provider[/]")
@@ -561,7 +646,7 @@ def prompt_llm_provider(ai_framework: AIFrameworkType) -> LLMProviderType:
561
646
  questionary.Choice("Anthropic (claude-sonnet-4-5)", value=LLMProviderType.ANTHROPIC),
562
647
  ]
563
648
 
564
- # OpenRouter only available for PydanticAI (not LangChain or LangGraph)
649
+ # OpenRouter only available for PydanticAI (not LangChain, LangGraph, or CrewAI)
565
650
  if ai_framework == AIFrameworkType.PYDANTIC_AI:
566
651
  choices.append(
567
652
  questionary.Choice("OpenRouter (multi-provider)", value=LLMProviderType.OPENROUTER)
@@ -579,18 +664,31 @@ def prompt_llm_provider(ai_framework: AIFrameworkType) -> LLMProviderType:
579
664
  )
580
665
 
581
666
 
582
- def prompt_websocket_auth() -> WebSocketAuthType:
583
- """Prompt for WebSocket authentication method for AI Agent."""
667
+ def prompt_websocket_auth(auth: AuthType) -> WebSocketAuthType:
668
+ """Prompt for WebSocket authentication method for AI Agent.
669
+
670
+ Args:
671
+ auth: The main auth type. JWT WebSocket auth is only available
672
+ if JWT is enabled (JWT or BOTH).
673
+ """
584
674
  console.print()
585
675
  console.print("[bold cyan]AI Agent WebSocket Authentication[/]")
586
676
  console.print()
587
677
 
588
678
  choices = [
589
679
  questionary.Choice("None (public access)", value=WebSocketAuthType.NONE),
590
- questionary.Choice("JWT token required", value=WebSocketAuthType.JWT),
591
- questionary.Choice("API Key required (query param)", value=WebSocketAuthType.API_KEY),
592
680
  ]
593
681
 
682
+ # JWT WebSocket auth only available if main auth uses JWT
683
+ if auth in (AuthType.JWT, AuthType.BOTH):
684
+ choices.append(questionary.Choice("JWT token required", value=WebSocketAuthType.JWT))
685
+
686
+ # API Key WebSocket auth available if main auth uses API keys
687
+ if auth in (AuthType.API_KEY, AuthType.BOTH):
688
+ choices.append(
689
+ questionary.Choice("API Key required (query param)", value=WebSocketAuthType.API_KEY)
690
+ )
691
+
594
692
  return cast(
595
693
  WebSocketAuthType,
596
694
  _check_cancelled(
@@ -741,8 +839,8 @@ def run_interactive_prompts() -> ProjectConfig:
741
839
  # Background tasks
742
840
  background_tasks = prompt_background_tasks()
743
841
 
744
- # Integrations
745
- integrations = prompt_integrations()
842
+ # Integrations (pass context for dynamic option filtering)
843
+ integrations = prompt_integrations(database=database, orm_type=orm_type)
746
844
 
747
845
  # Dev tools
748
846
  dev_tools = prompt_dev_tools()
@@ -777,7 +875,7 @@ def run_interactive_prompts() -> ProjectConfig:
777
875
  if integrations.get("enable_ai_agent"):
778
876
  ai_framework = prompt_ai_framework()
779
877
  llm_provider = prompt_llm_provider(ai_framework)
780
- websocket_auth = prompt_websocket_auth()
878
+ websocket_auth = prompt_websocket_auth(auth=auth)
781
879
  # Only offer persistence if database is enabled
782
880
  if database != DatabaseType.NONE:
783
881
  enable_conversation_persistence = _check_cancelled(
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fastapi-fullstack"
3
- version = "0.1.11"
3
+ version = "0.1.13"
4
4
  description = "Full-stack FastAPI + Next.js template generator with PydanticAI/LangChain agents, WebSocket streaming, 20+ enterprise integrations, and Logfire/LangSmith observability. Ship AI apps fast. CLI tool to generate production-ready FastAPI + Next.js projects with AI agents, auth, and observability."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -149,6 +149,9 @@ testpaths = ["tests"]
149
149
  python_files = ["test_*.py"]
150
150
  python_functions = ["test_*"]
151
151
  addopts = "-v --tb=short"
152
+ markers = [
153
+ "slow: marks tests as slow (deselect with '-m \"not slow\"')",
154
+ ]
152
155
 
153
156
  [tool.coverage.run]
154
157
  source = ["fastapi_gen"]
@@ -162,3 +165,9 @@ exclude_lines = [
162
165
  "if TYPE_CHECKING:",
163
166
  "raise NotImplementedError",
164
167
  ]
168
+
169
+ [dependency-groups]
170
+ dev = [
171
+ "mypy>=1.19.1",
172
+ "pytest-cov>=7.0.0",
173
+ ]
@@ -187,10 +187,11 @@ These variables are set automatically by the generator.
187
187
  | Variable | Type | Default | Description | Dependencies |
188
188
  |----------|------|---------|-------------|--------------|
189
189
  | `enable_ai_agent` | bool | `false` | Enable AI agent functionality | - |
190
- | `ai_framework` | enum | `"pydantic_ai"` | AI framework. Values: `pydantic_ai`, `langchain`, `langgraph` | Requires `enable_ai_agent` |
190
+ | `ai_framework` | enum | `"pydantic_ai"` | AI framework. Values: `pydantic_ai`, `langchain`, `langgraph`, `crewai` | Requires `enable_ai_agent` |
191
191
  | `use_pydantic_ai` | bool | `true` | PydanticAI is selected | Computed from `ai_framework` |
192
192
  | `use_langchain` | bool | `false` | LangChain is selected | Computed from `ai_framework` |
193
193
  | `use_langgraph` | bool | `false` | LangGraph (ReAct agent) is selected | Computed from `ai_framework` |
194
+ | `use_crewai` | bool | `false` | CrewAI (multi-agent crews) is selected | Computed from `ai_framework` |
194
195
  | `llm_provider` | enum | `"openai"` | LLM provider. Values: `openai`, `anthropic`, `openrouter` | Requires `enable_ai_agent` |
195
196
  | `use_openai` | bool | `true` | OpenAI is selected | Computed from `llm_provider` |
196
197
  | `use_anthropic` | bool | `false` | Anthropic is selected | Computed from `llm_provider` |
@@ -200,7 +201,8 @@ These variables are set automatically by the generator.
200
201
  **Notes:**
201
202
  - PydanticAI uses `iter()` for full event streaming over WebSocket
202
203
  - LangGraph implements a ReAct (Reasoning + Acting) agent pattern with graph-based architecture
203
- - OpenRouter with LangChain or LangGraph is not supported
204
+ - CrewAI enables multi-agent teams that collaborate on complex tasks
205
+ - OpenRouter with LangChain, LangGraph, or CrewAI is not supported
204
206
 
205
207
  ---
206
208
 
@@ -62,6 +62,7 @@
62
62
  "use_pydantic_ai": true,
63
63
  "use_langchain": false,
64
64
  "use_langgraph": false,
65
+ "use_crewai": false,
65
66
  "llm_provider": "openai",
66
67
  "use_openai": true,
67
68
  "use_anthropic": false,
@@ -16,10 +16,14 @@ use_database = "{{ cookiecutter.use_database }}" == "True"
16
16
  use_postgresql = "{{ cookiecutter.use_postgresql }}" == "True"
17
17
  use_sqlite = "{{ cookiecutter.use_sqlite }}" == "True"
18
18
  use_mongodb = "{{ cookiecutter.use_mongodb }}" == "True"
19
+ use_sqlalchemy = "{{ cookiecutter.use_sqlalchemy }}" == "True"
20
+ use_sqlmodel = "{{ cookiecutter.use_sqlmodel }}" == "True"
19
21
  include_example_crud = "{{ cookiecutter.include_example_crud }}" == "True"
20
22
  enable_ai_agent = "{{ cookiecutter.enable_ai_agent }}" == "True"
21
23
  use_pydantic_ai = "{{ cookiecutter.use_pydantic_ai }}" == "True"
22
24
  use_langchain = "{{ cookiecutter.use_langchain }}" == "True"
25
+ use_langgraph = "{{ cookiecutter.use_langgraph }}" == "True"
26
+ use_crewai = "{{ cookiecutter.use_crewai }}" == "True"
23
27
  enable_admin_panel = "{{ cookiecutter.enable_admin_panel }}" == "True"
24
28
  enable_websockets = "{{ cookiecutter.enable_websockets }}" == "True"
25
29
  enable_redis = "{{ cookiecutter.enable_redis }}" == "True"
@@ -30,6 +34,7 @@ enable_conversation_persistence = "{{ cookiecutter.enable_conversation_persisten
30
34
  enable_webhooks = "{{ cookiecutter.enable_webhooks }}" == "True"
31
35
  enable_oauth = "{{ cookiecutter.enable_oauth }}" == "True"
32
36
  use_jwt = "{{ cookiecutter.use_jwt }}" == "True"
37
+ use_api_key = "{{ cookiecutter.use_api_key }}" == "True"
33
38
  use_celery = "{{ cookiecutter.use_celery }}" == "True"
34
39
  use_taskiq = "{{ cookiecutter.use_taskiq }}" == "True"
35
40
  use_arq = "{{ cookiecutter.use_arq }}" == "True"
@@ -37,6 +42,7 @@ use_github_actions = "{{ cookiecutter.use_github_actions }}" == "True"
37
42
  use_gitlab_ci = "{{ cookiecutter.use_gitlab_ci }}" == "True"
38
43
  enable_kubernetes = "{{ cookiecutter.enable_kubernetes }}" == "True"
39
44
  use_nginx = "{{ cookiecutter.use_nginx }}" == "True"
45
+ enable_logfire = "{{ cookiecutter.enable_logfire }}" == "True"
40
46
 
41
47
 
42
48
  def remove_file(path: str) -> None:
@@ -46,6 +52,23 @@ def remove_file(path: str) -> None:
46
52
  print(f" Removed: {os.path.relpath(path)}")
47
53
 
48
54
 
55
+ def is_stub_file(filepath: str) -> bool:
56
+ """Check if file only contains a docstring stub with no real code."""
57
+ if not os.path.exists(filepath):
58
+ return False
59
+ with open(filepath) as f:
60
+ content = f.read().strip()
61
+ # Empty file
62
+ if not content:
63
+ return True
64
+ # File only has docstring (triple-quoted string)
65
+ if content.startswith('"""') and content.endswith('"""'):
66
+ # Check if there's only one docstring and no code
67
+ inner = content[3:-3].strip()
68
+ return '"""' not in inner and "def " not in content and "class " not in content
69
+ return False
70
+
71
+
49
72
  def remove_dir(path: str) -> None:
50
73
  """Remove a directory if it exists."""
51
74
  if os.path.exists(path):
@@ -72,6 +95,10 @@ else:
72
95
  remove_file(os.path.join(backend_app, "agents", "assistant.py"))
73
96
  if not use_langchain:
74
97
  remove_file(os.path.join(backend_app, "agents", "langchain_assistant.py"))
98
+ if not use_langgraph:
99
+ remove_file(os.path.join(backend_app, "agents", "langgraph_assistant.py"))
100
+ if not use_crewai:
101
+ remove_file(os.path.join(backend_app, "agents", "crewai_assistant.py"))
75
102
 
76
103
  # --- Example CRUD files ---
77
104
  if not include_example_crud or not use_database:
@@ -109,8 +136,8 @@ if not enable_session_management or not use_jwt:
109
136
  if not enable_websockets:
110
137
  remove_file(os.path.join(backend_app, "api", "routes", "v1", "ws.py"))
111
138
 
112
- # --- Admin panel ---
113
- if not enable_admin_panel or (not use_postgresql and not use_sqlite):
139
+ # --- Admin panel (requires SQLAlchemy, not SQLModel) ---
140
+ if not enable_admin_panel or (not use_postgresql and not use_sqlite) or not use_sqlalchemy:
114
141
  remove_file(os.path.join(backend_app, "admin.py"))
115
142
 
116
143
  # --- Redis/Cache files ---
@@ -129,6 +156,32 @@ if not enable_oauth:
129
156
  remove_file(os.path.join(backend_app, "api", "routes", "v1", "oauth.py"))
130
157
  remove_file(os.path.join(backend_app, "core", "oauth.py"))
131
158
 
159
+ # --- Security file (only when no auth at all) ---
160
+ if not use_jwt and not use_api_key:
161
+ remove_file(os.path.join(backend_app, "core", "security.py"))
162
+
163
+ # --- Auth/User files (when JWT is disabled) ---
164
+ if not use_jwt:
165
+ remove_file(os.path.join(backend_app, "api", "routes", "v1", "auth.py"))
166
+ remove_file(os.path.join(backend_app, "api", "routes", "v1", "users.py"))
167
+ remove_file(os.path.join(backend_app, "db", "models", "user.py"))
168
+ remove_file(os.path.join(backend_app, "repositories", "user.py"))
169
+ remove_file(os.path.join(backend_app, "services", "user.py"))
170
+ remove_file(os.path.join(backend_app, "schemas", "user.py"))
171
+ remove_file(os.path.join(backend_app, "schemas", "token.py"))
172
+
173
+ # --- Logfire setup file (when logfire is disabled) ---
174
+ if not enable_logfire:
175
+ remove_file(os.path.join(backend_app, "core", "logfire_setup.py"))
176
+
177
+ # --- Cleanup stub files (files with only docstring, no code) ---
178
+ core_dir = os.path.join(backend_app, "core")
179
+ for stub_candidate in ["security.py", "cache.py", "rate_limit.py", "oauth.py", "logfire_setup.py", "csrf.py"]:
180
+ filepath = os.path.join(core_dir, stub_candidate)
181
+ if is_stub_file(filepath):
182
+ remove_file(filepath)
183
+ print(f" Removed stub: {os.path.relpath(filepath)}")
184
+
132
185
  # --- Worker/Background tasks ---
133
186
  use_any_background_tasks = use_celery or use_taskiq or use_arq
134
187
  if not use_any_background_tasks:
@@ -13,6 +13,7 @@
13
13
  {%- if cookiecutter.enable_ai_agent and cookiecutter.use_pydantic_ai %}, PydanticAI{%- endif %}
14
14
  {%- if cookiecutter.enable_ai_agent and cookiecutter.use_langchain %}, LangChain{%- endif %}
15
15
  {%- if cookiecutter.enable_ai_agent and cookiecutter.use_langgraph %}, LangGraph{%- endif %}
16
+ {%- if cookiecutter.enable_ai_agent and cookiecutter.use_crewai %}, CrewAI{%- endif %}
16
17
  {%- if cookiecutter.use_celery %}, Celery{%- endif %}
17
18
  {%- if cookiecutter.use_taskiq %}, Taskiq{%- endif %}
18
19
  {%- if cookiecutter.use_frontend %}, Next.js 15{%- endif %}