@leanspec/ui 0.2.5-dev.20251120070726 → 0.2.5-dev.20251120093243

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 (361) hide show
  1. package/.next/standalone/packages/ui/.next/BUILD_ID +1 -1
  2. package/.next/standalone/packages/ui/.next/app-path-routes-manifest.json +12 -0
  3. package/.next/standalone/packages/ui/.next/build-manifest.json +7 -6
  4. package/.next/standalone/packages/ui/.next/prerender-manifest.json +28 -3
  5. package/.next/standalone/packages/ui/.next/routes-manifest.json +91 -0
  6. package/.next/standalone/packages/ui/.next/server/app/_global-error/page/build-manifest.json +5 -4
  7. package/.next/standalone/packages/ui/.next/server/app/_global-error/page.js +1 -1
  8. package/.next/standalone/packages/ui/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/standalone/packages/ui/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/packages/ui/.next/server/app/_global-error.html +2 -2
  11. package/.next/standalone/packages/ui/.next/server/app/_global-error.rsc +1 -1
  12. package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  13. package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  15. package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/.next/standalone/packages/ui/.next/server/app/_not-found/page/build-manifest.json +5 -4
  17. package/.next/standalone/packages/ui/.next/server/app/_not-found/page.js +2 -2
  18. package/.next/standalone/packages/ui/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/.next/standalone/packages/ui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/packages/ui/.next/server/app/_not-found.html +2 -2
  21. package/.next/standalone/packages/ui/.next/server/app/_not-found.rsc +20 -19
  22. package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_full.segment.rsc +20 -19
  23. package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_index.segment.rsc +26 -25
  24. package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +3 -3
  25. package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  26. package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_tree.segment.rsc +5 -5
  27. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route/app-paths-manifest.json +3 -0
  28. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route/build-manifest.json +11 -0
  29. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route/server-reference-manifest.json +4 -0
  30. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js +6 -0
  31. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js.map +5 -0
  32. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js.nft.json +1 -0
  33. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route_client-reference-manifest.js +2 -0
  34. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route/app-paths-manifest.json +3 -0
  35. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route/build-manifest.json +11 -0
  36. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route/server-reference-manifest.json +4 -0
  37. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js +6 -0
  38. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js.map +5 -0
  39. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js.nft.json +1 -0
  40. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route_client-reference-manifest.js +2 -0
  41. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/app-paths-manifest.json +3 -0
  42. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/build-manifest.json +11 -0
  43. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/server-reference-manifest.json +4 -0
  44. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js +6 -0
  45. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js.map +5 -0
  46. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js.nft.json +1 -0
  47. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route_client-reference-manifest.js +2 -0
  48. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route/app-paths-manifest.json +3 -0
  49. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route/build-manifest.json +11 -0
  50. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route/server-reference-manifest.json +4 -0
  51. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js +6 -0
  52. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js.map +5 -0
  53. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js.nft.json +1 -0
  54. package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route_client-reference-manifest.js +2 -0
  55. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/app-paths-manifest.json +3 -0
  56. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/build-manifest.json +11 -0
  57. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/server-reference-manifest.json +4 -0
  58. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js +8 -0
  59. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js.map +5 -0
  60. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js.nft.json +1 -0
  61. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route_client-reference-manifest.js +2 -0
  62. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/app-paths-manifest.json +3 -0
  63. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/build-manifest.json +11 -0
  64. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/server-reference-manifest.json +4 -0
  65. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js +9 -0
  66. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js.map +5 -0
  67. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js.nft.json +1 -0
  68. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route_client-reference-manifest.js +2 -0
  69. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/app-paths-manifest.json +3 -0
  70. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/build-manifest.json +11 -0
  71. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/server-reference-manifest.json +4 -0
  72. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js +8 -0
  73. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js.map +5 -0
  74. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js.nft.json +1 -0
  75. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route_client-reference-manifest.js +2 -0
  76. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/route.js +4 -2
  77. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/route.js.nft.json +1 -1
  78. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/app-paths-manifest.json +3 -0
  79. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/build-manifest.json +11 -0
  80. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/server-reference-manifest.json +4 -0
  81. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js +8 -0
  82. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js.map +5 -0
  83. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js.nft.json +1 -0
  84. package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route_client-reference-manifest.js +2 -0
  85. package/.next/standalone/packages/ui/.next/server/app/api/projects/route.js +3 -2
  86. package/.next/standalone/packages/ui/.next/server/app/api/projects/route.js.nft.json +1 -1
  87. package/.next/standalone/packages/ui/.next/server/app/api/revalidate/route.js +4 -2
  88. package/.next/standalone/packages/ui/.next/server/app/api/revalidate/route.js.nft.json +1 -1
  89. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/dependency-graph/route.js +4 -2
  90. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/dependency-graph/route.js.nft.json +1 -1
  91. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/route.js +4 -2
  92. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/route.js.nft.json +1 -1
  93. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/status/route.js +4 -3
  94. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/status/route.js.nft.json +1 -1
  95. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/subspecs/[file]/route.js +4 -2
  96. package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/subspecs/[file]/route.js.nft.json +1 -1
  97. package/.next/standalone/packages/ui/.next/server/app/api/stats/route.js +4 -2
  98. package/.next/standalone/packages/ui/.next/server/app/api/stats/route.js.nft.json +1 -1
  99. package/.next/standalone/packages/ui/.next/server/app/page/build-manifest.json +5 -4
  100. package/.next/standalone/packages/ui/.next/server/app/page.js +2 -2
  101. package/.next/standalone/packages/ui/.next/server/app/page.js.nft.json +1 -1
  102. package/.next/standalone/packages/ui/.next/server/app/page_client-reference-manifest.js +1 -1
  103. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/app-paths-manifest.json +3 -0
  104. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/build-manifest.json +18 -0
  105. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/next-font-manifest.json +6 -0
  106. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/react-loadable-manifest.json +1 -0
  107. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/server-reference-manifest.json +4 -0
  108. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js +21 -0
  109. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js.map +5 -0
  110. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js.nft.json +1 -0
  111. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page_client-reference-manifest.js +2 -0
  112. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/app-paths-manifest.json +3 -0
  113. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/build-manifest.json +18 -0
  114. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/next-font-manifest.json +6 -0
  115. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/react-loadable-manifest.json +1 -0
  116. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/server-reference-manifest.json +4 -0
  117. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js +21 -0
  118. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js.map +5 -0
  119. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js.nft.json +1 -0
  120. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page_client-reference-manifest.js +2 -0
  121. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/app-paths-manifest.json +3 -0
  122. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/build-manifest.json +18 -0
  123. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/next-font-manifest.json +6 -0
  124. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/react-loadable-manifest.json +1 -0
  125. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/server-reference-manifest.json +4 -0
  126. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js +20 -0
  127. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js.map +5 -0
  128. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js.nft.json +1 -0
  129. package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page_client-reference-manifest.js +2 -0
  130. package/.next/standalone/packages/ui/.next/server/app/projects/page/app-paths-manifest.json +3 -0
  131. package/.next/standalone/packages/ui/.next/server/app/projects/page/build-manifest.json +18 -0
  132. package/.next/standalone/packages/ui/.next/server/app/projects/page/next-font-manifest.json +6 -0
  133. package/.next/standalone/packages/ui/.next/server/app/projects/page/react-loadable-manifest.json +1 -0
  134. package/.next/standalone/packages/ui/.next/server/app/projects/page/server-reference-manifest.json +4 -0
  135. package/.next/standalone/packages/ui/.next/server/app/projects/page.js +19 -0
  136. package/.next/standalone/packages/ui/.next/server/app/projects/page.js.map +5 -0
  137. package/.next/standalone/packages/ui/.next/server/app/projects/page.js.nft.json +1 -0
  138. package/.next/standalone/packages/ui/.next/server/app/projects/page_client-reference-manifest.js +2 -0
  139. package/.next/standalone/packages/ui/.next/server/app/projects.html +2 -0
  140. package/.next/standalone/packages/ui/.next/server/app/projects.meta +14 -0
  141. package/.next/standalone/packages/ui/.next/server/app/projects.rsc +34 -0
  142. package/.next/standalone/packages/ui/.next/server/app/projects.segments/_full.segment.rsc +34 -0
  143. package/.next/standalone/packages/ui/.next/server/app/projects.segments/_index.segment.rsc +27 -0
  144. package/.next/standalone/packages/ui/.next/server/app/projects.segments/_tree.segment.rsc +9 -0
  145. package/.next/standalone/packages/ui/.next/server/app/projects.segments/projects/__PAGE__.segment.rsc +9 -0
  146. package/.next/standalone/packages/ui/.next/server/app/projects.segments/projects.segment.rsc +4 -0
  147. package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page/build-manifest.json +5 -4
  148. package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page.js +4 -4
  149. package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page.js.nft.json +1 -1
  150. package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page_client-reference-manifest.js +1 -1
  151. package/.next/standalone/packages/ui/.next/server/app/specs/page/build-manifest.json +5 -4
  152. package/.next/standalone/packages/ui/.next/server/app/specs/page.js +2 -2
  153. package/.next/standalone/packages/ui/.next/server/app/specs/page.js.nft.json +1 -1
  154. package/.next/standalone/packages/ui/.next/server/app/specs/page_client-reference-manifest.js +1 -1
  155. package/.next/standalone/packages/ui/.next/server/app/stats/page/build-manifest.json +5 -4
  156. package/.next/standalone/packages/ui/.next/server/app/stats/page.js +2 -2
  157. package/.next/standalone/packages/ui/.next/server/app/stats/page.js.nft.json +1 -1
  158. package/.next/standalone/packages/ui/.next/server/app/stats/page_client-reference-manifest.js +1 -1
  159. package/.next/standalone/packages/ui/.next/server/app-paths-manifest.json +12 -0
  160. package/.next/standalone/packages/ui/.next/server/chunks/6681a__next-internal_server_app_api_projects_[id]_specs_[spec]_route_actions_d018d9e0.js +3 -0
  161. package/.next/standalone/packages/ui/.next/server/chunks/730ea_ui__next-internal_server_app_api_local-projects_[id]_route_actions_664abe9c.js +3 -0
  162. package/.next/standalone/packages/ui/.next/server/chunks/730ea_ui__next-internal_server_app_api_local-projects_discover_route_actions_e6ec3fa7.js +3 -0
  163. package/.next/standalone/packages/ui/.next/server/chunks/730ea_ui__next-internal_server_app_api_projects_[id]_stats_route_actions_a0bb04a8.js +3 -0
  164. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__0fbfea15._.js +3 -0
  165. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__126dea7b._.js +3 -0
  166. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__1f037512._.js +3 -0
  167. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__3559376c._.js +21 -0
  168. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__548e27d4._.js +3 -0
  169. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__65667b70._.js +3 -0
  170. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__675a763e._.js +3 -0
  171. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__803d07f0._.js +3 -0
  172. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__8075fe29._.js +3 -0
  173. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__8233e09b._.js +3 -0
  174. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__84cdc14a._.js +3 -0
  175. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__9ce722b4._.js +3 -0
  176. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__a2d7cbed._.js +3 -0
  177. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__aa677b0d._.js +3 -0
  178. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__ac744182._.js +3 -0
  179. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__bb9fca84._.js +4 -0
  180. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__bdc3963a._.js +3 -0
  181. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__f5c6d6b8._.js +3 -0
  182. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__fb91986f._.js +3 -0
  183. package/.next/standalone/packages/ui/.next/server/chunks/f825c_server_app_api_local-projects_list-directory_route_actions_d620ec1a.js +3 -0
  184. package/.next/standalone/packages/ui/.next/server/chunks/f825c_server_app_api_projects_[id]_specs_[spec]_status_route_actions_e9f1bdc5.js +3 -0
  185. package/.next/standalone/packages/ui/.next/server/chunks/node_modules__pnpm_731b55aa._.js +3 -0
  186. package/.next/standalone/packages/ui/.next/server/chunks/packages_ui__next-internal_server_app_api_local-projects_route_actions_9142d5ad.js +3 -0
  187. package/.next/standalone/packages/ui/.next/server/chunks/packages_ui__next-internal_server_app_api_projects_[id]_route_actions_bff49675.js +3 -0
  188. package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_db_index_ts_556307fa._.js +64 -5
  189. package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_specs_sources_database-source_ts_0bd881ee._.js +3 -0
  190. package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_specs_sources_database-source_ts_baa0160d._.js +3 -0
  191. package/.next/standalone/packages/ui/.next/server/chunks/ssr/38a22_sonner_dist_index_mjs_207730fe._.js +3 -0
  192. package/.next/standalone/packages/ui/.next/server/chunks/ssr/6e9bd_next_dist_7af75658._.js +3 -0
  193. package/.next/standalone/packages/ui/.next/server/chunks/ssr/{_a5b58449._.js → 6e9bd_next_dist_df5dcbe9._.js} +2 -2
  194. package/.next/standalone/packages/ui/.next/server/chunks/ssr/730ea_ui__next-internal_server_app_projects_[projectId]_specs_page_actions_82e32fe4.js +3 -0
  195. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__01bfc8ff._.js +3 -0
  196. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__1d0c2012._.js +1 -1
  197. package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__41f5b5c0._.js → [root-of-the-server]__4ec37765._.js} +2 -2
  198. package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__1af33d49._.js → [root-of-the-server]__50122e7e._.js} +2 -2
  199. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__5382b397._.js +3 -0
  200. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__73f60f12._.js +7 -0
  201. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__88a691ee._.js +3 -0
  202. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__a7ae8552._.js +7 -0
  203. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__bdbbba01._.js +3 -0
  204. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__c592f5d1._.js +3 -0
  205. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__cc589a54._.js +3 -0
  206. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__ec5b96a5._.js +3 -0
  207. package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__cbbbfb5d._.js → [root-of-the-server]__fd80e4dd._.js} +2 -2
  208. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_000dd317._.js +1 -1
  209. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_196b5a83._.js +3 -0
  210. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_39562b2a._.js +4 -0
  211. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_3b617676._.js +1 -1
  212. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_4129cc0f._.js +3 -0
  213. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6174313a._.js +3 -0
  214. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6e4dd8b6._.js +3 -0
  215. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_85effc18._.js +4 -0
  216. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_ad8c1e99._.js +1 -1
  217. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_bae6d2b8._.js +4 -0
  218. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_c2f54661._.js +5 -0
  219. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_fdd7780b._.js +4 -0
  220. package/.next/standalone/packages/ui/.next/server/chunks/ssr/f825c_server_app_projects_[projectId]_specs_[specId]_page_actions_22d9c35e.js +3 -0
  221. package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_af9d3830._.js +3 -0
  222. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui__next-internal_server_app_projects_[projectId]_page_actions_f2986585.js +3 -0
  223. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui__next-internal_server_app_projects_page_actions_715940ea.js +3 -0
  224. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_[projectId]_be242d6c._.js +3 -0
  225. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_[projectId]_project-context-syncer_tsx_7954ea3b._.js +3 -0
  226. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_page_tsx_6e166c8e._.js +3 -0
  227. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_specs_specs-client_tsx_0bb8f8f8._.js +1 -1
  228. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_components_ui_select_tsx_7e21d40f._.js +3 -0
  229. package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_lib_specs_sources_database-source_ts_f7186c2a._.js +60 -1
  230. package/.next/standalone/packages/ui/.next/server/middleware-build-manifest.js +5 -4
  231. package/.next/standalone/packages/ui/.next/server/pages/404.html +2 -2
  232. package/.next/standalone/packages/ui/.next/server/pages/500.html +2 -2
  233. package/.next/standalone/packages/ui/.next/server/server-reference-manifest.js +1 -1
  234. package/.next/standalone/packages/ui/.next/server/server-reference-manifest.json +1 -1
  235. package/.next/standalone/packages/ui/.next/static/chunks/07f48b316e895080.js +1 -0
  236. package/.next/standalone/packages/ui/.next/static/chunks/0a7be410b438418a.js +1 -0
  237. package/.next/standalone/packages/ui/.next/static/chunks/1089ca88f6bef846.js +1 -0
  238. package/.next/standalone/packages/ui/.next/static/chunks/17471c87082c392c.js +5 -0
  239. package/.next/standalone/packages/ui/.next/static/chunks/220ba5cb8fe4dd69.js +1 -0
  240. package/.next/standalone/packages/ui/.next/static/chunks/35ccd3286e538bd2.js +1 -0
  241. package/.next/standalone/packages/ui/.next/static/chunks/571033caca823138.js +1 -0
  242. package/.next/standalone/packages/ui/.next/static/chunks/5a6fc30cd64085b4.css +1 -0
  243. package/.next/standalone/packages/ui/.next/static/chunks/5c2072ad938de8ed.js +1 -0
  244. package/.next/standalone/packages/ui/.next/static/chunks/843e1dfdc28e1385.js +1 -0
  245. package/.next/standalone/packages/ui/.next/static/chunks/9dad7fd31627df80.js +1 -0
  246. package/.next/standalone/packages/ui/.next/static/chunks/{c3d4d07de959ecf1.js → a055d4b2866ff8d4.js} +1 -1
  247. package/.next/standalone/packages/ui/.next/static/chunks/afb7c5a4255f4081.js +3 -0
  248. package/.next/{static/chunks/c557ac675be79771.js → standalone/packages/ui/.next/static/chunks/b760a3a9c2c8be28.js} +1 -1
  249. package/.next/standalone/packages/ui/.next/static/chunks/dcdd95180149fa10.js +1 -0
  250. package/.next/standalone/packages/ui/.next/static/chunks/ebd89051637b9a47.js +4 -0
  251. package/.next/standalone/packages/ui/.next/static/chunks/f9db24028d8c058e.js +1 -0
  252. package/.next/standalone/packages/ui/.next/static/chunks/fb640f50455ba34f.js +1 -0
  253. package/.next/standalone/packages/ui/.next/static/chunks/turbopack-b9690cacbf9fe48c.js +3 -0
  254. package/.next/standalone/packages/ui/bin/ui.js +17 -7
  255. package/.next/standalone/packages/ui/package.json +3 -1
  256. package/.next/standalone/packages/ui/src/app/api/local-projects/[id]/route.ts +117 -0
  257. package/.next/standalone/packages/ui/src/app/api/local-projects/discover/route.ts +41 -0
  258. package/.next/standalone/packages/ui/src/app/api/local-projects/list-directory/route.ts +38 -0
  259. package/.next/standalone/packages/ui/src/app/api/local-projects/route.ts +63 -0
  260. package/.next/standalone/packages/ui/src/app/api/projects/[id]/route.ts +97 -0
  261. package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/[spec]/route.ts +38 -0
  262. package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/[spec]/status/route.ts +97 -0
  263. package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/route.ts +7 -0
  264. package/.next/standalone/packages/ui/src/app/api/projects/[id]/stats/route.ts +19 -0
  265. package/.next/standalone/packages/ui/src/app/api/projects/route.ts +48 -1
  266. package/.next/standalone/packages/ui/src/app/dashboard-client.tsx +67 -6
  267. package/.next/standalone/packages/ui/src/app/layout.tsx +11 -8
  268. package/.next/standalone/packages/ui/src/app/not-found.tsx +1 -1
  269. package/.next/standalone/packages/ui/src/app/projects/[projectId]/layout.tsx +18 -0
  270. package/.next/standalone/packages/ui/src/app/projects/[projectId]/page.tsx +10 -0
  271. package/.next/standalone/packages/ui/src/app/projects/[projectId]/project-context-syncer.tsx +16 -0
  272. package/.next/standalone/packages/ui/src/app/projects/[projectId]/specs/[specId]/page.tsx +34 -0
  273. package/.next/standalone/packages/ui/src/app/projects/[projectId]/specs/page.tsx +20 -0
  274. package/.next/standalone/packages/ui/src/app/projects/page.tsx +156 -0
  275. package/.next/standalone/packages/ui/src/app/specs/specs-client.tsx +7 -2
  276. package/.next/standalone/packages/ui/src/components/create-project-dialog.tsx +139 -0
  277. package/.next/standalone/packages/ui/src/components/directory-picker.tsx +191 -0
  278. package/.next/standalone/packages/ui/src/components/main-sidebar.tsx +4 -0
  279. package/.next/standalone/packages/ui/src/components/project-switcher.tsx +139 -0
  280. package/.next/standalone/packages/ui/src/components/ui/dropdown-menu.tsx +200 -0
  281. package/.next/standalone/packages/ui/src/components/ui/popover.tsx +31 -0
  282. package/.next/standalone/packages/ui/src/contexts/project-context.tsx +229 -0
  283. package/.next/standalone/packages/ui/src/lib/db/index.ts +100 -0
  284. package/.next/standalone/packages/ui/src/lib/projects/index.ts +7 -0
  285. package/.next/standalone/packages/ui/src/lib/projects/registry.ts +467 -0
  286. package/.next/standalone/packages/ui/src/lib/projects/types.ts +37 -0
  287. package/.next/standalone/packages/ui/src/lib/specs/service.ts +13 -1
  288. package/.next/standalone/packages/ui/src/lib/specs/sources/multi-project-source.ts +258 -0
  289. package/.next/standalone/packages/ui/tsconfig.tsbuildinfo +1 -1
  290. package/.next/static/chunks/07f48b316e895080.js +1 -0
  291. package/.next/static/chunks/0a7be410b438418a.js +1 -0
  292. package/.next/static/chunks/1089ca88f6bef846.js +1 -0
  293. package/.next/static/chunks/17471c87082c392c.js +5 -0
  294. package/.next/static/chunks/220ba5cb8fe4dd69.js +1 -0
  295. package/.next/static/chunks/35ccd3286e538bd2.js +1 -0
  296. package/.next/static/chunks/571033caca823138.js +1 -0
  297. package/.next/static/chunks/5a6fc30cd64085b4.css +1 -0
  298. package/.next/static/chunks/5c2072ad938de8ed.js +1 -0
  299. package/.next/static/chunks/843e1dfdc28e1385.js +1 -0
  300. package/.next/static/chunks/9dad7fd31627df80.js +1 -0
  301. package/.next/static/chunks/{c3d4d07de959ecf1.js → a055d4b2866ff8d4.js} +1 -1
  302. package/.next/static/chunks/afb7c5a4255f4081.js +3 -0
  303. package/.next/{standalone/packages/ui/.next/static/chunks/c557ac675be79771.js → static/chunks/b760a3a9c2c8be28.js} +1 -1
  304. package/.next/static/chunks/dcdd95180149fa10.js +1 -0
  305. package/.next/static/chunks/ebd89051637b9a47.js +4 -0
  306. package/.next/static/chunks/f9db24028d8c058e.js +1 -0
  307. package/.next/static/chunks/fb640f50455ba34f.js +1 -0
  308. package/.next/static/chunks/turbopack-b9690cacbf9fe48c.js +3 -0
  309. package/bin/ui.js +17 -7
  310. package/package.json +3 -1
  311. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__175bef84._.js +0 -3
  312. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__3971eae5._.js +0 -3
  313. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__482b093a._.js +0 -21
  314. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__6bca1621._.js +0 -3
  315. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__87a3475a._.js +0 -3
  316. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__9f0f4c0b._.js +0 -3
  317. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__c1c9f5f5._.js +0 -3
  318. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__c6689757._.js +0 -3
  319. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__cd1fb0a2._.js +0 -4
  320. package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__e2071b2e._.js +0 -3
  321. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__299c81cc._.js +0 -3
  322. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__5ca2e973._.js +0 -3
  323. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__b2fe773d._.js +0 -3
  324. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__e79a982a._.js +0 -7
  325. package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__ff03fc1e._.js +0 -7
  326. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_66209e84._.js +0 -3
  327. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6cd9a5e0._.js +0 -3
  328. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_b483c9fe._.js +0 -3
  329. package/.next/standalone/packages/ui/.next/server/chunks/ssr/_b5040d31._.js +0 -5
  330. package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_9710705b._.js +0 -3
  331. package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_b8ff10b9._.js +0 -3
  332. package/.next/standalone/packages/ui/.next/static/chunks/093ea4b175adb770.js +0 -1
  333. package/.next/standalone/packages/ui/.next/static/chunks/5f97d665a4d9dc62.js +0 -3
  334. package/.next/standalone/packages/ui/.next/static/chunks/9a80c22382ddcfaf.css +0 -1
  335. package/.next/standalone/packages/ui/.next/static/chunks/9b7b7024c39c5f99.js +0 -1
  336. package/.next/standalone/packages/ui/.next/static/chunks/aa47b212786d8695.js +0 -1
  337. package/.next/standalone/packages/ui/.next/static/chunks/ae04dcd433be6dab.js +0 -1
  338. package/.next/standalone/packages/ui/.next/static/chunks/c0fe4c94c7282ac0.js +0 -4
  339. package/.next/standalone/packages/ui/.next/static/chunks/c61cbb6a0ba3b6ab.js +0 -1
  340. package/.next/standalone/packages/ui/.next/static/chunks/d79bf953f0dfb650.js +0 -1
  341. package/.next/standalone/packages/ui/.next/static/chunks/e50fb8d0b728cd35.js +0 -5
  342. package/.next/standalone/packages/ui/.next/static/chunks/e6e238dbf1d3e740.js +0 -1
  343. package/.next/standalone/packages/ui/.next/static/chunks/turbopack-9cc79aa1b34ffcbe.js +0 -3
  344. package/.next/static/chunks/093ea4b175adb770.js +0 -1
  345. package/.next/static/chunks/5f97d665a4d9dc62.js +0 -3
  346. package/.next/static/chunks/9a80c22382ddcfaf.css +0 -1
  347. package/.next/static/chunks/9b7b7024c39c5f99.js +0 -1
  348. package/.next/static/chunks/aa47b212786d8695.js +0 -1
  349. package/.next/static/chunks/ae04dcd433be6dab.js +0 -1
  350. package/.next/static/chunks/c0fe4c94c7282ac0.js +0 -4
  351. package/.next/static/chunks/c61cbb6a0ba3b6ab.js +0 -1
  352. package/.next/static/chunks/d79bf953f0dfb650.js +0 -1
  353. package/.next/static/chunks/e50fb8d0b728cd35.js +0 -5
  354. package/.next/static/chunks/e6e238dbf1d3e740.js +0 -1
  355. package/.next/static/chunks/turbopack-9cc79aa1b34ffcbe.js +0 -3
  356. /package/.next/standalone/packages/ui/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_buildManifest.js +0 -0
  357. /package/.next/standalone/packages/ui/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_clientMiddlewareManifest.json +0 -0
  358. /package/.next/standalone/packages/ui/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_ssgManifest.js +0 -0
  359. /package/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_buildManifest.js +0 -0
  360. /package/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_clientMiddlewareManifest.json +0 -0
  361. /package/.next/static/{C8sZuJV5DQETshOIgjsmH → T1wNN9JmkdwBabQsqL-tC}/_ssgManifest.js +0 -0
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { NextResponse } from 'next/server';
6
6
  import { getSpecsByProjectId } from '@/lib/db/queries';
7
+ import { specsService } from '@/lib/specs/service';
7
8
 
8
9
  export async function GET(
9
10
  request: Request,
@@ -11,6 +12,12 @@ export async function GET(
11
12
  ) {
12
13
  try {
13
14
  const { id } = await params;
15
+
16
+ if (process.env.SPECS_MODE === 'multi-project') {
17
+ const specs = await specsService.getAllSpecs(id);
18
+ return NextResponse.json({ specs });
19
+ }
20
+
14
21
  const specs = await getSpecsByProjectId(id);
15
22
  return NextResponse.json({ specs });
16
23
  } catch (error) {
@@ -0,0 +1,19 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { getStats } from '@/lib/db/service-queries';
3
+
4
+ export async function GET(
5
+ request: Request,
6
+ { params }: { params: Promise<{ id: string }> }
7
+ ) {
8
+ try {
9
+ const { id } = await params;
10
+ const stats = await getStats(id);
11
+ return NextResponse.json({ stats });
12
+ } catch (error) {
13
+ console.error('Error fetching stats:', error);
14
+ return NextResponse.json(
15
+ { error: 'Failed to fetch stats' },
16
+ { status: 500 }
17
+ );
18
+ }
19
+ }
@@ -4,11 +4,28 @@
4
4
 
5
5
  import { NextResponse } from 'next/server';
6
6
  import { getProjects } from '@/lib/db/queries';
7
+ import { projectRegistry } from '@/lib/projects/registry';
7
8
 
8
9
  export async function GET() {
9
10
  try {
11
+ // Check if running in multi-project mode
12
+ if (process.env.SPECS_MODE === 'multi-project') {
13
+ const projects = await projectRegistry.getProjects();
14
+ const recentProjects = await projectRegistry.getRecentProjects();
15
+ const favoriteProjects = await projectRegistry.getFavoriteProjects();
16
+ return NextResponse.json({
17
+ mode: 'multi-project',
18
+ projects,
19
+ recentProjects,
20
+ favoriteProjects
21
+ });
22
+ }
23
+
10
24
  const projects = await getProjects();
11
- return NextResponse.json({ projects });
25
+ return NextResponse.json({
26
+ mode: 'single-project',
27
+ projects
28
+ });
12
29
  } catch (error) {
13
30
  console.error('Error fetching projects:', error);
14
31
  return NextResponse.json(
@@ -17,3 +34,33 @@ export async function GET() {
17
34
  );
18
35
  }
19
36
  }
37
+
38
+ export async function POST(request: Request) {
39
+ try {
40
+ if (process.env.SPECS_MODE !== 'multi-project') {
41
+ return NextResponse.json(
42
+ { error: 'Multi-project mode is not enabled' },
43
+ { status: 400 }
44
+ );
45
+ }
46
+
47
+ const body = await request.json();
48
+ const { path, favorite, color } = body;
49
+
50
+ if (!path) {
51
+ return NextResponse.json(
52
+ { error: 'Project path is required' },
53
+ { status: 400 }
54
+ );
55
+ }
56
+
57
+ const project = await projectRegistry.addProject(path, { favorite, color });
58
+ return NextResponse.json({ project });
59
+ } catch (error) {
60
+ console.error('Error adding project:', error);
61
+ return NextResponse.json(
62
+ { error: error instanceof Error ? error.message : 'Failed to add project' },
63
+ { status: 500 }
64
+ );
65
+ }
66
+ }
@@ -1,6 +1,8 @@
1
1
  'use client';
2
2
 
3
+ import { useState, useEffect } from 'react';
3
4
  import Link from 'next/link';
5
+ import { useProject } from '@/contexts/project-context';
4
6
  import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
5
7
  import { Button } from '@/components/ui/button';
6
8
  import {
@@ -11,7 +13,8 @@ import {
11
13
  LayoutGrid,
12
14
  List,
13
15
  TrendingUp,
14
- Calendar
16
+ Calendar,
17
+ Loader2
15
18
  } from 'lucide-react';
16
19
  import { StatusBadge } from '@/components/status-badge';
17
20
  import { PriorityBadge } from '@/components/priority-badge';
@@ -133,20 +136,78 @@ function ActivityItem({ spec, action, time }: { spec: Spec; action: string; time
133
136
  }
134
137
 
135
138
  export function DashboardClient({ initialSpecs, initialStats }: DashboardClientProps) {
136
- const stats = initialStats;
139
+ const { mode, currentProject, isLoading: isProjectLoading } = useProject();
140
+ const [specs, setSpecs] = useState<Spec[]>(initialSpecs);
141
+ const [stats, setStats] = useState<Stats>(initialStats);
142
+ const [isLoadingData, setIsLoadingData] = useState(false);
143
+
144
+ useEffect(() => {
145
+ if (mode === 'multi-project') {
146
+ if (currentProject) {
147
+ fetchProjectData(currentProject.id);
148
+ } else {
149
+ setSpecs([]);
150
+ setStats({ totalSpecs: 0, completionRate: 0, specsByStatus: [] });
151
+ }
152
+ }
153
+ }, [mode, currentProject]);
154
+
155
+ const fetchProjectData = async (projectId: string) => {
156
+ setIsLoadingData(true);
157
+ try {
158
+ const [specsRes, statsRes] = await Promise.all([
159
+ fetch(`/api/projects/${projectId}/specs`),
160
+ fetch(`/api/projects/${projectId}/stats`)
161
+ ]);
162
+
163
+ if (specsRes.ok && statsRes.ok) {
164
+ const specsData = await specsRes.json();
165
+ const statsData = await statsRes.json();
166
+
167
+ const parsedSpecs = specsData.specs.map((s: any) => ({
168
+ ...s,
169
+ createdAt: s.createdAt ? new Date(s.createdAt) : null,
170
+ updatedAt: s.updatedAt ? new Date(s.updatedAt) : null,
171
+ }));
172
+
173
+ setSpecs(parsedSpecs);
174
+ setStats(statsData.stats);
175
+ }
176
+ } catch (e) {
177
+ console.error(e);
178
+ } finally {
179
+ setIsLoadingData(false);
180
+ }
181
+ };
182
+
183
+ if (mode === 'multi-project' && !currentProject) {
184
+ if (isProjectLoading) {
185
+ return <div className="flex items-center justify-center h-screen"><Loader2 className="animate-spin" /></div>;
186
+ }
187
+ return (
188
+ <div className="flex flex-col items-center justify-center h-[calc(100vh-4rem)] text-center p-8">
189
+ <h2 className="text-2xl font-bold mb-2">Welcome to LeanSpec</h2>
190
+ <p className="text-muted-foreground mb-4">Select a project from the sidebar or create a new one to get started.</p>
191
+ </div>
192
+ );
193
+ }
194
+
195
+ if (isLoadingData) {
196
+ return <div className="flex items-center justify-center h-screen"><Loader2 className="animate-spin" /></div>;
197
+ }
137
198
 
138
199
  // Get specs by status
139
- const inProgressSpecs = initialSpecs
200
+ const inProgressSpecs = specs
140
201
  .filter(spec => spec.status === 'in-progress')
141
202
  .sort((a, b) => (b.specNumber || 0) - (a.specNumber || 0))
142
203
  .slice(0, 5);
143
204
 
144
- const plannedSpecs = initialSpecs
205
+ const plannedSpecs = specs
145
206
  .filter(spec => spec.status === 'planned')
146
207
  .sort((a, b) => (b.specNumber || 0) - (a.specNumber || 0))
147
208
  .slice(0, 5);
148
209
 
149
- const recentlyAdded = initialSpecs
210
+ const recentlyAdded = specs
150
211
  .sort((a, b) => {
151
212
  if (!a.createdAt) return 1;
152
213
  if (!b.createdAt) return -1;
@@ -154,7 +215,7 @@ export function DashboardClient({ initialSpecs, initialStats }: DashboardClientP
154
215
  })
155
216
  .slice(0, 5);
156
217
 
157
- const recentActivity = initialSpecs
218
+ const recentActivity = specs
158
219
  .filter(spec => spec.updatedAt)
159
220
  .sort((a, b) => {
160
221
  if (!a.updatedAt) return 1;
@@ -4,6 +4,7 @@ import { Navigation } from "@/components/navigation";
4
4
  import { MainSidebar } from "@/components/main-sidebar";
5
5
  import { ThemeProvider } from "@/components/theme-provider";
6
6
  import { Toast } from "@/components/ui/toast";
7
+ import { ProjectProvider } from "@/contexts/project-context";
7
8
  import { getSpecs } from "@/lib/db/service-queries";
8
9
 
9
10
  export const metadata: Metadata = {
@@ -56,14 +57,16 @@ export default async function RootLayout({
56
57
  enableSystem
57
58
  disableTransitionOnChange
58
59
  >
59
- <Navigation specs={specsForSearch} />
60
- <div className="flex w-full min-w-0">
61
- <MainSidebar />
62
- <main className="flex-1 min-h-[calc(100vh-3.5rem)] min-w-0 w-full lg:w-[calc(100vw-var(--main-sidebar-width,240px))]">
63
- {children}
64
- </main>
65
- </div>
66
- <Toast />
60
+ <ProjectProvider>
61
+ <Navigation specs={specsForSearch} />
62
+ <div className="flex w-full min-w-0">
63
+ <MainSidebar />
64
+ <main className="flex-1 min-h-[calc(100vh-3.5rem)] min-w-0 w-full lg:w-[calc(100vw-var(--main-sidebar-width,240px))]">
65
+ {children}
66
+ </main>
67
+ </div>
68
+ <Toast />
69
+ </ProjectProvider>
67
70
  </ThemeProvider>
68
71
  </body>
69
72
  </html>
@@ -18,7 +18,7 @@ export default function NotFound() {
18
18
  <Link href="/">Go Home</Link>
19
19
  </Button>
20
20
  <Button variant="outline" asChild>
21
- <Link href="/board">View Board</Link>
21
+ <Link href="/specs">View Specs</Link>
22
22
  </Button>
23
23
  </div>
24
24
  </div>
@@ -0,0 +1,18 @@
1
+ import { ProjectContextSyncer } from './project-context-syncer';
2
+
3
+ export default async function ProjectLayout({
4
+ children,
5
+ params,
6
+ }: {
7
+ children: React.ReactNode;
8
+ params: Promise<{ projectId: string }>;
9
+ }) {
10
+ const { projectId } = await params;
11
+
12
+ return (
13
+ <>
14
+ <ProjectContextSyncer projectId={projectId} />
15
+ {children}
16
+ </>
17
+ );
18
+ }
@@ -0,0 +1,10 @@
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default async function ProjectPage({
4
+ params,
5
+ }: {
6
+ params: Promise<{ projectId: string }>;
7
+ }) {
8
+ const { projectId } = await params;
9
+ redirect(`/projects/${projectId}/specs`);
10
+ }
@@ -0,0 +1,16 @@
1
+ 'use client';
2
+
3
+ import { useEffect } from 'react';
4
+ import { useProject } from '@/contexts/project-context';
5
+
6
+ export function ProjectContextSyncer({ projectId }: { projectId: string }) {
7
+ const { switchProject, currentProject } = useProject();
8
+
9
+ useEffect(() => {
10
+ if (projectId && (!currentProject || currentProject.id !== projectId)) {
11
+ switchProject(projectId).catch(console.error);
12
+ }
13
+ }, [projectId, currentProject, switchProject]);
14
+
15
+ return null;
16
+ }
@@ -0,0 +1,34 @@
1
+ import { notFound } from 'next/navigation';
2
+ import { getSpecById, getSpecsWithSubSpecCount } from '@/lib/db/service-queries';
3
+ import { SpecDetailWrapper } from '@/components/spec-detail-wrapper';
4
+
5
+ export const revalidate = 0; // No caching for local dev
6
+ export const dynamic = 'force-dynamic';
7
+
8
+ export default async function ProjectSpecDetailPage({
9
+ params,
10
+ searchParams
11
+ }: {
12
+ params: Promise<{ projectId: string; specId: string }>;
13
+ searchParams: Promise<{ subspec?: string }>;
14
+ }) {
15
+ const { projectId, specId } = await params;
16
+ const { subspec: currentSubSpec } = await searchParams;
17
+
18
+ const [spec, allSpecs] = await Promise.all([
19
+ getSpecById(specId, projectId),
20
+ getSpecsWithSubSpecCount(projectId)
21
+ ]);
22
+
23
+ if (!spec) {
24
+ notFound();
25
+ }
26
+
27
+ return (
28
+ <SpecDetailWrapper
29
+ spec={spec}
30
+ allSpecs={allSpecs}
31
+ currentSubSpec={currentSubSpec}
32
+ />
33
+ );
34
+ }
@@ -0,0 +1,20 @@
1
+ import { getSpecsWithMetadata, getStats } from '@/lib/db/service-queries';
2
+ import { SpecsClient } from '@/app/specs/specs-client';
3
+
4
+ // Force dynamic rendering
5
+ export const dynamic = 'force-dynamic';
6
+
7
+ export default async function ProjectSpecsPage({
8
+ params,
9
+ }: {
10
+ params: Promise<{ projectId: string }>;
11
+ }) {
12
+ const { projectId } = await params;
13
+
14
+ const [specs, stats] = await Promise.all([
15
+ getSpecsWithMetadata(projectId),
16
+ getStats(projectId),
17
+ ]);
18
+
19
+ return <SpecsClient initialSpecs={specs} initialStats={stats} projectId={projectId} />;
20
+ }
@@ -0,0 +1,156 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import { Plus, Search, FolderOpen, Star, MoreVertical, Trash2 } from 'lucide-react';
5
+ import { useProject } from '@/contexts/project-context';
6
+ import { Button } from '@/components/ui/button';
7
+ import { Input } from '@/components/ui/input';
8
+ import {
9
+ Card,
10
+ CardContent,
11
+ CardDescription,
12
+ CardHeader,
13
+ CardTitle,
14
+ } from '@/components/ui/card';
15
+ import {
16
+ DropdownMenu,
17
+ DropdownMenuContent,
18
+ DropdownMenuItem,
19
+ DropdownMenuTrigger,
20
+ } from '@/components/ui/dropdown-menu';
21
+ import { CreateProjectDialog } from '@/components/create-project-dialog';
22
+ import dayjs from 'dayjs';
23
+ import relativeTime from 'dayjs/plugin/relativeTime';
24
+
25
+ dayjs.extend(relativeTime);
26
+
27
+ export default function ProjectsPage() {
28
+ const { projects, switchProject, toggleFavorite, removeProject } = useProject();
29
+ const [searchQuery, setSearchQuery] = useState('');
30
+ const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
31
+
32
+ const filteredProjects = projects.filter((p) =>
33
+ p.name.toLowerCase().includes(searchQuery.toLowerCase())
34
+ );
35
+
36
+ const handleProjectClick = async (projectId: string) => {
37
+ await switchProject(projectId);
38
+ // Optionally navigate to dashboard, but switchProject might handle it or we stay here
39
+ };
40
+
41
+ return (
42
+ <div className="container max-w-5xl py-8 space-y-8">
43
+ <div className="flex items-center justify-between">
44
+ <div>
45
+ <h1 className="text-3xl font-bold tracking-tight">Projects</h1>
46
+ <p className="text-muted-foreground mt-2">
47
+ Manage your LeanSpec projects and workspaces.
48
+ </p>
49
+ </div>
50
+ <Button onClick={() => setIsCreateDialogOpen(true)}>
51
+ <Plus className="mr-2 h-4 w-4" />
52
+ Add Project
53
+ </Button>
54
+ </div>
55
+
56
+ <div className="flex items-center space-x-2">
57
+ <div className="relative flex-1 max-w-sm">
58
+ <Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
59
+ <Input
60
+ placeholder="Search projects..."
61
+ value={searchQuery}
62
+ onChange={(e) => setSearchQuery(e.target.value)}
63
+ className="pl-8"
64
+ />
65
+ </div>
66
+ </div>
67
+
68
+ <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
69
+ {filteredProjects.map((project) => (
70
+ <Card key={project.id} className="group relative hover:border-primary/50 transition-colors">
71
+ <CardHeader className="pb-4">
72
+ <div className="flex items-start justify-between">
73
+ <div className="flex items-center space-x-2">
74
+ <div
75
+ className="h-8 w-8 rounded-full flex items-center justify-center text-white text-xs font-bold"
76
+ style={{ backgroundColor: project.color || '#666' }}
77
+ >
78
+ {project.name.substring(0, 2).toUpperCase()}
79
+ </div>
80
+ <div className="space-y-1">
81
+ <CardTitle className="text-base leading-none">
82
+ <button
83
+ onClick={() => handleProjectClick(project.id)}
84
+ className="hover:underline focus:outline-none"
85
+ >
86
+ {project.name}
87
+ </button>
88
+ </CardTitle>
89
+ <CardDescription className="text-xs truncate max-w-[150px]">
90
+ {project.path}
91
+ </CardDescription>
92
+ </div>
93
+ </div>
94
+ <DropdownMenu>
95
+ <DropdownMenuTrigger asChild>
96
+ <Button variant="ghost" size="icon" className="h-8 w-8">
97
+ <MoreVertical className="h-4 w-4" />
98
+ <span className="sr-only">Open menu</span>
99
+ </Button>
100
+ </DropdownMenuTrigger>
101
+ <DropdownMenuContent align="end">
102
+ <DropdownMenuItem onClick={() => toggleFavorite(project.id)}>
103
+ <Star className="mr-2 h-4 w-4" />
104
+ {project.favorite ? 'Unfavorite' : 'Favorite'}
105
+ </DropdownMenuItem>
106
+ <DropdownMenuItem className="text-destructive" onClick={() => removeProject(project.id)}>
107
+ <Trash2 className="mr-2 h-4 w-4" />
108
+ Remove
109
+ </DropdownMenuItem>
110
+ </DropdownMenuContent>
111
+ </DropdownMenu>
112
+ </div>
113
+ </CardHeader>
114
+ <CardContent className="pb-4">
115
+ <div className="flex items-center justify-between text-sm text-muted-foreground">
116
+ <div className="flex items-center">
117
+ <FolderOpen className="mr-1 h-3 w-3" />
118
+ <span className="text-xs">Local</span>
119
+ </div>
120
+ {project.lastAccessed && (
121
+ <span className="text-xs">
122
+ Opened {dayjs(project.lastAccessed).fromNow()}
123
+ </span>
124
+ )}
125
+ </div>
126
+ </CardContent>
127
+ {project.favorite && (
128
+ <div className="absolute top-2 right-10 text-yellow-500">
129
+ <Star className="h-4 w-4 fill-current" />
130
+ </div>
131
+ )}
132
+ </Card>
133
+ ))}
134
+
135
+ {filteredProjects.length === 0 && (
136
+ <div className="col-span-full flex flex-col items-center justify-center py-12 text-center border rounded-lg border-dashed">
137
+ <FolderOpen className="h-10 w-10 text-muted-foreground mb-4" />
138
+ <h3 className="text-lg font-medium">No projects found</h3>
139
+ <p className="text-sm text-muted-foreground mt-1 mb-4">
140
+ {searchQuery ? "Try adjusting your search query." : "Get started by adding your first project."}
141
+ </p>
142
+ <Button onClick={() => setIsCreateDialogOpen(true)}>
143
+ <Plus className="mr-2 h-4 w-4" />
144
+ Add Project
145
+ </Button>
146
+ </div>
147
+ )}
148
+ </div>
149
+
150
+ <CreateProjectDialog
151
+ open={isCreateDialogOpen}
152
+ onOpenChange={setIsCreateDialogOpen}
153
+ />
154
+ </div>
155
+ );
156
+ }
@@ -102,12 +102,13 @@ interface Stats {
102
102
  interface SpecsClientProps {
103
103
  initialSpecs: Spec[];
104
104
  initialStats: Stats;
105
+ projectId?: string;
105
106
  }
106
107
 
107
108
  type ViewMode = 'list' | 'board';
108
109
  type SortBy = 'id-desc' | 'id-asc' | 'updated-desc' | 'title-asc';
109
110
 
110
- export function SpecsClient({ initialSpecs }: SpecsClientProps) {
111
+ export function SpecsClient({ initialSpecs, projectId }: SpecsClientProps) {
111
112
  const searchParams = useSearchParams();
112
113
  const router = useRouter();
113
114
 
@@ -147,7 +148,11 @@ export function SpecsClient({ initialSpecs }: SpecsClientProps) {
147
148
  setSpecs((prev) => prev.map(item => item.id === spec.id ? { ...item, status: nextStatus } : item));
148
149
 
149
150
  try {
150
- const response = await fetch(`/api/specs/${encodeURIComponent(spec.specName)}/status`, {
151
+ const url = projectId
152
+ ? `/api/projects/${projectId}/specs/${encodeURIComponent(spec.specName)}/status`
153
+ : `/api/specs/${encodeURIComponent(spec.specName)}/status`;
154
+
155
+ const response = await fetch(url, {
151
156
  method: 'PATCH',
152
157
  headers: {
153
158
  'Content-Type': 'application/json',