fastapi-fullstack 0.1.2__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 (221) hide show
  1. fastapi_fullstack-0.1.2.dist-info/METADATA +545 -0
  2. fastapi_fullstack-0.1.2.dist-info/RECORD +221 -0
  3. fastapi_fullstack-0.1.2.dist-info/WHEEL +4 -0
  4. fastapi_fullstack-0.1.2.dist-info/entry_points.txt +2 -0
  5. fastapi_fullstack-0.1.2.dist-info/licenses/LICENSE +21 -0
  6. fastapi_gen/__init__.py +3 -0
  7. fastapi_gen/cli.py +256 -0
  8. fastapi_gen/config.py +255 -0
  9. fastapi_gen/generator.py +181 -0
  10. fastapi_gen/prompts.py +648 -0
  11. fastapi_gen/template/cookiecutter.json +76 -0
  12. fastapi_gen/template/hooks/post_gen_project.py +111 -0
  13. fastapi_gen/template/{{cookiecutter.project_slug}}/.env.example +136 -0
  14. fastapi_gen/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +150 -0
  15. fastapi_gen/template/{{cookiecutter.project_slug}}/.gitignore +108 -0
  16. fastapi_gen/template/{{cookiecutter.project_slug}}/CLAUDE.md +357 -0
  17. fastapi_gen/template/{{cookiecutter.project_slug}}/Makefile +298 -0
  18. fastapi_gen/template/{{cookiecutter.project_slug}}/README.md +723 -0
  19. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.dockerignore +60 -0
  20. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +32 -0
  21. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/Dockerfile +56 -0
  22. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +76 -0
  23. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +30 -0
  24. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
  25. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic.ini +48 -0
  26. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +3 -0
  27. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/admin.py +115 -0
  28. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +13 -0
  29. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +202 -0
  30. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +13 -0
  31. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +17 -0
  32. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +1 -0
  33. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +528 -0
  34. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +85 -0
  35. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +10 -0
  36. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +9 -0
  37. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +87 -0
  38. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +448 -0
  39. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +395 -0
  40. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +490 -0
  41. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +227 -0
  42. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +275 -0
  43. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +205 -0
  44. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +168 -0
  45. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +333 -0
  46. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +477 -0
  47. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +46 -0
  48. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +221 -0
  49. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +14 -0
  50. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +88 -0
  51. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +117 -0
  52. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +75 -0
  53. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +28 -0
  54. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +266 -0
  55. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +5 -0
  56. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +23 -0
  57. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +247 -0
  58. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +153 -0
  59. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +122 -0
  60. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +101 -0
  61. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +99 -0
  62. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +23 -0
  63. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +58 -0
  64. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +271 -0
  65. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +102 -0
  66. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +7 -0
  67. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +41 -0
  68. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +31 -0
  69. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +319 -0
  70. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +96 -0
  71. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +126 -0
  72. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +218 -0
  73. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +244 -0
  74. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +113 -0
  75. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/main.py +326 -0
  76. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +9 -0
  77. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +73 -0
  78. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +49 -0
  79. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +154 -0
  80. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +760 -0
  81. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +222 -0
  82. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +318 -0
  83. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +322 -0
  84. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +358 -0
  85. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +50 -0
  86. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +57 -0
  87. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +195 -0
  88. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +52 -0
  89. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +42 -0
  90. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +31 -0
  91. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +64 -0
  92. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +89 -0
  93. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +38 -0
  94. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +797 -0
  95. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +246 -0
  96. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +333 -0
  97. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +432 -0
  98. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +561 -0
  99. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +5 -0
  100. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +64 -0
  101. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +38 -0
  102. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +25 -0
  103. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +106 -0
  104. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +29 -0
  105. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +92 -0
  106. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +1 -0
  107. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +438 -0
  108. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +158 -0
  109. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
  110. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +1 -0
  111. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +1 -0
  112. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +242 -0
  113. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +151 -0
  114. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +113 -0
  115. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +310 -0
  116. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +253 -0
  117. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +151 -0
  118. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +121 -0
  119. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +183 -0
  120. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +173 -0
  121. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +143 -0
  122. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +118 -0
  123. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +181 -0
  124. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +124 -0
  125. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +363 -0
  126. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +85 -0
  127. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +242 -0
  128. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +31 -0
  129. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +382 -0
  130. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml +241 -0
  131. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.env.example +12 -0
  132. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.gitignore +45 -0
  133. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +19 -0
  134. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +11 -0
  135. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +44 -0
  136. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/README.md +693 -0
  137. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +49 -0
  138. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +134 -0
  139. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +207 -0
  140. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +73 -0
  141. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +14 -0
  142. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +84 -0
  143. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +84 -0
  144. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +76 -0
  145. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/package.json +66 -0
  146. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +101 -0
  147. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +7 -0
  148. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(auth)/layout.tsx +11 -0
  149. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(auth)/login/page.tsx +5 -0
  150. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(auth)/register/page.tsx +5 -0
  151. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/chat/page.tsx +20 -0
  152. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/dashboard/page.tsx +99 -0
  153. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/layout.tsx +17 -0
  154. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/profile/page.tsx +156 -0
  155. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +58 -0
  156. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +24 -0
  157. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +39 -0
  158. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +50 -0
  159. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +54 -0
  160. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +26 -0
  161. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +41 -0
  162. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +108 -0
  163. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +73 -0
  164. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +21 -0
  165. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/auth/callback/page.tsx +96 -0
  166. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +108 -0
  167. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +25 -0
  168. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/page.tsx +73 -0
  169. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +29 -0
  170. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +2 -0
  171. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +120 -0
  172. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +153 -0
  173. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +135 -0
  174. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +73 -0
  175. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +261 -0
  176. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +8 -0
  177. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +63 -0
  178. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +18 -0
  179. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +60 -0
  180. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +32 -0
  181. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +3 -0
  182. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +97 -0
  183. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +45 -0
  184. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +2 -0
  185. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +48 -0
  186. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +7 -0
  187. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +53 -0
  188. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +83 -0
  189. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +35 -0
  190. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +75 -0
  191. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +54 -0
  192. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +82 -0
  193. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +12 -0
  194. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +21 -0
  195. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +21 -0
  196. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +6 -0
  197. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +97 -0
  198. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +203 -0
  199. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +175 -0
  200. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +105 -0
  201. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +32 -0
  202. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +90 -0
  203. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +39 -0
  204. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +78 -0
  205. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +44 -0
  206. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +44 -0
  207. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +33 -0
  208. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +72 -0
  209. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +48 -0
  210. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +65 -0
  211. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +76 -0
  212. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +6 -0
  213. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +44 -0
  214. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +27 -0
  215. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +52 -0
  216. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +81 -0
  217. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +49 -0
  218. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +10 -0
  219. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +28 -0
  220. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +36 -0
  221. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +56 -0
@@ -0,0 +1,693 @@
1
+ # {{ cookiecutter.project_name }} - Frontend
2
+
3
+ <p align="center">
4
+ <img src="https://img.shields.io/badge/Next.js-15-black?logo=next.js&logoColor=white" alt="Next.js">
5
+ <img src="https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=white" alt="React">
6
+ <img src="https://img.shields.io/badge/TypeScript-5-3178C6?logo=typescript&logoColor=white" alt="TypeScript">
7
+ <img src="https://img.shields.io/badge/Tailwind-4-06B6D4?logo=tailwindcss&logoColor=white" alt="Tailwind">
8
+ <img src="https://img.shields.io/badge/Bun-latest-F9F1E1?logo=bun&logoColor=black" alt="Bun">
9
+ </p>
10
+
11
+ <p align="center">
12
+ Next.js 15 frontend for <b>{{ cookiecutter.project_name }}</b>
13
+ </p>
14
+
15
+ ---
16
+
17
+ ## Tech Stack
18
+
19
+ | Technology | Version | Purpose |
20
+ |------------|---------|---------|
21
+ | [Next.js](https://nextjs.org) | 15.x | React framework with App Router |
22
+ | [React](https://react.dev) | 19.x | UI library with Server Components |
23
+ | [TypeScript](https://www.typescriptlang.org) | 5.x | Type safety |
24
+ | [Tailwind CSS](https://tailwindcss.com) | 4.x | Utility-first styling |
25
+ | [Zustand](https://zustand-demo.pmnd.rs) | 5.x | State management |
26
+ | [TanStack Query](https://tanstack.com/query) | 5.x | Server state & data fetching |
27
+ | [Bun](https://bun.sh) | Latest | Package manager & runtime |
28
+
29
+ ---
30
+
31
+ ## Quick Start
32
+
33
+ ### Prerequisites
34
+
35
+ - [Bun](https://bun.sh) installed (`curl -fsSL https://bun.sh/install | bash`)
36
+
37
+ ### Installation
38
+
39
+ ```bash
40
+ # Install dependencies
41
+ bun install
42
+
43
+ # Copy environment file
44
+ cp .env.example .env.local
45
+ ```
46
+
47
+ ### Development
48
+
49
+ ```bash
50
+ bun dev
51
+ ```
52
+
53
+ Open [http://localhost:{{ cookiecutter.frontend_port }}](http://localhost:{{ cookiecutter.frontend_port }}) in your browser.
54
+
55
+ ### Build & Production
56
+
57
+ ```bash
58
+ # Build for production
59
+ bun build
60
+
61
+ # Start production server
62
+ bun start
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Project Structure
68
+
69
+ ```
70
+ frontend/
71
+ ├── src/
72
+ │ ├── app/ # Next.js App Router
73
+ │ │ ├── layout.tsx # Root layout
74
+ │ │ ├── page.tsx # Home page
75
+ │ │ ├── providers.tsx # Client providers (React Query, etc.)
76
+ │ │ ├── (auth)/ # Auth route group (public)
77
+ │ │ │ ├── layout.tsx
78
+ │ │ │ ├── login/page.tsx
79
+ │ │ │ └── register/page.tsx
80
+ │ │ ├── (dashboard)/ # Dashboard route group (protected)
81
+ │ │ │ ├── layout.tsx
82
+ │ │ │ ├── dashboard/page.tsx
83
+ {%- if cookiecutter.enable_ai_agent %}
84
+ │ │ │ ├── chat/page.tsx
85
+ {%- endif %}
86
+ │ │ │ └── profile/page.tsx
87
+ │ │ └── api/ # API routes (BFF proxy)
88
+ │ │ ├── auth/
89
+ │ │ │ ├── login/route.ts
90
+ │ │ │ ├── logout/route.ts
91
+ │ │ │ ├── register/route.ts
92
+ │ │ │ ├── refresh/route.ts
93
+ │ │ │ └── me/route.ts
94
+ {%- if cookiecutter.enable_conversation_persistence %}
95
+ │ │ └── conversations/
96
+ │ │ └── route.ts
97
+ {%- endif %}
98
+ │ │
99
+ │ ├── components/
100
+ │ │ ├── ui/ # Base UI components
101
+ │ │ │ ├── button.tsx
102
+ │ │ │ ├── input.tsx
103
+ │ │ │ ├── card.tsx
104
+ │ │ │ ├── badge.tsx
105
+ │ │ │ └── label.tsx
106
+ │ │ ├── layout/ # Layout components
107
+ │ │ │ ├── header.tsx
108
+ │ │ │ └── sidebar.tsx
109
+ │ │ ├── auth/ # Auth components
110
+ │ │ │ ├── login-form.tsx
111
+ │ │ │ └── register-form.tsx
112
+ {%- if cookiecutter.enable_ai_agent %}
113
+ │ │ ├── chat/ # Chat components
114
+ │ │ │ ├── chat-container.tsx
115
+ │ │ │ ├── chat-input.tsx
116
+ │ │ │ ├── message-list.tsx
117
+ │ │ │ ├── message-item.tsx
118
+ │ │ │ └── tool-call-card.tsx
119
+ {%- endif %}
120
+ │ │ └── theme/ # Theme components
121
+ │ │ ├── theme-provider.tsx
122
+ │ │ └── theme-toggle.tsx
123
+ │ │
124
+ │ ├── hooks/ # Custom React hooks
125
+ │ │ ├── use-auth.ts # Authentication hook
126
+ {%- if cookiecutter.enable_ai_agent %}
127
+ │ │ ├── use-websocket.ts # WebSocket connection
128
+ │ │ ├── use-chat.ts # Chat functionality
129
+ {%- endif %}
130
+ {%- if cookiecutter.enable_conversation_persistence %}
131
+ │ │ └── use-conversations.ts # Conversation management
132
+ {%- endif %}
133
+ │ │
134
+ │ ├── stores/ # Zustand state stores
135
+ │ │ ├── auth-store.ts # Auth state
136
+ │ │ ├── theme-store.ts # Theme state
137
+ {%- if cookiecutter.enable_ai_agent %}
138
+ │ │ └── chat-store.ts # Chat messages state
139
+ {%- endif %}
140
+ │ │
141
+ │ ├── lib/ # Utilities
142
+ │ │ ├── api-client.ts # Fetch wrapper
143
+ │ │ ├── server-api.ts # Server-side API calls
144
+ │ │ ├── utils.ts # Helper functions (cn, etc.)
145
+ │ │ └── constants.ts # App constants
146
+ │ │
147
+ │ ├── types/ # TypeScript types
148
+ │ │ ├── api.ts
149
+ │ │ ├── auth.ts
150
+ {%- if cookiecutter.enable_ai_agent %}
151
+ │ │ └── chat.ts
152
+ {%- endif %}
153
+ │ │
154
+ │ └── middleware.ts # Auth middleware
155
+
156
+ ├── e2e/ # Playwright E2E tests
157
+ │ ├── auth.setup.ts
158
+ │ ├── auth.spec.ts
159
+ │ ├── home.spec.ts
160
+ {%- if cookiecutter.enable_ai_agent %}
161
+ │ └── chat.spec.ts
162
+ {%- endif %}
163
+
164
+ {%- if cookiecutter.enable_i18n %}
165
+ ├── messages/ # i18n translations
166
+ │ ├── en.json
167
+ │ └── pl.json
168
+ {%- endif %}
169
+
170
+ ├── public/ # Static assets
171
+ ├── .env.example # Environment template
172
+ ├── next.config.ts
173
+ ├── tailwind.config.ts
174
+ ├── tsconfig.json
175
+ ├── playwright.config.ts
176
+ ├── vitest.config.ts
177
+ └── package.json
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Available Scripts
183
+
184
+ | Command | Description |
185
+ |---------|-------------|
186
+ | `bun dev` | Start development server (port {{ cookiecutter.frontend_port }}) |
187
+ | `bun build` | Build for production |
188
+ | `bun start` | Start production server |
189
+ | `bun lint` | Run ESLint |
190
+ | `bun lint:fix` | Fix ESLint issues |
191
+ | `bun format` | Format with Prettier |
192
+ | `bun type-check` | Run TypeScript type checking |
193
+ | `bun test` | Run unit tests (Vitest) |
194
+ | `bun test:run` | Run tests once (CI mode) |
195
+ | `bun test:coverage` | Run tests with coverage |
196
+ | `bun test:e2e` | Run E2E tests (Playwright) |
197
+ | `bun test:e2e:ui` | Run E2E tests with UI |
198
+ | `bun test:e2e:headed` | Run E2E tests in browser |
199
+
200
+ ---
201
+
202
+ ## Environment Variables
203
+
204
+ Create `.env.local` from `.env.example`:
205
+
206
+ ```bash
207
+ # Backend API URL (server-side only)
208
+ BACKEND_URL=http://localhost:{{ cookiecutter.backend_port }}
209
+
210
+ # WebSocket URL (client-side)
211
+ NEXT_PUBLIC_WS_URL=ws://localhost:{{ cookiecutter.backend_port }}/api/v1/agent/ws
212
+ {%- if cookiecutter.enable_logfire %}
213
+
214
+ # OpenTelemetry (Logfire)
215
+ OTEL_EXPORTER_OTLP_ENDPOINT=https://logfire-api.pydantic.dev
216
+ OTEL_EXPORTER_OTLP_HEADERS=Authorization=your-write-token
217
+ {%- endif %}
218
+ ```
219
+
220
+ ---
221
+
222
+ ## Authentication
223
+
224
+ ### How It Works
225
+
226
+ 1. **Login** - User submits credentials to `/api/auth/login`
227
+ 2. **BFF Proxy** - Next.js API route calls backend, receives JWT tokens
228
+ 3. **Cookies** - Tokens stored in HTTP-only cookies (secure)
229
+ 4. **Auto-refresh** - Tokens refreshed automatically before expiry
230
+ 5. **Middleware** - Protected routes check auth via middleware
231
+
232
+ ### Auth Store (Zustand)
233
+
234
+ ```typescript
235
+ // src/stores/auth-store.ts
236
+ import { useAuthStore } from '@/stores/auth-store';
237
+
238
+ // In components
239
+ const { user, isAuthenticated, logout } = useAuthStore();
240
+ ```
241
+
242
+ ### Auth Hook
243
+
244
+ ```typescript
245
+ // src/hooks/use-auth.ts
246
+ import { useAuth } from '@/hooks/use-auth';
247
+
248
+ function MyComponent() {
249
+ const { user, isLoading, login, logout } = useAuth();
250
+
251
+ // ...
252
+ }
253
+ ```
254
+
255
+ ### Protected Routes
256
+
257
+ Middleware automatically redirects unauthenticated users:
258
+
259
+ ```typescript
260
+ // src/middleware.ts
261
+ const protectedPaths = ['/dashboard', '/chat', '/profile'];
262
+ ```
263
+
264
+ ---
265
+ {%- if cookiecutter.enable_ai_agent %}
266
+
267
+ ## AI Chat
268
+
269
+ ### WebSocket Connection
270
+
271
+ The chat uses WebSocket for real-time streaming:
272
+
273
+ ```typescript
274
+ // src/hooks/use-chat.ts
275
+ import { useChat } from '@/hooks/use-chat';
276
+
277
+ function ChatPage() {
278
+ const { messages, isConnected, isStreaming, sendMessage } = useChat();
279
+
280
+ return (
281
+ <div>
282
+ <MessageList messages={messages} />
283
+ <ChatInput onSend={sendMessage} disabled={isStreaming} />
284
+ </div>
285
+ );
286
+ }
287
+ ```
288
+
289
+ ### Message Types
290
+
291
+ ```typescript
292
+ interface Message {
293
+ id: string;
294
+ role: 'user' | 'assistant' | 'tool';
295
+ content: string;
296
+ tool_name?: string;
297
+ created_at: Date;
298
+ }
299
+
300
+ interface StreamEvent {
301
+ type: 'start' | 'token' | 'tool_call' | 'end' | 'error';
302
+ content?: string;
303
+ tool?: { name: string; args: Record<string, unknown> };
304
+ }
305
+ ```
306
+
307
+ ### Components
308
+
309
+ | Component | Description |
310
+ |-----------|-------------|
311
+ | `ChatContainer` | Main chat wrapper with WebSocket |
312
+ | `ChatInput` | Message input with send button |
313
+ | `MessageList` | Scrollable message container |
314
+ | `MessageItem` | Single message bubble |
315
+ | `ToolCallCard` | Tool invocation display |
316
+
317
+ ---
318
+ {%- endif %}
319
+
320
+ ## UI Components
321
+
322
+ Pre-built components following shadcn/ui patterns:
323
+
324
+ ### Button
325
+
326
+ ```tsx
327
+ import { Button } from '@/components/ui/button';
328
+
329
+ <Button variant="default">Click me</Button>
330
+ <Button variant="destructive">Delete</Button>
331
+ <Button variant="outline">Cancel</Button>
332
+ <Button variant="ghost">Ghost</Button>
333
+ <Button size="sm">Small</Button>
334
+ <Button size="lg">Large</Button>
335
+ ```
336
+
337
+ ### Input
338
+
339
+ ```tsx
340
+ import { Input } from '@/components/ui/input';
341
+ import { Label } from '@/components/ui/label';
342
+
343
+ <div>
344
+ <Label htmlFor="email">Email</Label>
345
+ <Input id="email" type="email" placeholder="you@example.com" />
346
+ </div>
347
+ ```
348
+
349
+ ### Card
350
+
351
+ ```tsx
352
+ import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
353
+
354
+ <Card>
355
+ <CardHeader>
356
+ <CardTitle>Title</CardTitle>
357
+ </CardHeader>
358
+ <CardContent>
359
+ Content here...
360
+ </CardContent>
361
+ </Card>
362
+ ```
363
+
364
+ ---
365
+
366
+ ## State Management
367
+
368
+ ### Zustand Stores
369
+
370
+ ```typescript
371
+ // Creating a store
372
+ import { create } from 'zustand';
373
+ import { persist } from 'zustand/middleware';
374
+
375
+ interface CounterState {
376
+ count: number;
377
+ increment: () => void;
378
+ decrement: () => void;
379
+ }
380
+
381
+ export const useCounterStore = create<CounterState>()(
382
+ persist(
383
+ (set) => ({
384
+ count: 0,
385
+ increment: () => set((state) => ({ count: state.count + 1 })),
386
+ decrement: () => set((state) => ({ count: state.count - 1 })),
387
+ }),
388
+ { name: 'counter-storage' }
389
+ )
390
+ );
391
+ ```
392
+
393
+ ### Available Stores
394
+
395
+ | Store | Purpose |
396
+ |-------|---------|
397
+ | `auth-store` | User authentication state |
398
+ | `theme-store` | Dark/light mode preference |
399
+ {%- if cookiecutter.enable_ai_agent %}
400
+ | `chat-store` | Chat messages and state |
401
+ {%- endif %}
402
+ {%- if cookiecutter.enable_conversation_persistence %}
403
+ | `conversation-store` | Conversation list and selection |
404
+ {%- endif %}
405
+
406
+ ---
407
+
408
+ ## Dark Mode
409
+
410
+ Theme switching with system preference detection:
411
+
412
+ ```tsx
413
+ import { useThemeStore } from '@/stores/theme-store';
414
+ import { ThemeToggle } from '@/components/theme/theme-toggle';
415
+
416
+ // Toggle component
417
+ <ThemeToggle />
418
+
419
+ // Manual control
420
+ const { theme, setTheme } = useThemeStore();
421
+ setTheme('dark'); // 'light' | 'dark' | 'system'
422
+ ```
423
+
424
+ ---
425
+ {%- if cookiecutter.enable_logfire %}
426
+
427
+ ## Logfire Observability
428
+
429
+ [Logfire](https://logfire.pydantic.dev) provides frontend observability through OpenTelemetry instrumentation.
430
+
431
+ ### What Gets Traced
432
+
433
+ - **Page navigations** - Route changes and load times
434
+ - **API calls** - Fetch requests to backend
435
+ - **Web Vitals** - Core Web Vitals metrics (LCP, FID, CLS)
436
+ - **Errors** - Client-side exceptions
437
+
438
+ ### Configuration
439
+
440
+ Set environment variables in `.env.local`:
441
+
442
+ ```bash
443
+ OTEL_EXPORTER_OTLP_ENDPOINT=https://logfire-api.pydantic.dev
444
+ OTEL_EXPORTER_OTLP_HEADERS=Authorization=your-write-token
445
+ ```
446
+
447
+ ### Manual Instrumentation
448
+
449
+ ```typescript
450
+ import { trace } from '@opentelemetry/api';
451
+
452
+ const tracer = trace.getTracer('frontend');
453
+
454
+ async function processCheckout(order: Order) {
455
+ const span = tracer.startSpan('checkout.process');
456
+ try {
457
+ span.setAttribute('order.id', order.id);
458
+ await submitOrder(order);
459
+ span.setStatus({ code: SpanStatusCode.OK });
460
+ } catch (error) {
461
+ span.setStatus({ code: SpanStatusCode.ERROR });
462
+ throw error;
463
+ } finally {
464
+ span.end();
465
+ }
466
+ }
467
+ ```
468
+
469
+ > 📚 For more details, see [Logfire Browser Integration](https://logfire.pydantic.dev/docs/integrations/browser/).
470
+ {%- endif %}
471
+
472
+ ---
473
+ {%- if cookiecutter.enable_i18n %}
474
+
475
+ ## Internationalization (i18n)
476
+
477
+ Using `next-intl` for translations:
478
+
479
+ ### Translation Files
480
+
481
+ ```json
482
+ // messages/en.json
483
+ {
484
+ "common": {
485
+ "login": "Login",
486
+ "logout": "Logout"
487
+ },
488
+ "auth": {
489
+ "email": "Email",
490
+ "password": "Password"
491
+ }
492
+ }
493
+ ```
494
+
495
+ ### Usage in Components
496
+
497
+ ```tsx
498
+ import { useTranslations } from 'next-intl';
499
+
500
+ function LoginForm() {
501
+ const t = useTranslations('auth');
502
+
503
+ return (
504
+ <form>
505
+ <Label>{t('email')}</Label>
506
+ <Input name="email" />
507
+ </form>
508
+ );
509
+ }
510
+ ```
511
+
512
+ ### Language Switcher
513
+
514
+ ```tsx
515
+ import { LanguageSwitcher } from '@/components/language-switcher';
516
+
517
+ <LanguageSwitcher />
518
+ ```
519
+
520
+ ---
521
+ {%- endif %}
522
+
523
+ ## Testing
524
+
525
+ ### Unit Tests (Vitest)
526
+
527
+ ```bash
528
+ # Run tests
529
+ bun test
530
+
531
+ # Watch mode
532
+ bun test --watch
533
+
534
+ # With coverage
535
+ bun test:coverage
536
+
537
+ # UI mode
538
+ bun test:ui
539
+ ```
540
+
541
+ Example test:
542
+
543
+ ```typescript
544
+ // src/lib/utils.test.ts
545
+ import { describe, it, expect } from 'vitest';
546
+ import { cn } from './utils';
547
+
548
+ describe('cn utility', () => {
549
+ it('merges class names', () => {
550
+ expect(cn('foo', 'bar')).toBe('foo bar');
551
+ });
552
+ });
553
+ ```
554
+
555
+ ### E2E Tests (Playwright)
556
+
557
+ ```bash
558
+ # Run all E2E tests
559
+ bun test:e2e
560
+
561
+ # With browser UI
562
+ bun test:e2e:ui
563
+
564
+ # Headed mode (see browser)
565
+ bun test:e2e:headed
566
+
567
+ # Debug mode
568
+ bun test:e2e:debug
569
+
570
+ # Show report
571
+ bun test:e2e:report
572
+ ```
573
+
574
+ Example test:
575
+
576
+ ```typescript
577
+ // e2e/auth.spec.ts
578
+ import { test, expect } from '@playwright/test';
579
+
580
+ test('should login successfully', async ({ page }) => {
581
+ await page.goto('/login');
582
+ await page.fill('input[name="email"]', 'test@example.com');
583
+ await page.fill('input[name="password"]', 'password123');
584
+ await page.click('button[type="submit"]');
585
+
586
+ await expect(page).toHaveURL('/dashboard');
587
+ });
588
+ ```
589
+
590
+ ---
591
+
592
+ ## API Proxy (BFF Pattern)
593
+
594
+ All API calls go through Next.js API routes to:
595
+
596
+ 1. **Hide backend URL** from browser
597
+ 2. **Handle cookies** securely (HTTP-only)
598
+ 3. **Add auth headers** automatically
599
+ 4. **Transform responses** if needed
600
+
601
+ ### Example API Route
602
+
603
+ ```typescript
604
+ // src/app/api/auth/login/route.ts
605
+ import { NextRequest, NextResponse } from 'next/server';
606
+ import { cookies } from 'next/headers';
607
+
608
+ const API_URL = process.env.BACKEND_URL;
609
+
610
+ export async function POST(request: NextRequest) {
611
+ const body = await request.json();
612
+
613
+ const res = await fetch(`${API_URL}/api/v1/auth/login`, {
614
+ method: 'POST',
615
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
616
+ body: new URLSearchParams({
617
+ username: body.email,
618
+ password: body.password,
619
+ }),
620
+ });
621
+
622
+ if (!res.ok) {
623
+ return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 });
624
+ }
625
+
626
+ const data = await res.json();
627
+
628
+ // Set HTTP-only cookies
629
+ const cookieStore = await cookies();
630
+ cookieStore.set('access_token', data.access_token, {
631
+ httpOnly: true,
632
+ secure: process.env.NODE_ENV === 'production',
633
+ sameSite: 'lax',
634
+ maxAge: 60 * 30,
635
+ });
636
+
637
+ return NextResponse.json({ user: data.user });
638
+ }
639
+ ```
640
+
641
+ ---
642
+
643
+ ## Deployment
644
+
645
+ ### Docker
646
+
647
+ ```dockerfile
648
+ # Dockerfile
649
+ FROM oven/bun:1 AS builder
650
+ WORKDIR /app
651
+ COPY package.json bun.lockb ./
652
+ RUN bun install --frozen-lockfile
653
+ COPY . .
654
+ RUN bun build
655
+
656
+ FROM oven/bun:1-slim
657
+ WORKDIR /app
658
+ COPY --from=builder /app/.next ./.next
659
+ COPY --from=builder /app/public ./public
660
+ COPY --from=builder /app/package.json ./
661
+ CMD ["bun", "start"]
662
+ ```
663
+
664
+ ### Environment Variables for Production
665
+
666
+ ```bash
667
+ BACKEND_URL=https://api.your-domain.com
668
+ NEXT_PUBLIC_WS_URL=wss://api.your-domain.com/api/v1/agent/ws
669
+ NODE_ENV=production
670
+ ```
671
+
672
+ ---
673
+
674
+ ## Documentation
675
+
676
+ | Resource | Link |
677
+ |----------|------|
678
+ | Template Repository | [github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template](https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template) |
679
+ | Frontend Guide | [docs/frontend.md](https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template/blob/main/docs/frontend.md) |
680
+ {%- if cookiecutter.enable_ai_agent %}
681
+ | AI Agent Guide | [docs/ai-agent.md](https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template/blob/main/docs/ai-agent.md) |
682
+ {%- endif %}
683
+ {%- if cookiecutter.enable_logfire %}
684
+ | Observability Guide | [docs/observability.md](https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template/blob/main/docs/observability.md) |
685
+ {%- endif %}
686
+ | Next.js Docs | [nextjs.org/docs](https://nextjs.org/docs) |
687
+ | Tailwind CSS Docs | [tailwindcss.com/docs](https://tailwindcss.com/docs) |
688
+
689
+ ---
690
+
691
+ ## License
692
+
693
+ MIT